You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
7.8 KiB
246 lines
7.8 KiB
# -*- tcl -*- |
|
# Maintenance Instruction: leave the 999999.xxx.x as is and use 'deck make' or src/make.tcl to update from <pkg>-buildversion.txt |
|
# |
|
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem. |
|
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository. |
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
# (C) 2023 |
|
# |
|
# @@ Meta Begin |
|
# Application winlibreoffice 999999.0a1.0 |
|
# Meta platform tcl |
|
# Meta license <unspecified> |
|
# @@ Meta End |
|
|
|
|
|
|
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
## Requirements |
|
##e.g package require frobz |
|
package require uri ;#tcllib |
|
|
|
#windows? REVIEW - can we provide a common api for other platforms with only script? tcluno instead? |
|
|
|
if {"windows" eq $::tcl_platform(platform)} { |
|
if {[catch {package require twapi}]} { |
|
puts stderr "Twapi package required for winlibreoffice to function" |
|
puts stderr "Minimal functionality - only some utils may work" |
|
} |
|
} else { |
|
puts stderr "Package requires twapi. No current equivalent on non-windows platform. Try tcluno http://sf.net/projets/tcluno " |
|
puts stderr "Minimal functionality - only some utils may work" |
|
} |
|
|
|
|
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
namespace eval winlibreoffice { |
|
#--- |
|
#todo: investigate tcluno package http://sf.net/projects/tcluno |
|
#CPlusPlus - platforms? |
|
#--- |
|
# |
|
|
|
#enable 1 |
|
variable datebase "1899-12-30" ;#libreoffice default in options->LibreOfifce Calc->Calculate |
|
#variable datebase "1900-01-01" ;#StarCalc 1.0 |
|
#variable datebase "1904-01-01" ;# ??? |
|
|
|
#sometimes a com object may support $obj -print |
|
#see also |
|
# $obj -destroy |
|
# $obj Quit |
|
# $collection -iterate ?options? varname script |
|
|
|
variable uno "" ;# service manager object |
|
variable psm "" ;# process service manager |
|
|
|
# -- --- --- --- |
|
# libreoffice functions |
|
proc getServiceManager {} { |
|
variable uno |
|
if {$uno eq ""} { |
|
set uno [twapi::comobj com.sun.star.ServiceManager] |
|
} |
|
return $uno |
|
} |
|
#uno getAvailableServiceNames |
|
|
|
#e.g com.sun.star.beans.Introspection |
|
# com.sun.star.ucb.SimpleFileAccess |
|
proc createUnoService {objname} { |
|
[getProcessServiceManager] createInstance $objname |
|
} |
|
proc getProcessServiceManager {} { |
|
variable psm |
|
if {$psm eq ""} { |
|
set svcmgr [getServiceManager] |
|
#set psm [$svcmgr getProcessServiceManager] |
|
#seems to be same object? - it has createInstance anyway REVIEW |
|
set psm $svcmgr |
|
} |
|
return $psm |
|
} |
|
|
|
#what does libreoffice accept for this fun.. local file paths only? |
|
proc convertToUrl {fpath} { |
|
if {![string match "file:/*" $fpath]} { |
|
# this turns //server/blah to file:////server/blah - which is probably nonsense |
|
set fpath [uri::join scheme file path $fpath] |
|
} |
|
return $fpath |
|
} |
|
|
|
#this |
|
proc convertFromUrl {fileuri} { |
|
if {[string match "file:/*" $fileuri]} { |
|
set finfo [uri::split $fileuri] |
|
if {"windows" eq $::tcl_platform(platform)} { |
|
if {[dict exists $finfo host]} { |
|
return "//${host}${path}" |
|
} else { |
|
#the leading slash in path indicates a local path and we strip on windows |
|
set p [dict get $finfo path] |
|
if {[string index $p 0] eq "/"} { |
|
set p [string range $p 1 end] |
|
} |
|
return $p |
|
} |
|
} else { |
|
if {[dict exists $finfo host]} { |
|
#?? review - how are file uris to other hosts handled? |
|
error "convertFromUrl doesn't handle non-local file uris on this platform" |
|
} else { |
|
return [dict get $finfo path] |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
# -- --- --- --- |
|
# custom functions |
|
proc get_desktop {} { |
|
set uno [getServiceManager] |
|
set ctx [$uno getPropertyValue "DefaultContext"] |
|
set dt [$ctx getByName /singletons/com.sun.star.frame.theDesktop] |
|
#$dt setName odk_officedev_desk |
|
#$dt getName |
|
return $dt |
|
} |
|
|
|
proc blankdoc {{type scalc}} { |
|
set known_types [list scalc swriter simpress sdraw smath] |
|
if {$type ni $known_types} { |
|
puts stderr "Warning: unknown type $type. (known types: $known_types) will try anyway - private:factory/$type" |
|
} |
|
set dt [get_desktop] |
|
set doc [$dt loadComponentFromUrl "private:factory/$type" "_blank" 0 ""] ;#doesn't work without final param - empty string seems to work |
|
puts "doc title: [$doc Title]" |
|
return $doc |
|
} |
|
|
|
proc file_open_dialog {{title "pick a libreoffice file"}} { |
|
set filepicker [createUnoService "com.sun.star.ui.dialogs.FilePicker"] |
|
$filepicker Title $title |
|
set result [$filepicker Execute] |
|
if {$result} { |
|
#set files [$filepicker getSelectedFiles] |
|
# -iterate ? |
|
# return files(0) ? |
|
|
|
#e.g file:///C:/Users/sleek/test.txt |
|
return [$filepicker getFiles] |
|
} else { |
|
return "" |
|
} |
|
} |
|
|
|
#todo oo interface? |
|
proc calcdoc_sheets_by_index {doc idx} { |
|
set sheets [$doc getSheets] |
|
set s [$sheets getByIndex $idx] |
|
puts stdout "Sheet: [$s getName]" |
|
return $s |
|
} |
|
proc calcsheet_cell_range_by_name {sheet rangename} { |
|
return [$sheet getCellRangeByName $rangename] ;#e.g A1 |
|
} |
|
proc calccell_setString {cell str} { |
|
$cell setString $str |
|
} |
|
proc calccell_setValue {cell value} { |
|
$cell setValue $value |
|
} |
|
proc calccell_setPropertyValue {cell propset} { |
|
$cell setPropertyValue {*}$propset |
|
#e.g "NumberFormat" 49 |
|
# YYYY-MM-DD |
|
} |
|
|
|
#a hack |
|
#return libreoffice date in days since 1899.. |
|
proc date_from_clockseconds_approx {cs} { |
|
variable datebase |
|
set tbase [clock scan $datebase] |
|
package require punk::timeinterval |
|
set diff [punk::timeinterval::difference $tbase $cs] |
|
|
|
set Y [dict get $diff years] |
|
set M [dict get $diff months] |
|
set D [dict get $diff days] |
|
set yeardays [expr 365.25 * $Y] |
|
set monthdays [expr 30.437 * $M] |
|
|
|
#yes.. this is horrible.. just a test really - but gets in the ballpark. |
|
return [expr int($yeardays + $monthdays + $D)] |
|
} |
|
#time is represented on a scale of 0 to 1 6:00am = 0.25 (24/4) |
|
|
|
|
|
proc date_from_clockseconds {cs} { |
|
puts stderr "unimplemented" |
|
|
|
} |
|
|
|
#see also: https://wiki.tcl-lang.org/page/Tcom+examples+for+Microsoft+Outlook |
|
# this also uses days since 1899 (but 31 dec?) and uses a fixed base_offset of 36526 (for 2000-01-01) - this might be a better approach than using punk::timeinterval anyway |
|
# it seems to match libreoffice very closely (if not exact?) REVIEW |
|
# wher val is days since 1899 |
|
proc msdate_to_iso {val} { |
|
set base_ticks [clock scan 20000101] |
|
set base_offset 36526;# days since 31. Dec 1899, ARRRGGHHHHH |
|
set offset [expr {int($val)-$base_offset}] |
|
set clkdate [clock scan "$offset days" -base $base_ticks] |
|
set isodate [clock format $clkdate -format %Y%m%d] |
|
set fhours [expr {24.0*($val-int($val))}] |
|
set hours [expr {int($fhours)}] |
|
set mins [expr {int(($fhours-$hours)*60)}] |
|
#date<sp>H:m is valid iso but not if space replaced with T - then would need seconds too |
|
return "${isodate} $hours:$mins" |
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
## Ready |
|
package provide winlibreoffice [namespace eval winlibreoffice { |
|
variable version |
|
set version 999999.0a1.0 |
|
}] |
|
return
|
|
|