Check-in [d692415492]
Not logged in

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

Overview
Comment:merge with trunk
Timelines: family | ancestors | descendants | both | wtf-8-experiment
Files: files | file ages | folders
SHA1: d692415492e734cb61cf1e5d146aca45d7b33df4
User & Date: chw 2020-07-25 05:19:16
Context
2020-07-25
19:24
merge with trunk check-in: d78a1dbb7e user: chw tags: wtf-8-experiment
05:19
merge with trunk check-in: d692415492 user: chw tags: wtf-8-experiment
05:18
improve tcl-fuse Makefile.in check-in: bed12d9ce5 user: chw tags: trunk
2020-07-20
17:12
merge with trunk check-in: 4a764038f2 user: chw tags: wtf-8-experiment
Changes

Changes to jni/sdl2tk/macosx/tkMacOSXDraw.c.

1744
1745
1746
1747
1748
1749
1750

1751
1752
1753
1754
1755
1756
1757
	    CGContextSetLineWidth(dc.context, w);
	    if (gc->line_style != LineSolid) {
		int num = 0;
		char *p = &gc->dashes;
		CGFloat dashOffset = gc->dash_offset;
		CGFloat lengths[10];


		while (p[num] != '\0' && num < 10) {
		    lengths[num] = p[num];
		    num++;
		}
		CGContextSetLineDash(dc.context, dashOffset, lengths, num);
	    }
	    if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {







>







1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
	    CGContextSetLineWidth(dc.context, w);
	    if (gc->line_style != LineSolid) {
		int num = 0;
		char *p = &gc->dashes;
		CGFloat dashOffset = gc->dash_offset;
		CGFloat lengths[10];

		dashOffset -= (gc->line_width % 2) ? 0.5 : 0.0;
		while (p[num] != '\0' && num < 10) {
		    lengths[num] = p[num];
		    num++;
		}
		CGContextSetLineDash(dc.context, dashOffset, lengths, num);
	    }
	    if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {

Changes to jni/sdl2tk/tests/textWind.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

deleteWindows

set fixedFont {"Courier New" -12}
set fixedHeight [font metrics $fixedFont -linespace]
set fixedWidth [font measure $fixedFont m]
set fixedAscent [font metrics $fixedFont -ascent]

# Widget used in almost all tests
set tWidth 30
set tHeight 6







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

deleteWindows

set fixedFont {"Courier" -12}
set fixedHeight [font metrics $fixedFont -linespace]
set fixedWidth [font measure $fixedFont m]
set fixedAscent [font metrics $fixedFont -ascent]

# Widget used in almost all tests
set tWidth 30
set tHeight 6

Changes to jni/topcua/examples/fuse.tcl.

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
139
140
141
142
143
144
145


146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Fuse entry points; the "fs_getattr" function fills
# a cache when an OPCUA variable is referenced.
# Other functions work with cached entries later.

proc fs_getattr {context path} {
    log "getattr $path"
    if {$path eq "/"} {
        return [dict create type directory mode 0755 nlinks 2]
    }
    if {[info exists ::T($path)]} {
	lassign $::T($path) nodeid clspath
	if {[string match "*/Variable" $clspath]} {
	    set now [clock seconds]
	    # Fetch Value attribute into cache, if cache entry doesn't
	    # exist at all, or is not open and older than 10 seconds.
................................................................................
	lassign $::T($path) nodeid clspath
	if {[string match "*/Variable" $clspath]} {
	    return -code error -errorcode [list POSIX ENOENT {}]
	}
	set pattern ${path}/*
    } elseif {$path eq "/"} {
	set pattern /*


    }
    set nsl [llength [split $pattern "/"]]
    set list [list "." ".."]
    foreach name [array names ::T] {
	if {[string match $pattern $name]} {
	    set sl [llength [split $name "/"]]
	    if {$sl == $nsl} {
		lappend list [file tail $name]
	    }
	}
    }
    return $list
}

proc fs_read {context path fileinfo size offset} {
    log "read $path"







|







 







>
>



|
|
|
|
|
<







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
# Fuse entry points; the "fs_getattr" function fills
# a cache when an OPCUA variable is referenced.
# Other functions work with cached entries later.

proc fs_getattr {context path} {
    log "getattr $path"
    if {$path eq "/"} {
	return [dict create type directory mode 0755 nlinks 2]
    }
    if {[info exists ::T($path)]} {
	lassign $::T($path) nodeid clspath
	if {[string match "*/Variable" $clspath]} {
	    set now [clock seconds]
	    # Fetch Value attribute into cache, if cache entry doesn't
	    # exist at all, or is not open and older than 10 seconds.
................................................................................
	lassign $::T($path) nodeid clspath
	if {[string match "*/Variable" $clspath]} {
	    return -code error -errorcode [list POSIX ENOENT {}]
	}
	set pattern ${path}/*
    } elseif {$path eq "/"} {
	set pattern /*
    } else {
	return -code error -errorcode [list POSIX ENOENT {}]
    }
    set nsl [llength [split $pattern "/"]]
    set list [list "." ".."]
    foreach name [lsort [array names ::T $pattern]] {
	set lname [split $name "/"]
	set sl [llength $lname]
	if {$sl == $nsl} {
	    lappend list [lindex $lname end]

	}
    }
    return $list
}

proc fs_read {context path fileinfo size offset} {
    log "read $path"

Changes to jni/topcua/library/topcua.tcl.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
76
77
78
79
80
81
82










83
84
85
86
87
88
89
90
...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
...
589
590
591
592
593
594
595

596
597
598
599
600

601
602
603
604
605
606
607
    # Internal tree walker for "tree" and related procs.

    proc _walk {handle nodeid browsename dispname nodeclass
		    refnodeid typenodeid result {level 0} {path {}}} {
	if {$level > 32} return
	if {[lsearch -exact $path $nodeid] >= 0} return
	upvar $result ret

	lappend ret $level $nodeid $browsename $dispname \
	    $nodeclass $refnodeid $typenodeid
	if {$nodeclass eq "Variable"} return
	incr level
	set path [concat $path $nodeid]
	foreach {n b d c r t} [lsort -stride 6 -index 1 \
		[browse $handle $nodeid Forward /]] {
	    if {$b eq "FolderType"} continue
	    _walk $handle $n $b $d $c $r $t ret $level $path
	}
    }

................................................................................
	set ret {}
	set ref [reftype References]
	if {$root eq {}} {
	    set root [root]
	    set org [reftype Organizes]
	    set type [translate $handle $root \
		/ Types / ObjectTypes / BaseObjectType / FolderType]
        } else {
	    set org $ref
	    if {[catch {read $handle $root DataType} type]} {
		switch [read $handle $root NodeClass] {
		    Object {
			set type [translate $handle [root] \
				/ Types / ObjectTypes / BaseObjectType]
		    }
................................................................................
	set type [lindex $type 0]
	# read BrowseName attribute yields QualifiedName
	set bname [read $handle $root BrowseName]
	# read DisplayName attribute yields LocalizedText
	# but we want the name only here
	set dname [lindex [read $handle $root DisplayName] 1]
	_walk $handle $root $bname $dname Object $org $type ret










	return $ret
    }

    # Similar to tree, but make path like layout as in
    # "browsepath nodeid nodeclasspath refnodeid typenodeid ...", e.g.
    #
    # /Root         i=84 /Object          i=35      i=61
    # /Root/Objects i=85 /Object/Object   i=35      i=61
................................................................................
		}
	    }
	    if {$found} {
		# procname will be method path with prefix stripped
		set b [string range $b [string length $strip] end]
		# the opcua::call object is the method's parent
		set o [parent $handle $n]
	       	# parameter list for proc
		set plist {}
		# arguments (type and name pairs) for opcua::call
		set alist {}
		if {![catch {translate $handle $n / InputArguments} ia]} {
		    # only nodeid needed
		    set ia [lindex $ia 0]
		    # fetch InputArguments
................................................................................
		    break
		}
		# TBD: handle attribute LengthField
		set nstype [$field getAttribute TypeName]
		lassign [split $nstype :] fns type
		if {$type ne ""} {
		    switch -- $fns {
			opc {
			    lappend stf $type
			}
			tns {
			    lappend stf $nstype
			}
			default {
			    # cannot process this struct
................................................................................
	foreach name $stl {
	    set newst {}
	    foreach {type field} $st($name) {
		if {$type eq "CharArray"} {
		    set type "String"
		}
		lassign [split $type :] fns nstype
		if {$fns eq "tns" && $nstype ne ""} {
		    if {($nstype ni $stl) && ($nstype ni $enl)} {
			# in a different namespace, skip
			set newst {}
			break
		    }
		    # check enum field and add integer base type
		    if {$nstype in $enl} {
................................................................................
	    set stn($name) $nodeid
	    set enc($name) $encid
	    set bsn($bsdname) $name
	}
	if {![array exists stn]} {
	    return
	}
	set def {}
	foreach {nsindex uri bsd} [_getbsds $handle] {
	    set data [_readbsd $bsd]
	    array set need {}
	    array set later {}
	    array set have {}
	    foreach {en ed} [dict get $data enums] {
		switch -- [lindex $ed 0] {
................................................................................
		# Robin, let's use the *.bsd name in the opcua::typedef
		set bn $bsn($sn)
		if {[::info exists stn($bn)]} {
		    # verify namespace index
		    if {[scan $stn($sn) "ns=%d;i=%d" ns id] != 2} {
			continue
		    }
	    	    if {$ns != $nsindex} {
			continue
	    	    }
    		}
		set def [list typedef $handle struct $sn $stn($bn) $enc($bn)]
		foreach {type member} $sd {
		    if {[regsub -- ^tns: $type ${nsindex}: type]} {
			# enums have two elements
			scan [lindex $type 0] "%d:%s" tns ttype
			if {![::info exists have($ttype)]} {
			    set ee {}
................................................................................
	    unset -nocomplain need
	    unset -nocomplain later
	    unset -nocomplain have
	}
	# Now typedef all the shiny new things in a transaction:
	# in a client, this replaces former definitions,
	# in a server, this adds new definitions.

	typedef $handle begin
	foreach cmd $defs {
	    {*}$cmd
	}
	typedef $handle commit

    }

    # Internal helper: generate next numeric node identifier
    # given namespace index. In open62541 versions < 1.0 the
    # number is managed internally, otherwise we make it here.

    proc _nodeid {handle nsidx} {







>

|


<







 







|







 







>
>
>
>
>
>
>
>
>
>
|







 







|







 







|







 







|







 







|







 







|

|
|







 







>
|
|
|
|
|
>







13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
    # Internal tree walker for "tree" and related procs.

    proc _walk {handle nodeid browsename dispname nodeclass
		    refnodeid typenodeid result {level 0} {path {}}} {
	if {$level > 32} return
	if {[lsearch -exact $path $nodeid] >= 0} return
	upvar $result ret
	set path [concat $path $nodeid]
	lappend ret $level $nodeid $browsename $dispname \
	    $nodeclass $refnodeid $typenodeid $path
	if {$nodeclass eq "Variable"} return
	incr level

	foreach {n b d c r t} [lsort -stride 6 -index 1 \
		[browse $handle $nodeid Forward /]] {
	    if {$b eq "FolderType"} continue
	    _walk $handle $n $b $d $c $r $t ret $level $path
	}
    }

................................................................................
	set ret {}
	set ref [reftype References]
	if {$root eq {}} {
	    set root [root]
	    set org [reftype Organizes]
	    set type [translate $handle $root \
		/ Types / ObjectTypes / BaseObjectType / FolderType]
	} else {
	    set org $ref
	    if {[catch {read $handle $root DataType} type]} {
		switch [read $handle $root NodeClass] {
		    Object {
			set type [translate $handle [root] \
				/ Types / ObjectTypes / BaseObjectType]
		    }
................................................................................
	set type [lindex $type 0]
	# read BrowseName attribute yields QualifiedName
	set bname [read $handle $root BrowseName]
	# read DisplayName attribute yields LocalizedText
	# but we want the name only here
	set dname [lindex [read $handle $root DisplayName] 1]
	_walk $handle $root $bname $dname Object $org $type ret
	# remove duplicates by path
	array set x {}
	set nodup {}
	foreach {l n b d c r t path} $ret {
	    if {[::info exists x($path)]} {
		continue
	    }
	    incr x($path)
	    lappend nodup $l $n $b $d $c $r $t
	}
	return $nodup
    }

    # Similar to tree, but make path like layout as in
    # "browsepath nodeid nodeclasspath refnodeid typenodeid ...", e.g.
    #
    # /Root         i=84 /Object          i=35      i=61
    # /Root/Objects i=85 /Object/Object   i=35      i=61
................................................................................
		}
	    }
	    if {$found} {
		# procname will be method path with prefix stripped
		set b [string range $b [string length $strip] end]
		# the opcua::call object is the method's parent
		set o [parent $handle $n]
		# parameter list for proc
		set plist {}
		# arguments (type and name pairs) for opcua::call
		set alist {}
		if {![catch {translate $handle $n / InputArguments} ia]} {
		    # only nodeid needed
		    set ia [lindex $ia 0]
		    # fetch InputArguments
................................................................................
		    break
		}
		# TBD: handle attribute LengthField
		set nstype [$field getAttribute TypeName]
		lassign [split $nstype :] fns type
		if {$type ne ""} {
		    switch -- $fns {
			opc - ua {
			    lappend stf $type
			}
			tns {
			    lappend stf $nstype
			}
			default {
			    # cannot process this struct
................................................................................
	foreach name $stl {
	    set newst {}
	    foreach {type field} $st($name) {
		if {$type eq "CharArray"} {
		    set type "String"
		}
		lassign [split $type :] fns nstype
		if {$nstype ne "" && $fns eq "tns"} {
		    if {($nstype ni $stl) && ($nstype ni $enl)} {
			# in a different namespace, skip
			set newst {}
			break
		    }
		    # check enum field and add integer base type
		    if {$nstype in $enl} {
................................................................................
	    set stn($name) $nodeid
	    set enc($name) $encid
	    set bsn($bsdname) $name
	}
	if {![array exists stn]} {
	    return
	}
	set defs {}
	foreach {nsindex uri bsd} [_getbsds $handle] {
	    set data [_readbsd $bsd]
	    array set need {}
	    array set later {}
	    array set have {}
	    foreach {en ed} [dict get $data enums] {
		switch -- [lindex $ed 0] {
................................................................................
		# Robin, let's use the *.bsd name in the opcua::typedef
		set bn $bsn($sn)
		if {[::info exists stn($bn)]} {
		    # verify namespace index
		    if {[scan $stn($sn) "ns=%d;i=%d" ns id] != 2} {
			continue
		    }
		    if {$ns != $nsindex} {
			continue
		    }
		}
		set def [list typedef $handle struct $sn $stn($bn) $enc($bn)]
		foreach {type member} $sd {
		    if {[regsub -- ^tns: $type ${nsindex}: type]} {
			# enums have two elements
			scan [lindex $type 0] "%d:%s" tns ttype
			if {![::info exists have($ttype)]} {
			    set ee {}
................................................................................
	    unset -nocomplain need
	    unset -nocomplain later
	    unset -nocomplain have
	}
	# Now typedef all the shiny new things in a transaction:
	# in a client, this replaces former definitions,
	# in a server, this adds new definitions.
	if {[llength $defs]} {
	    typedef $handle begin
	    foreach cmd $defs {
		{*}$cmd
	    }
	    typedef $handle commit
	}
    }

    # Internal helper: generate next numeric node identifier
    # given namespace index. In open62541 versions < 1.0 the
    # number is managed internally, otherwise we make it here.

    proc _nodeid {handle nsidx} {

Changes to jni/topcua/topcua.c.

332
333
334
335
336
337
338






339
340
341
342
343
344



345
346
347
348
349
350
351
...
355
356
357
358
359
360
361









362
363
364
365
366
367
368
...
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
....
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
....
8032
8033
8034
8035
8036
8037
8038

8039
8040
8041
8042
8043
8044
8045
8046
    "Historizing", "Executable", "UserExecutable", NULL
};

/*
 * ReferenceTypes and their NodeIds.
 */







#ifndef UA_NS0ID_HASPUBSUBCONNECTION
#define UA_NS0ID_HASPUBSUBCONNECTION 14476
#endif
#ifndef UA_NS0ID_DATASETTOWRITER
#define UA_NS0ID_DATASETTOWRITER 14936
#endif



#ifndef UA_NS0ID_HASDATASETWRITER
#define UA_NS0ID_HASDATASETWRITER 15296
#endif
#ifndef UA_NS0ID_HASDATASETREADER
#define UA_NS0ID_HASDATASETREADER 15297
#endif
#ifndef UA_NS0ID_HASALARMSUPPRESSIONGROUP
................................................................................
#define UA_NS0ID_ALARMGROUPMEMBER 16362
#endif
#ifndef UA_NS0ID_HASEFFECTDISABLE
#define UA_NS0ID_HASEFFECTDISABLE 17276
#endif
#ifndef UA_NS0ID_HASEFFECTENABLE
#define UA_NS0ID_HASEFFECTENABLE 17983









#endif
#ifndef UA_NS0ID_HASEFFECTSUPPRESSED
#define US_NS0ID_HASEFFECTSUPPRESSED 17984
#endif
#ifndef UA_NS0ID_HASEFFECTUNSUPPRESSED
#define UA_NS0ID_HASEFFECTUNSUPPRESSED 17985
#endif
................................................................................
    { "HasNotifier", UA_NS0ID_HASNOTIFIER },
    { "HasOrderedComponent", UA_NS0ID_HASORDEREDCOMPONENT },
    { "FromState", UA_NS0ID_FROMSTATE },
    { "ToState", UA_NS0ID_TOSTATE },
    { "HasCause", UA_NS0ID_HASCAUSE },
    { "HasEffect", UA_NS0ID_HASEFFECT },
    { "HasHistoricalConfiguration", UA_NS0ID_HASHISTORICALCONFIGURATION },



    { "HasSubStateMachine", UA_NS0ID_HASSUBSTATEMACHINE },
    { "AlwaysGeneratesEvent", UA_NS0ID_ALWAYSGENERATESEVENT },
    { "HasTrueSubState", UA_NS0ID_HASTRUESUBSTATE },
    { "HasFalseSubState", UA_NS0ID_HASFALSESUBSTATE },
    { "HasCondition", UA_NS0ID_HASCONDITION },
    { "HasPubSubConnection", UA_NS0ID_HASPUBSUBCONNECTION },
    { "DataSetToWriter", UA_NS0ID_DATASETTOWRITER },

    { "HasDataSetWriter", UA_NS0ID_HASDATASETWRITER },
    { "HasDataSetReader", UA_NS0ID_HASDATASETREADER },
    { "HasAlarmSuppressionGroup", UA_NS0ID_HASALARMSUPPRESSIONGROUP },
    { "AlarmGroupMember", UA_NS0ID_ALARMGROUPMEMBER },
    { "HasEffectDisable", UA_NS0ID_HASEFFECTDISABLE },

    { "HasEffectEnable", UA_NS0ID_HASEFFECTENABLE },


    { "HasEffectSuppressed", UA_NS0ID_HASEFFECTSUPPRESSED },
    { "HasEffectUnsuppressed", UA_NS0ID_HASEFFECTUNSUPPRESSED }
};
 
#if (UA_OPEN62541_VER_MAJOR >= 1)
/*
 *-------------------------------------------------------------------------
................................................................................
	    br.results[0].continuationPoint = UA_BYTESTRING_NULL;
	}
	UA_BrowseResponse_deleteMembers(&br);
    } else {
	UA_BrowseResult br;

	br = UA_Server_browse(uah->server,
			      brq.requestedMaxReferencesPerNode = 0,
			      brq.nodesToBrowse);
	for (j = 0; j < br.referencesSize; j++) {
		AddRefDescrToList(uai, list, &br.references[j]);
	}
	cp = br.continuationPoint;
	br.continuationPoint = UA_BYTESTRING_NULL;
	UA_BrowseResult_deleteMembers(&br);
    }
    UA_BrowseRequest_deleteMembers(&brq);
    while (cp.length > 0) {
................................................................................
	UA_TYPES_INT16, UA_TYPES_UINT16, UA_TYPES_INT32,
	UA_TYPES_UINT32, UA_TYPES_INT64, UA_TYPES_UINT64,
	UA_TYPES_FLOAT, UA_TYPES_DOUBLE, UA_TYPES_STRING,
	UA_TYPES_DATETIME, UA_TYPES_GUID, UA_TYPES_BYTESTRING,
	UA_TYPES_XMLELEMENT, UA_TYPES_NODEID, UA_TYPES_EXPANDEDNODEID,
	UA_TYPES_STATUSCODE, UA_TYPES_QUALIFIEDNAME,
	UA_TYPES_LOCALIZEDTEXT, UA_TYPES_EXTENSIONOBJECT,

	UA_TYPES_DATAVALUE, UA_TYPES_ARGUMENT, UA_TYPES_DIAGNOSTICINFO
    };

    /*
     * Aliased types as found with
     *   grep "#define.*UA_TYPES_.*UA_TYPES_" open62541/open62541.h
     */
    static const struct {







>
>
>
>
>
>






>
>
>







 







>
>
>
>
>
>
>
>
>







 







>
>
>







>





>

>
>







 







|


|







 







>
|







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
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
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
....
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
....
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
    "Historizing", "Executable", "UserExecutable", NULL
};

/*
 * ReferenceTypes and their NodeIds.
 */

#ifndef UA_NS0ID_HASARGUMENTDESCRIPTION
#define UA_NS0ID_HASARGUMENTDESCRIPTION 129
#endif
#ifndef UA_NS0ID_HASOPTIONALINPUTARGUMENTDESCRIPTION
#define UA_NS0ID_HASOPTIONALINPUTARGUMENTDESCRIPTION 131
#endif
#ifndef UA_NS0ID_HASPUBSUBCONNECTION
#define UA_NS0ID_HASPUBSUBCONNECTION 14476
#endif
#ifndef UA_NS0ID_DATASETTOWRITER
#define UA_NS0ID_DATASETTOWRITER 14936
#endif
#ifndef UA_NS0ID_HASGUARD
#define UA_NS0ID_HASGUARD 15112
#endif
#ifndef UA_NS0ID_HASDATASETWRITER
#define UA_NS0ID_HASDATASETWRITER 15296
#endif
#ifndef UA_NS0ID_HASDATASETREADER
#define UA_NS0ID_HASDATASETREADER 15297
#endif
#ifndef UA_NS0ID_HASALARMSUPPRESSIONGROUP
................................................................................
#define UA_NS0ID_ALARMGROUPMEMBER 16362
#endif
#ifndef UA_NS0ID_HASEFFECTDISABLE
#define UA_NS0ID_HASEFFECTDISABLE 17276
#endif
#ifndef UA_NS0ID_HASEFFECTENABLE
#define UA_NS0ID_HASEFFECTENABLE 17983
#endif
#ifndef UA_NS0ID_HASDICTIONARYENTRY
#define UA_NS0ID_HASDICTIONARYENTRY 17597
#endif
#ifndef UA_NS0ID_HASINTERFACE
#define UA_NS0ID_HASINTERFACE 17603
#endif
#ifndef UA_NS0ID_HASADDIN
#define UA_NS0ID_HASADDIN 17604
#endif
#ifndef UA_NS0ID_HASEFFECTSUPPRESSED
#define US_NS0ID_HASEFFECTSUPPRESSED 17984
#endif
#ifndef UA_NS0ID_HASEFFECTUNSUPPRESSED
#define UA_NS0ID_HASEFFECTUNSUPPRESSED 17985
#endif
................................................................................
    { "HasNotifier", UA_NS0ID_HASNOTIFIER },
    { "HasOrderedComponent", UA_NS0ID_HASORDEREDCOMPONENT },
    { "FromState", UA_NS0ID_FROMSTATE },
    { "ToState", UA_NS0ID_TOSTATE },
    { "HasCause", UA_NS0ID_HASCAUSE },
    { "HasEffect", UA_NS0ID_HASEFFECT },
    { "HasHistoricalConfiguration", UA_NS0ID_HASHISTORICALCONFIGURATION },
    { "HasArgumentDescription", UA_NS0ID_HASARGUMENTDESCRIPTION },
    { "HasOptionalInputArgumentDescription",
	    UA_NS0ID_HASOPTIONALINPUTARGUMENTDESCRIPTION },
    { "HasSubStateMachine", UA_NS0ID_HASSUBSTATEMACHINE },
    { "AlwaysGeneratesEvent", UA_NS0ID_ALWAYSGENERATESEVENT },
    { "HasTrueSubState", UA_NS0ID_HASTRUESUBSTATE },
    { "HasFalseSubState", UA_NS0ID_HASFALSESUBSTATE },
    { "HasCondition", UA_NS0ID_HASCONDITION },
    { "HasPubSubConnection", UA_NS0ID_HASPUBSUBCONNECTION },
    { "DataSetToWriter", UA_NS0ID_DATASETTOWRITER },
    { "HasGuard", UA_NS0ID_HASGUARD },
    { "HasDataSetWriter", UA_NS0ID_HASDATASETWRITER },
    { "HasDataSetReader", UA_NS0ID_HASDATASETREADER },
    { "HasAlarmSuppressionGroup", UA_NS0ID_HASALARMSUPPRESSIONGROUP },
    { "AlarmGroupMember", UA_NS0ID_ALARMGROUPMEMBER },
    { "HasEffectDisable", UA_NS0ID_HASEFFECTDISABLE },
    { "HasDictionaryEntry", UA_NS0ID_HASDICTIONARYENTRY },
    { "HasEffectEnable", UA_NS0ID_HASEFFECTENABLE },
    { "HasInterface", UA_NS0ID_HASINTERFACE },
    { "HasAddin", UA_NS0ID_HASADDIN },
    { "HasEffectSuppressed", UA_NS0ID_HASEFFECTSUPPRESSED },
    { "HasEffectUnsuppressed", UA_NS0ID_HASEFFECTUNSUPPRESSED }
};
 
#if (UA_OPEN62541_VER_MAJOR >= 1)
/*
 *-------------------------------------------------------------------------
................................................................................
	    br.results[0].continuationPoint = UA_BYTESTRING_NULL;
	}
	UA_BrowseResponse_deleteMembers(&br);
    } else {
	UA_BrowseResult br;

	br = UA_Server_browse(uah->server,
			      brq.requestedMaxReferencesPerNode,
			      brq.nodesToBrowse);
	for (j = 0; j < br.referencesSize; j++) {
	    AddRefDescrToList(uai, list, &br.references[j]);
	}
	cp = br.continuationPoint;
	br.continuationPoint = UA_BYTESTRING_NULL;
	UA_BrowseResult_deleteMembers(&br);
    }
    UA_BrowseRequest_deleteMembers(&brq);
    while (cp.length > 0) {
................................................................................
	UA_TYPES_INT16, UA_TYPES_UINT16, UA_TYPES_INT32,
	UA_TYPES_UINT32, UA_TYPES_INT64, UA_TYPES_UINT64,
	UA_TYPES_FLOAT, UA_TYPES_DOUBLE, UA_TYPES_STRING,
	UA_TYPES_DATETIME, UA_TYPES_GUID, UA_TYPES_BYTESTRING,
	UA_TYPES_XMLELEMENT, UA_TYPES_NODEID, UA_TYPES_EXPANDEDNODEID,
	UA_TYPES_STATUSCODE, UA_TYPES_QUALIFIEDNAME,
	UA_TYPES_LOCALIZEDTEXT, UA_TYPES_EXTENSIONOBJECT,
	UA_TYPES_DATAVALUE, UA_TYPES_VARIANT,
	UA_TYPES_ARGUMENT, UA_TYPES_DIAGNOSTICINFO
    };

    /*
     * Aliased types as found with
     *   grep "#define.*UA_TYPES_.*UA_TYPES_" open62541/open62541.h
     */
    static const struct {

Changes to undroid/cawt/CawtExcel/excelBasic.tcl.

3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
            if { $numVals < $len } {
                set len $numVals
            }
        }

        set cellId [Excel SelectRangeByIndex $worksheetId \
                    $row $startCol $row [expr {$startCol + $len -1}]]
        Excel SetRangeValues $cellId $valList
        Cawt Destroy $cellId
    }

    proc GetRowValues { worksheetId row { startCol 0 } { numVals 0 } } {
        # Return row values as a Tcl list.
        #
        # worksheetId - Identifier of the worksheet.







|







3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
            if { $numVals < $len } {
                set len $numVals
            }
        }

        set cellId [Excel SelectRangeByIndex $worksheetId \
                    $row $startCol $row [expr {$startCol + $len -1}]]
        Excel SetRangeValues $cellId [list $valList]
        Cawt Destroy $cellId
    }

    proc GetRowValues { worksheetId row { startCol 0 } { numVals 0 } } {
        # Return row values as a Tcl list.
        #
        # worksheetId - Identifier of the worksheet.

Changes to undroid/cawt/CawtExcel/excelCsv.tcl.

195
196
197
198
199
200
201










202
203
204
205
206
207
208
        set matrixList {}
        set rowCount 1

        set catchVal [catch {open $csvFileName r} fp]
        if { $catchVal != 0 } {
            error "Could not open file \"$csvFileName\" for reading."
        }











        while { [gets $fp row] >= 0 } {
            if { $rowCount <= $numHeaderRows && ! $useHeader } {
                incr rowCount
                continue
            }








>
>
>
>
>
>
>
>
>
>







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
        set matrixList {}
        set rowCount 1

        set catchVal [catch {open $csvFileName r} fp]
        if { $catchVal != 0 } {
            error "Could not open file \"$csvFileName\" for reading."
        }
        fconfigure $fp -translation binary

        # Read some bytes and search for \r\n to detect a DOS file.
        set test [read $fp 4096]
        if { [string match "*\r\n*" $test] } {
            fconfigure $fp -translation crlf
        } else {
            fconfigure $fp -translation lf
        }
        seek $fp 0

        while { [gets $fp row] >= 0 } {
            if { $rowCount <= $numHeaderRows && ! $useHeader } {
                incr rowCount
                continue
            }

Changes to undroid/cawt/CawtOffice/officeBasic.tcl.

2
3
4
5
6
7
8

9

10
11
12
13
14
15
16
17




18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
...
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
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# Distributed under BSD license.

namespace eval Office {

    namespace ensemble create

    namespace export AddMacro

    namespace export ColorToRgb

    namespace export GetActivePrinter
    namespace export GetApplicationId
    namespace export GetApplicationName
    namespace export GetApplicationVersion
    namespace export GetDocumentProperties
    namespace export GetDocumentProperty
    namespace export GetInstallationPath
    namespace export GetOfficeType




    namespace export GetStartupPath
    namespace export GetTemplatesPath
    namespace export GetUserLibraryPath
    namespace export GetUserName
    namespace export GetUserPath
    namespace export IsApplicationId
    namespace export RgbToColor
    namespace export RunMacro
    namespace export SetDocumentProperty
    namespace export SetPrinterCommunication

    namespace export ShowAlerts

    variable _ruff_preamble {
        The `Office` namespace provides commands for basic Office automation functionality.
    }

    proc RgbToColor { r g b } {
................................................................................
                set alertLevel [expr $Word::wdAlertsAll]
            } else {
                set alertLevel [expr 1]
            }
        } else {
            set alertLevel [expr 0]
        }
        $appId DisplayAlerts $alertLevel
    }

    proc IsApplicationId { objId } {
        # Check, if Office object is an application identifier.
        #
        # objId - The identifier of an Office object.
        #
................................................................................
        #
        # Returns no value.
        #
        # See also: GetActivePrinter

        if { ! [Office IsApplicationId $objId] } {
            set appId [Office GetApplicationId $objId]
            catch {$appId PrintCommunication [Cawt TclBool $onOff]}
            Cawt Destroy $appId
        } else {
            catch {$objId PrintCommunication [Cawt TclBool $onOff]}
        }
    }

    proc GetActivePrinter { appId } {
        # Get the name of the active printer.
        #
        # appId - The application identifier.
................................................................................
        }
    }

    proc GetDocumentProperties { objId { type "" } } {
        # Get document property names as a list.
        #
        # objId - The identifier of an Office object (Workbook, Document, Presentation).
        # type  - Type of document properties (`Builtin` or `Custom`).
        #         If type is not specified or the empty string, both types
        #         of document properties are included in the list.
        #
        # Returns a sorted Tcl list containing the names of all properties
        # of the specified type.
        #
        # See also: GetDocumentProperty SetDocumentProperty


        set propsBuiltin [$objId BuiltinDocumentProperties]
        set propsCustom  [$objId CustomDocumentProperties]

        set propList [list]
        if { $type eq "Builtin" || $type eq "" } {
            $propsBuiltin -iterate prop {
................................................................................
            }
        }
        Cawt Destroy $propsBuiltin
        Cawt Destroy $propsCustom
        return [lsort -dictionary $propList]
    }



































































































    proc _GetPropertyValue { propertyId } {










        set retVal [catch {$propertyId Value} propVal]
        if { $retVal == 0 } {
            return $propVal
        } else {
            return "N/A"
        }
    }













































    proc GetDocumentProperty { objId propertyName } {
        # Get the value of a document property.
        #
        # objId        - The identifier of an Office object (Workbook, Document, Presentation).
        # propertyName - The name of the property.

        #





        # Returns the value of specified property.
        # If the property value is not set or an invalid property name is given,
        # the string `N/A` is returned.

        #
        # See also: GetDocumentProperties SetDocumentProperty













        set properties [Office GetDocumentProperties $objId]
        if { [lsearch $properties $propertyName] >= 0 } {

            set propsBuiltin [$objId BuiltinDocumentProperties]
            set retVal [catch {$propsBuiltin -get Item $propertyName} property]
            Cawt Destroy $propsBuiltin
            if { $retVal != 0 } {




                set propsCustom  [$objId CustomDocumentProperties]
                set retVal [catch {$propsCustom -get Item $propertyName} property]
                Cawt Destroy $propsCustom
                if { $retVal != 0 } {
                    set propertyValue "N/A"
                } else {
                    set propertyValue [_GetPropertyValue $property]
                    Cawt Destroy $property
                }
            } else {
                set propertyValue [_GetPropertyValue $property]
                Cawt Destroy $property
            }
        } else {

            error "GetDocumentProperty: \"$propertyName\" is not a valid property name."




















        }
        return $propertyValue
    }

    proc SetDocumentProperty { objId propertyName propertyValue } {
        # Set the value of a document property.
        #
        # objId         - The identifier of an Office object (Workbook, Document, Presentation).
        # propertyName  - The name of the property to set.
        # propertyValue - The value for the property as string.


        #
        # Returns no value.
        #
        # If the property name is a builtin property, it's value is set.
        # Otherwise either a new custom property is generated and it's value set or,
        # if the custom property already exists, only it's value is set.
        #
        # See also: GetDocumentProperties GetDocumentProperty

        set properties [Office GetDocumentProperties $objId "Builtin"]
        if { [lsearch -exact $properties $propertyName] >= 0 } {
            set propsBuiltin [$objId BuiltinDocumentProperties]
            $propsBuiltin -set Item $propertyName $propertyValue
            Cawt Destroy $propsBuiltin
        } else {
            set properties [Office GetDocumentProperties $objId "Custom"]
            set propsCustom [$objId CustomDocumentProperties]
            if { [lsearch -exact $properties $propertyName] >= 0 } {
                $propsCustom -set Item $propertyName $propertyValue
            } else {
                $propsCustom Add $propertyName [Cawt TclBool false] 4 $propertyValue
            }
            Cawt Destroy $propsCustom
        }
    }

    proc GetOfficeType { fileName } {
        # Get the Office type of a file.
        #
        # fileName - File name.
        #
................................................................................
                default {
                    error "AddMacro: Unknown key \"$key\" specified" 
                }
            }
        }

        if { $fileName ne "" } {
            set catchVal [catch { $appId -with { VBE ActiveVBProject VBComponents } Import $fileName }]
            if { $catchVal } {
                error "AddMacro: Trust Access to the VBA project object model must be enabled."
            }
        } elseif { $codeStr ne "" } {
            set vbext_ct_StdModule [expr int(1)]
            set catchVal [catch { $appId -with { VBE ActiveVBProject VBComponents } Add $vbext_ct_StdModule } module]
            if { $catchVal } {
                error "AddMacro: Trust Access to the VBA project object model must be enabled."
            }
            $module -with { CodeModule } AddFromString $codeStr
        } else {
            error "AddMacro: Neither \"-file\" nor \"-code\" option specified." 
        }
................................................................................
        # Returns an empty string, if the macro is a procedure (Sub).
        # If the macro is a Function, the return value of the function is returned.
        # An error is thrown, if the macro does not exist or the execution of the 
        # macro fails.
        #
        # See also: AddMacro

        set retVal [catch { $appId Run $macroName {*}$args } val]
        if { $retVal == 0 } {
            return $val
        } else {
            error "RunMacro: $val"
        }
    }
}







>

>








>
>
>
>










>







 







|







 







|


|







 







|
|





|
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|



>

>
>
>
>
>
|
<
<
>

<
>
>

>
>
>
>
>
>
>
>
>
>
|

>
|
|
|
|
>
>
>
>



|
<
<
<
|

<
<
<

<
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|
>
>



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<







 







|





|







 







|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
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
...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# Distributed under BSD license.

namespace eval Office {

    namespace ensemble create

    namespace export AddMacro
    namespace export AddProperty
    namespace export ColorToRgb
    namespace export DeleteProperty
    namespace export GetActivePrinter
    namespace export GetApplicationId
    namespace export GetApplicationName
    namespace export GetApplicationVersion
    namespace export GetDocumentProperties
    namespace export GetDocumentProperty
    namespace export GetInstallationPath
    namespace export GetOfficeType
    namespace export GetProperty
    namespace export GetPropertyName
    namespace export GetPropertyType
    namespace export GetPropertyValue
    namespace export GetStartupPath
    namespace export GetTemplatesPath
    namespace export GetUserLibraryPath
    namespace export GetUserName
    namespace export GetUserPath
    namespace export IsApplicationId
    namespace export RgbToColor
    namespace export RunMacro
    namespace export SetDocumentProperty
    namespace export SetPrinterCommunication
    namespace export SetPropertyValue
    namespace export ShowAlerts

    variable _ruff_preamble {
        The `Office` namespace provides commands for basic Office automation functionality.
    }

    proc RgbToColor { r g b } {
................................................................................
                set alertLevel [expr $Word::wdAlertsAll]
            } else {
                set alertLevel [expr 1]
            }
        } else {
            set alertLevel [expr 0]
        }
        $appId -call DisplayAlerts $alertLevel
    }

    proc IsApplicationId { objId } {
        # Check, if Office object is an application identifier.
        #
        # objId - The identifier of an Office object.
        #
................................................................................
        #
        # Returns no value.
        #
        # See also: GetActivePrinter

        if { ! [Office IsApplicationId $objId] } {
            set appId [Office GetApplicationId $objId]
            catch {$appId -call PrintCommunication [Cawt TclBool $onOff]}
            Cawt Destroy $appId
        } else {
            catch {$objId -call PrintCommunication [Cawt TclBool $onOff]}
        }
    }

    proc GetActivePrinter { appId } {
        # Get the name of the active printer.
        #
        # appId - The application identifier.
................................................................................
        }
    }

    proc GetDocumentProperties { objId { type "" } } {
        # Get document property names as a list.
        #
        # objId - The identifier of an Office object (Workbook, Document, Presentation).
        # type  - Type of document properties as string: `Builtin` or `Custom`.
        #         If `type` is not specified or the empty string, both types
        #         of document properties are included in the list.
        #
        # Returns a sorted Tcl list containing the names of all properties
        # of the specified type.
        #
        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetProperty DeleteProperty
        #           GetPropertyName GetPropertyType GetPropertyValue SetPropertyValue

        set propsBuiltin [$objId BuiltinDocumentProperties]
        set propsCustom  [$objId CustomDocumentProperties]

        set propList [list]
        if { $type eq "Builtin" || $type eq "" } {
            $propsBuiltin -iterate prop {
................................................................................
            }
        }
        Cawt Destroy $propsBuiltin
        Cawt Destroy $propsCustom
        return [lsort -dictionary $propList]
    }

    proc AddProperty { objId propertyName args } {
        # Add a custom document property.
        #
        # objId        - The identifier of an Office object (Workbook, Document, Presentation).
        # propertyName - The name of the new custom property.
        # args         - Options described below.
        #
        # -type <enum> -      The type (string, int, bool, date, float) of the property.
        #                     Enumeration of type [Enum::MsoDocProperties].
        #                     If not specified, the property is of type `msoPropertyTypeString`.
        # -value <val>      - Value of the new property. The specified value must match the
        #                     specified type. If not specified, the value is set to the empty
        #                     string for string properties and to zero for all other property types.
        # -overwrite <bool> - If a property with given name already exists, the property is either
        #                     replaced (`-overwrite true`) or an error is thrown 
        #                     (`-overwrite false`). If not specified, overwriting is disabled.
        #
        # Returns the identifier of the new property or an error depending on the setting of
        # option `-overwrite`.
        #
        # See also: SetDocumentProperty GetDocumentProperty GetProperty GetDocumentProperties
        #           GetPropertyName GetPropertyType GetPropertyValue SetPropertyValue DeleteProperty

        set propertyType [Office GetEnum msoPropertyTypeString] 
        set overwrite    false
        foreach { key value } $args {
            if { $value eq "" } {
                error "AddProperty: No value specified for key \"$key\""
            }
            switch -exact -nocase -- $key {
                "-type"      { set propertyType [Office GetEnum $value] }
                "-value"     { set propertyValue $value }
                "-overwrite" { set overwrite $value }
                default  { error "AddProperty: Unknown key \"$key\" specified" }
            }
        }

        if { ! [info exists propertyValue] } {
            if { $propertyType == $::Office::msoPropertyTypeString } {
                set propertyValue ""
            } else {
                set propertyValue 0
            }
        }
        switch -- [Office GetEnumName "MsoDocProperties" $propertyType] {
            "msoPropertyTypeBoolean" { set val [Cawt TclBool $propertyValue] }
            "msoPropertyTypeString"  { set val [Cawt TclString $propertyValue] }
            "msoPropertyTypeNumber"  { set val [expr { int ($propertyValue) }] }
            "msoPropertyTypeDate"    { set val [expr { double ($propertyValue) }] }
            "msoPropertyTypeFloat"   { set val [expr { double ($propertyValue) }] }
            default { error "AddProperty: Unknown property type \"$propertyType\"" }
        }
        set retVal [catch {Office GetProperty $objId $propertyName -type "Custom"} propertyId]
        if { $retVal == 0 } {
            if { $overwrite } {
                Office DeleteProperty $propertyId
            } else {
                error "AddProperty: Property \"$propertyName\" already exists"
            }
        }
        set propsCustom [$objId CustomDocumentProperties]
        set propertyId [$propsCustom -call Add $propertyName [Cawt TclBool false] $propertyType $propertyValue]
        Cawt Destroy $propsCustom
        return $propertyId
    }

    proc DeleteProperty { propertyId } {
        # Delete a document property.
        #
        # propertyId - Identifier of the Office property.
        #
        # Returns no value.
        #
        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetProperty GetPropertyName
        #           GetPropertyType GetPropertyValue SetPropertyValue GetDocumentProperties

        $propertyId -call Delete
        Cawt Destroy $propertyId
    }

    proc GetPropertyName { propertyId } {
        # Get the name of a document property.
        #
        # propertyId - Identifier of the Office property.
        #
        # Returns the name of the property as string.
        #
        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetProperty DeleteProperty
        #           GetPropertyType GetPropertyValue SetPropertyValue GetDocumentProperties

        set retVal [catch {$propertyId Name} propName]
        if { $retVal == 0 } {
            return $propName
        } else {
            return "N/A"
        }
    }

    proc GetPropertyValue { propertyId } {
        # Get the value of a document property.
        #
        # propertyId - Identifier of the Office property.
        #
        # Returns the value of the property.
        # If the property value is not set, the string `N/A` is returned.
        #
        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetProperty DeleteProperty
        #           GetPropertyName GetPropertyType SetPropertyValue GetDocumentProperties

        set retVal [catch {$propertyId Value} propVal]
        if { $retVal == 0 } {
            return $propVal
        } else {
            return "N/A"
        }
    }
 
    proc SetPropertyValue { propertyId propertyValue } {
        # Set the value of a document property.
        #
        # propertyId    - Identifier of the Office property.
        # propertyValue - The value for the property.
        #                 The specified value must match the type of the property,
        #                 see [GetPropertyType].
        #
        # Returns no value.
        #
        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetProperty DeleteProperty
        #           GetPropertyName GetPropertyType GetPropertyValue GetDocumentProperties

        set propertyType [Office GetPropertyType $propertyId]
        switch -- $propertyType {
            "msoPropertyTypeBoolean" { set val [Cawt TclBool $propertyValue] }
            "msoPropertyTypeString"  { set val [Cawt TclString $propertyValue] }
            "msoPropertyTypeNumber"  { set val [expr { int ($propertyValue) }] }
            "msoPropertyTypeDate"    { set val [expr { double ($propertyValue) }] }
            "msoPropertyTypeFloat"   { set val [expr { double ($propertyValue) }] }
            default { error "SetPropertyValue: Unknown property type \"$propertyType\"" }
        }
        $propertyId Value $val
    }

    proc GetPropertyType { propertyId } {
        # Get the type of a document property.
        #
        # propertyId - Identifier of the Office property.
        #
        # Returns the type of the property as enumeration string.
        # The enumeration is of type [Enum::MsoDocProperties].
        #
        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetProperty DeleteProperty
        #           GetPropertyName GetPropertyValue SetPropertyValue GetDocumentProperties

        set retVal [catch {$propertyId Type} propType]
        if { $retVal == 0 } {
            return [Office GetEnumName "MsoDocProperties" $propType]
        } else {
            return "N/A"
        }
    }

    proc GetProperty { objId propertyName args } {
        # Get a document property.
        #
        # objId        - The identifier of an Office object (Workbook, Document, Presentation).
        # propertyName - The name of the property.
        # args         - Options described below.
        #
        # -type <string> - Type of document property (`Builtin` or `Custom`).
        #                  If not specified, the property is searched in the builtin and
        #                  custom properties list. If the property name exists in both lists,
        #                  the builtin property is returned.
        #
        # Returns the identifier of the specified property.


        # If a property with given name does not exist, an error is thrown.
        #

        # See also: SetDocumentProperty GetDocumentProperty AddProperty GetDocumentProperties
        #           GetPropertyName GetPropertyType GetPropertyValue SetPropertyValue DeleteProperty

        set type ""
        foreach { key value } $args {
            if { $value eq "" } {
                error "GetProperty: No value specified for key \"$key\""
            }
            switch -exact -nocase -- $key {
                "-type" { set type $value }
                default { error "GetProperty: Unknown key \"$key\" specified" }
            }
        }
        set properties [Office GetDocumentProperties $objId $type]
        if { [lsearch $properties $propertyName] >= 0 } {
            if { $type eq "Builtin" || $type eq "" } {
                set propsBuiltin [$objId BuiltinDocumentProperties]
                set retVal [catch {$propsBuiltin -get Item $propertyName} property]
                Cawt Destroy $propsBuiltin
                if { $retVal == 0 } {
                    return $property
                }
            }
            if { $type eq "Custom" || $type eq "" } {
                set propsCustom  [$objId CustomDocumentProperties]
                set retVal [catch {$propsCustom -get Item $propertyName} property]
                Cawt Destroy $propsCustom
                if { $retVal == 0 } {



                    return $property
                }



            }

        }
        error "GetProperty: \"$propertyName\" is not a valid property name."
    }

    proc GetDocumentProperty { objId propertyName } {
        # Get the value of a document property.
        #
        # objId        - The identifier of an Office object (Workbook, Document, Presentation).
        # propertyName - The name of the property.
        #
        # Returns the value of specified property.
        # If the property value is not set or an invalid property name is given,
        # the string `N/A` is returned.
        #
        # See also: SetDocumentProperty AddProperty GetProperty GetDocumentProperties
        #           GetPropertyName GetPropertyType GetPropertyValue SetPropertyValue DeleteProperty

        set propertyValue "N/A"
        set retVal [catch {Office GetProperty $objId $propertyName} propertyId]
        if { $retVal == 0 } {
            set propertyValue [Office GetPropertyValue $propertyId]
            Cawt Destroy $propertyId
        }
        return $propertyValue
    }

    proc SetDocumentProperty { objId propertyName propertyValue } {
        # Set the value of a document property.
        #
        # objId         - The identifier of an Office object (Workbook, Document, Presentation).
        # propertyName  - The name of the property to set.
        # propertyValue - The value for the property.
        #                 The specified value must match the type of the property,
        #                 see [GetPropertyType].
        #
        # Returns no value.
        #
        # If the property name is a builtin property, its value is set.
        # Otherwise either a new custom property is created and its value set or,
        # if the custom property already exists, only its value is set.
        #
        # **Note:**
        #  * Some builtin properties are read-only. If trying to set the value of 
        #    a read-only property, no error is generated by an Office application.
        #  * Custom properties created with this procedure are string properties.
        #    If you need other property types, use [AddProperty].
        #
        # See also: GetDocumentProperty AddProperty GetProperty GetDocumentProperties
        #           GetPropertyName GetPropertyType GetPropertyValue SetPropertyValue DeleteProperty

        set retVal [catch {Office GetProperty $objId $propertyName} propertyId]
        if { $retVal != 0 } {
            set propertyId [Office AddProperty $objId $propertyName]
        }
        Office SetPropertyValue $propertyId $propertyValue
        Cawt Destroy $propertyId


    }

    proc GetOfficeType { fileName } {
        # Get the Office type of a file.
        #
        # fileName - File name.
        #
................................................................................
                default {
                    error "AddMacro: Unknown key \"$key\" specified" 
                }
            }
        }

        if { $fileName ne "" } {
            set catchVal [catch { $appId -with { VBE ActiveVBProject VBComponents } -call Import $fileName }]
            if { $catchVal } {
                error "AddMacro: Trust Access to the VBA project object model must be enabled."
            }
        } elseif { $codeStr ne "" } {
            set vbext_ct_StdModule [expr int(1)]
            set catchVal [catch { $appId -with { VBE ActiveVBProject VBComponents } -call Add $vbext_ct_StdModule } module]
            if { $catchVal } {
                error "AddMacro: Trust Access to the VBA project object model must be enabled."
            }
            $module -with { CodeModule } AddFromString $codeStr
        } else {
            error "AddMacro: Neither \"-file\" nor \"-code\" option specified." 
        }
................................................................................
        # Returns an empty string, if the macro is a procedure (Sub).
        # If the macro is a Function, the return value of the function is returned.
        # An error is thrown, if the macro does not exist or the execution of the 
        # macro fails.
        #
        # See also: AddMacro

        set retVal [catch { $appId -call Run $macroName {*}$args } val]
        if { $retVal == 0 } {
            return $val
        } else {
            error "RunMacro: $val"
        }
    }
}

Changes to undroid/cawt/Readme.txt.

22
23
24
25
26
27
28













29
30
31
32
33
34
35
generating the documentation, the distribution packages and the CAWT
Starkit. It also includes the external packages Ruff! and textutil.
The developer distribution is intended for programmers who want to
extend the CAWT package.

Release history:
================














2.4.9   2020-06-09
    Enhanced functionality in Excel module

    All modules:
        Compare procedure options with -nocase.








>
>
>
>
>
>
>
>
>
>
>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
generating the documentation, the distribution packages and the CAWT
Starkit. It also includes the external packages Ruff! and textutil.
The developer distribution is intended for programmers who want to
extend the CAWT package.

Release history:
================

2.5.0   2020-07-25
    Enhanced functionality for handling Office document properties.

    CawtOffice:
        Extended to support all types of document properties:
        bool, int, float, date and string.

    New procedures in CawtOffice:  
        AddProperty, DeleteProperty, GetProperty,
        GetPropertyName, GetPropertyType, GetPropertyValue,
        SetPropertyValue


2.4.9   2020-06-09
    Enhanced functionality in Excel module

    All modules:
        Compare procedure options with -nocase.

Changes to undroid/cawt/TestPrograms/Excel-25_Properties.tcl.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Delete Excel file from previous test run.
file mkdir testOut
set xlsFile [file join [pwd] "testOut" "Excel-25_Properties"]
append xlsFile [Excel GetExtString $appId]
file delete -force $xlsFile

# Set some builtin and custom properties and check their values.
Office SetDocumentProperty $workbookId "Author"     "Paul Obermeier"
Office SetDocumentProperty $workbookId "Company"    "poSoft"
Office SetDocumentProperty $workbookId "Title"      $xlsFile
Office SetDocumentProperty $workbookId "CustomProp" "CustomValue"

Cawt CheckString "Paul Obermeier" [Office GetDocumentProperty $workbookId "Author"]     "Property Author"
Cawt CheckString "poSoft"         [Office GetDocumentProperty $workbookId "Company"]    "Property Company"
Cawt CheckString $xlsFile         [Office GetDocumentProperty $workbookId "Title"]      "Property Title"
Cawt CheckString "CustomValue"    [Office GetDocumentProperty $workbookId "CustomProp"] "Property CustomProp"

set worksheetId [Excel GetWorksheetIdByIndex $workbookId 1]

Excel SetHeaderRow $worksheetId "BuiltinProperties" 1 1
Excel SetHeaderRow $worksheetId "CustomProperties" 1 3
Excel SetHeaderRow $worksheetId [list "Name" "Value" "Name" "Value"] 2 1
set rangeId [Excel SelectRangeByIndex $worksheetId 1 1 1 2]







|
|
|
|

|
|
|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Delete Excel file from previous test run.
file mkdir testOut
set xlsFile [file join [pwd] "testOut" "Excel-25_Properties"]
append xlsFile [Excel GetExtString $appId]
file delete -force $xlsFile

# Set some builtin and custom properties and check their values.
Office SetDocumentProperty $workbookId "Author"      "Paul"
Office SetDocumentProperty $workbookId "Company"     "poSoft"
Office SetDocumentProperty $workbookId "Title"       $xlsFile
Office SetDocumentProperty $workbookId "Custom Prop" "Custom Value"

Cawt CheckString "Paul"         [Office GetDocumentProperty $workbookId "Author"]      "Property Author"
Cawt CheckString "poSoft"       [Office GetDocumentProperty $workbookId "Company"]     "Property Company"
Cawt CheckString $xlsFile       [Office GetDocumentProperty $workbookId "Title"]       "Property Title"
Cawt CheckString "Custom Value" [Office GetDocumentProperty $workbookId "Custom Prop"] "Property Custom Prop"

set worksheetId [Excel GetWorksheetIdByIndex $workbookId 1]

Excel SetHeaderRow $worksheetId "BuiltinProperties" 1 1
Excel SetHeaderRow $worksheetId "CustomProperties" 1 3
Excel SetHeaderRow $worksheetId [list "Name" "Value" "Name" "Value"] 2 1
set rangeId [Excel SelectRangeByIndex $worksheetId 1 1 1 2]

Changes to undroid/cawt/TestPrograms/Ppt-07_Properties.tcl.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Delete PowerPoint file from previous test run.
file mkdir testOut
set pptFile [file join [pwd] "testOut" "Ppt-07_Properties"]
append pptFile [Ppt GetExtString $appId]
file delete -force $pptFile

# Set some builtin and custom properties and check their values.
Office SetDocumentProperty $presId "Author"     "Paul Obermeier"
Office SetDocumentProperty $presId "Company"    "poSoft"
Office SetDocumentProperty $presId "Title"      $pptFile
Office SetDocumentProperty $presId "CustomProp" "CustomValue"

Cawt CheckString "Paul Obermeier" [Office GetDocumentProperty $presId "Author"]     "Property Author"
Cawt CheckString "poSoft"         [Office GetDocumentProperty $presId "Company"]    "Property Company"
Cawt CheckString $pptFile         [Office GetDocumentProperty $presId "Title"]      "Property Title"
Cawt CheckString "CustomValue"    [Office GetDocumentProperty $presId "CustomProp"] "Property CustomProp"

Cawt PrintNumComObjects

# Get all builtin and custom properties and insert them into the presentation.
set builtinSlide [Ppt AddSlide $presId]
set textboxId [Ppt AddTextbox $builtinSlide 1c 2c 20c 20c]
set builtinProps [Office GetDocumentProperties $presId "Builtin"]







|
|
|
|

|
|
|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Delete PowerPoint file from previous test run.
file mkdir testOut
set pptFile [file join [pwd] "testOut" "Ppt-07_Properties"]
append pptFile [Ppt GetExtString $appId]
file delete -force $pptFile

# Set some builtin and custom properties and check their values.
Office SetDocumentProperty $presId "Author"      "Paul"
Office SetDocumentProperty $presId "Company"     "poSoft"
Office SetDocumentProperty $presId "Title"       $pptFile
Office SetDocumentProperty $presId "Custom Prop" "Custom Value"

Cawt CheckString "Paul"         [Office GetDocumentProperty $presId "Author"]      "Property Author"
Cawt CheckString "poSoft"       [Office GetDocumentProperty $presId "Company"]     "Property Company"
Cawt CheckString $pptFile       [Office GetDocumentProperty $presId "Title"]       "Property Title"
Cawt CheckString "Custom Value" [Office GetDocumentProperty $presId "Custom Prop"] "Property Custom Prop"

Cawt PrintNumComObjects

# Get all builtin and custom properties and insert them into the presentation.
set builtinSlide [Ppt AddSlide $presId]
set textboxId [Ppt AddTextbox $builtinSlide 1c 2c 20c 20c]
set builtinProps [Office GetDocumentProperties $presId "Builtin"]

Changes to undroid/cawt/TestPrograms/Word-10_Properties.tcl.

3
4
5
6
7
8
9






10
11
12
13
14
15
16
..
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32










33
34













35
36
37
38
39
40
41
42
43
44
45
46
47


48
49
50
51
52
53
54
55
56
57
58

59

60
61
62
63
64
65
66
67
68
69
70

71












72

73













74
75
76
77
78
79
80
81

82
83
84



85
86
87
88
89
90
91
# Copyright: 2007-2020 Paul Obermeier (obermeier@poSoft.de)
# Distributed under BSD license.

if { [file exists "SetTestPathes.tcl"] } {
    source "SetTestPathes.tcl"
}
package require cawt







# Open Word, show the application window and create a workbook.
set appId  [Word OpenNew true]
set docId1 [Word AddDocument $appId]

# Delete Word file from previous test run.
file mkdir testOut
................................................................................
set docFile1 [file join [pwd] "testOut" "Word-10_Properties1"]
set docFile2 [file join [pwd] "testOut" "Word-10_Properties2"]
append docFile1 [Word GetExtString $appId]
append docFile2 [Word GetExtString $appId]
file delete -force $docFile1
file delete -force $docFile2

# Set some builtin and custom properties and check their values.
Office SetDocumentProperty $docId1 "Author"     "Paul Obermeier"
Office SetDocumentProperty $docId1 "Company"    "poSoft"
Office SetDocumentProperty $docId1 "Title"      $docFile1
Office SetDocumentProperty $docId1 "CustomProp" "CustomValue1"

Cawt CheckString "Paul Obermeier" [Office GetDocumentProperty $docId1 "Author"]     "Property Author"
Cawt CheckString "poSoft"         [Office GetDocumentProperty $docId1 "Company"]    "Property Company"
Cawt CheckString $docFile1        [Office GetDocumentProperty $docId1 "Title"]      "Property Title"










Cawt CheckString "CustomValue1"   [Office GetDocumentProperty $docId1 "CustomProp"] "Property CustomProp"














# Get all builtin and custom properties and insert them into the document.
Word AppendText $docId1 "Builtin Properties:"
set builtinProps [Office GetDocumentProperties $docId1 "Builtin"]
set builtinTable [Word AddTable [Word GetEndRange $docId1] [expr [llength $builtinProps] +1] 2]
Word SetTableBorderLineStyle $builtinTable
Word SetTableOptions $builtinTable -left 0.4c -right 0.3c -top 0.1c -bottom 0.2c -spacing 0.05c
Word SetHeaderRow $builtinTable [list "Name" "Value"]

set row 2
set col 1
foreach propertyName $builtinProps {
    Word SetCellValue $builtinTable $row [expr $col + 0] $propertyName
    Word SetCellValue $builtinTable $row [expr $col + 1] [Office GetDocumentProperty $docId1 $propertyName]


    incr row
}

Word AppendText $docId1 "\nCustom Properties:"
set customProps [Office GetDocumentProperties $docId1 "Custom"]
set customTable [Word AddTable [Word GetEndRange $docId1] [expr [llength $customProps] +1] 2]
Word SetTableBorderLineStyle $customTable
Word SetHeaderRow $customTable [list "Name" "Value"]
set row 2
set col 1


foreach propertyName [Office GetDocumentProperties $docId1 "Custom"] {

    Word SetCellValue $customTable $row [expr $col + 0] $propertyName
    Word SetCellValue $customTable $row [expr $col + 1] [Office GetDocumentProperty $docId1 $propertyName]
    incr row
}

puts "Saving as Word file: $docFile1"
Word SaveAs $docId1 $docFile1
Word Close  $docId1

puts "Changing custom property ..."
set docId2 [Word OpenDocument $appId $docFile1]

Office SetDocumentProperty $docId2 "CustomProp" "CustomValue2"












Cawt CheckString "CustomValue2" [Office GetDocumentProperty $docId2 "CustomProp"] "Property CustomProp"















Word AppendText $docId2 "\nChanged Custom Properties:"
set customProps [Office GetDocumentProperties $docId2 "Custom"]
set customTable [Word AddTable [Word GetEndRange $docId2] [expr [llength $customProps] +1] 2]
Word SetTableBorderLineStyle $customTable
Word SetHeaderRow $customTable [list "Name" "Value"]
set row 2
set col 1


foreach propertyName [Office GetDocumentProperties $docId2 "Custom"] {
    Word SetCellValue $customTable $row [expr $col + 0] $propertyName
    Word SetCellValue $customTable $row [expr $col + 1] [Office GetDocumentProperty $docId2 $propertyName]



    incr row
}

puts "Saving as Word file: $docFile2"
Word SaveAs $docId2 $docFile2

Cawt PrintNumComObjects







>
>
>
>
>
>







 







|
|
|
|
|

|
|
|
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>



|


|


<

<
|
>
>





|

|
<
<

>
|
>
|
|







|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>


|

|
<
<

>
|
<
<
>
>
>







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73

74
75
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91
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
# Copyright: 2007-2020 Paul Obermeier (obermeier@poSoft.de)
# Distributed under BSD license.

if { [file exists "SetTestPathes.tcl"] } {
    source "SetTestPathes.tcl"
}
package require cawt

proc AddPropertyInfo { tableId row propertyId } {
    Word SetCellValue $tableId $row 1 [Office GetPropertyName  $propertyId]
    Word SetCellValue $tableId $row 2 [Office GetPropertyValue $propertyId]
    Word SetCellValue $tableId $row 3 [Office GetPropertyType  $propertyId]
}

# Open Word, show the application window and create a workbook.
set appId  [Word OpenNew true]
set docId1 [Word AddDocument $appId]

# Delete Word file from previous test run.
file mkdir testOut
................................................................................
set docFile1 [file join [pwd] "testOut" "Word-10_Properties1"]
set docFile2 [file join [pwd] "testOut" "Word-10_Properties2"]
append docFile1 [Word GetExtString $appId]
append docFile2 [Word GetExtString $appId]
file delete -force $docFile1
file delete -force $docFile2

# Set some writable builtin properties and check their values.
Office SetDocumentProperty $docId1 "Author"           "Paul"
Office SetDocumentProperty $docId1 "Company"          "poSoft"
Office SetDocumentProperty $docId1 "Title"            $docFile1
Office SetDocumentProperty $docId1 "Document version" "01"

Cawt CheckString "Paul"    [Office GetDocumentProperty $docId1 "Author"]           "Property Author"
Cawt CheckString "poSoft"  [Office GetDocumentProperty $docId1 "Company"]          "Property Company"
Cawt CheckString $docFile1 [Office GetDocumentProperty $docId1 "Title"]            "Property Title"
Cawt CheckString "01"      [Office GetDocumentProperty $docId1 "Document version"] "Property Document version"

# Set some read-only builtin properties and check their values.
Office SetDocumentProperty $docId1 "Revision number" "4"
Office SetDocumentProperty $docId1 "Security"         4
Cawt CheckString "1" [Office GetDocumentProperty $docId1 "Revision number"] "Property Revision number"
Cawt CheckNumber 0   [Office GetDocumentProperty $docId1 "Security"]        "Property Security"

# Set some custom properties and check their values.
Office SetDocumentProperty $docId1 "Custom Prop1" "Custom Value1"
Office SetDocumentProperty $docId1 "Custom Prop2" "2.0"

Office AddProperty $docId1 "BoolProp"   -type msoPropertyTypeBoolean -value true
Office AddProperty $docId1 "IntProp"    -type msoPropertyTypeNumber  -value 123
Office AddProperty $docId1 "FloatProp"  -type msoPropertyTypeFloat   -value 12.45
Office AddProperty $docId1 "DateProp"   -type msoPropertyTypeDate    -value 1.5
Office AddProperty $docId1 "StringProp" -type msoPropertyTypeString  -value "String"

# Add a custom property with same name as a builtin property.
set propDupId [Office AddProperty $docId1 "Title" -type msoPropertyTypeString]
Office SetPropertyValue $propDupId "MyTitle"

Cawt CheckString "Custom Value1" [Office GetDocumentProperty $docId1 "Custom Prop1"] "Property Custom Prop1"
Cawt CheckString "2.0"           [Office GetDocumentProperty $docId1 "Custom Prop2"] "Property Custom Prop2"

# Get all builtin and custom properties and insert them into the document.
Word AppendText $docId1 "Builtin Properties:"
set builtinProps [Office GetDocumentProperties $docId1 "Builtin"]
set builtinTable [Word AddTable [Word GetEndRange $docId1] [expr [llength $builtinProps] +1] 3]
Word SetTableBorderLineStyle $builtinTable
Word SetTableOptions $builtinTable -left 0.4c -right 0.3c -top 0.1c -bottom 0.2c -spacing 0.05c
Word SetHeaderRow $builtinTable [list "Name" "Value" "Type"]

set row 2

foreach propertyName $builtinProps {

    set propertyId [Office GetProperty $docId1 $propertyName]
    AddPropertyInfo $builtinTable $row $propertyId
    Cawt Destroy $propertyId
    incr row
}

Word AppendText $docId1 "\nCustom Properties:"
set customProps [Office GetDocumentProperties $docId1 "Custom"]
set customTable [Word AddTable [Word GetEndRange $docId1] [expr [llength $customProps] +1] 3]
Word SetTableBorderLineStyle $customTable
Word SetHeaderRow $customTable [list "Name" "Value" "Type"]



set row 2
foreach propertyName $customProps {
    set propertyId [Office GetProperty $docId1 $propertyName -type "Custom"]
    AddPropertyInfo $customTable $row $propertyId
    Cawt Destroy $propertyId
    incr row
}

puts "Saving as Word file: $docFile1"
Word SaveAs $docId1 $docFile1
Word Close  $docId1

puts "Changing custom properties ..."
set docId2 [Word OpenDocument $appId $docFile1]

Office SetDocumentProperty $docId2 "Custom Prop1" "CS1"
Office SetDocumentProperty $docId2 "Custom Prop2" "-2.0"
Office SetDocumentProperty $docId2 "BoolProp"     false
Office SetDocumentProperty $docId2 "IntProp"      321
Office SetDocumentProperty $docId2 "FloatProp"    45.12
Office SetDocumentProperty $docId2 "DateProp"     2.5
Office SetDocumentProperty $docId2 "StringProp"   "ChangedString"

# Changing a custom property, which also exists as a builtin type,
# does not work using SetDocumentProperty.
set propTitleId [Office GetProperty $docId2 "Title" -type "Custom"]
Office SetPropertyValue $propTitleId "MyChangedTitle"

Cawt CheckString "CS1"  [Office GetDocumentProperty $docId2 "Custom Prop1"] "Property Custom Prop1"
Cawt CheckString "-2.0" [Office GetDocumentProperty $docId2 "Custom Prop2"] "Property Custom Prop2"

# Check value of a not existing property.
Cawt CheckString "N/A" [Office GetDocumentProperty $docId2 "InvalidProp"] "Property InvalidProp"

Office AddProperty $docId2 "NewProp" -type msoPropertyTypeBoolean -value true
Office AddProperty $docId2 "NewProp" -type msoPropertyTypeString  -value "New" -overwrite true
Cawt CheckString "New" [Office GetDocumentProperty $docId2 "NewProp"] "Property NewProp"

set propId [Office AddProperty $docId2 "NewProp2"]
Cawt CheckString "" [Office GetDocumentProperty $docId2 "NewProp2"] "Property NewProp2"
Office DeleteProperty $propId
Cawt CheckString "N/A" [Office GetDocumentProperty $docId2 "NewProp2"] "Property NewProp2"

# Get all custom properties and insert them into the document.
Word AppendText $docId2 "\nChanged Custom Properties:"
set customProps [Office GetDocumentProperties $docId2 "Custom"]
set customTable [Word AddTable [Word GetEndRange $docId2] [expr [llength $customProps] +1] 3]
Word SetTableBorderLineStyle $customTable
Word SetHeaderRow $customTable [list "Name" "Value" "Type"]



set row 2
foreach propertyName $customProps {


    set propertyId [Office GetProperty $docId2 $propertyName -type "Custom"]
    AddPropertyInfo $customTable $row $propertyId
    Cawt Destroy $propertyId
    incr row
}

puts "Saving as Word file: $docFile2"
Word SaveAs $docId2 $docFile2

Cawt PrintNumComObjects

Changes to undroid/cawt/pkgIndex.tcl.

26
27
28
29
30
31
32
33
34
35
    }
    package provide cawt $version
}

set _CawtSubDirs [list CawtCore CawtOffice CawtExcel CawtWord CawtPpt CawtOutlook \
                       CawtOneNote CawtOcr CawtReader CawtExplorer CawtEarth CawtMatlab]

_SetupCawtPkgs $dir 2.4.9 $_CawtSubDirs

package ifneeded cawt 2.4.9 [list _LoadCawtPkgs $dir 2.4.9 $_CawtSubDirs]







|

|
26
27
28
29
30
31
32
33
34
35
    }
    package provide cawt $version
}

set _CawtSubDirs [list CawtCore CawtOffice CawtExcel CawtWord CawtPpt CawtOutlook \
                       CawtOneNote CawtOcr CawtReader CawtExplorer CawtEarth CawtMatlab]

_SetupCawtPkgs $dir 2.5.0 $_CawtSubDirs

package ifneeded cawt 2.5.0 [list _LoadCawtPkgs $dir 2.5.0 $_CawtSubDirs]

Changes to undroid/tcl-fuse/Makefile.in.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
MAKE_SHARED_LIB	= @MAKE_SHARED_LIB@
MAKE_STATIC_LIB	= @MAKE_STATIC_LIB@
MAKE_STUB_LIB	= @MAKE_STUB_LIB@
OBJEXT		= @OBJEXT@
RANLIB		= @RANLIB@
RANLIB_STUB	= @RANLIB_STUB@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_LD	= @SHLIB_LD@ `pkg-config fuse --cflags --libs`
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
STLIB_LD	= @STLIB_LD@ `pkg-config fuse --cflags --libs`
#TCL_DEFS	= @TCL_DEFS@
TCL_BIN_DIR	= @TCL_BIN_DIR@
TCL_SRC_DIR	= @TCL_SRC_DIR@
#TK_BIN_DIR	= @TK_BIN_DIR@
#TK_SRC_DIR	= @TK_SRC_DIR@

# Not used, but retained for reference of what libs Tcl required
................................................................................
#WISH   	= $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)

SHARED_BUILD	= @SHARED_BUILD@

INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@
#INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@

PKG_CFLAGS	= @PKG_CFLAGS@

# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.in checks for the necessary components
# that your library may use.  TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS		= $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)







|

|







 







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
MAKE_SHARED_LIB	= @MAKE_SHARED_LIB@
MAKE_STATIC_LIB	= @MAKE_STATIC_LIB@
MAKE_STUB_LIB	= @MAKE_STUB_LIB@
OBJEXT		= @OBJEXT@
RANLIB		= @RANLIB@
RANLIB_STUB	= @RANLIB_STUB@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_LD	= @SHLIB_LD@ `pkg-config fuse --libs`
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
STLIB_LD	= @STLIB_LD@ `pkg-config fuse --libs --static`
#TCL_DEFS	= @TCL_DEFS@
TCL_BIN_DIR	= @TCL_BIN_DIR@
TCL_SRC_DIR	= @TCL_SRC_DIR@
#TK_BIN_DIR	= @TK_BIN_DIR@
#TK_SRC_DIR	= @TK_SRC_DIR@

# Not used, but retained for reference of what libs Tcl required
................................................................................
#WISH   	= $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)

SHARED_BUILD	= @SHARED_BUILD@

INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@
#INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@

PKG_CFLAGS	= @PKG_CFLAGS@ `pkg-config fuse --cflags`

# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.in checks for the necessary components
# that your library may use.  TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS		= $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)