mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
2474 lines
73 KiB
Tcl
Executable File
2474 lines
73 KiB
Tcl
Executable File
#!/bin/sh
|
|
# -*-Mode: TCL;-*-
|
|
|
|
#--------------------------------------------------------------
|
|
# TKREMIND
|
|
#
|
|
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
|
#
|
|
# This file is part of REMIND.
|
|
# Copyright (C) 1992-1998 by David F. Skoll
|
|
#
|
|
#--------------------------------------------------------------
|
|
|
|
# $Id: tkremind,v 1.17 1998-04-19 03:39:31 dfs Exp $
|
|
|
|
# the next line restarts using wish \
|
|
exec wish "$0" "$@"
|
|
|
|
wm withdraw .
|
|
|
|
# Check that we have the right version of wish
|
|
if {$tcl_version < 8.0} {
|
|
tk_dialog .error Error "You need wish version 8.0 or higher to run TkRemind; you have $tcl_version" error 0 OK
|
|
exit 1
|
|
}
|
|
|
|
if {$tcl_platform(platform) == "windows"} {
|
|
tk_dialog .error Error "You are not allowed to run Remind under Windows" error 0 OK
|
|
exit 1
|
|
}
|
|
#---------------------------------------------------------------------------
|
|
# GLOBAL VARIABLES
|
|
#---------------------------------------------------------------------------
|
|
|
|
set Option(ConfirmQuit) 0
|
|
set OptDescr(ConfirmQuit) "(0/1) If 1, TkRemind prompts you to confirm 'Quit' operation"
|
|
set Option(AutoClose) 1
|
|
set OptDescr(AutoClose) "(0/1) If 1, TkRemind automatically closes pop-up reminders after a minute"
|
|
set Option(RingBell) 0
|
|
set OptDescr(RingBell) "(0/1) If 1, TkRemind beeps the terminal when a pop-up reminder appears"
|
|
|
|
set Option(StartIconified) 0
|
|
set OptDescr(StartIconified) "(0/1) If 1, TkRemind starts up in the iconified state"
|
|
|
|
set Option(Deiconify) 0
|
|
set OptDescr(Deiconify) "(0/1) If 1, TkRemind deiconifies the calendar window when a reminder pops up"
|
|
|
|
set Option(RunCmd) ""
|
|
set OptDescr(RunCmd) "(String) If non-blank, run specified command when a pop-up reminder appears"
|
|
set Option(FeedReminder) 0
|
|
set OptDescr(FeedReminder) "(0/1) If 1, feed the reminder to RunCmd on standard input (see RunCmd option)"
|
|
|
|
# Remind program to execute -- supply full path if you want
|
|
set Remind "remind"
|
|
#set Remind "/home/dfs/Remind/src/remind"
|
|
|
|
# Rem2PS program to execute -- supply full path if you want
|
|
set Rem2PS "rem2ps"
|
|
|
|
# Reminder file to source -- default
|
|
set ReminderFile {NOSUCHFILE}
|
|
set ReminderFile [file nativename "~/.reminders"]
|
|
|
|
# Reminder file to append to -- default
|
|
set AppendFile {NOSUCHFILE}
|
|
catch {set AppendFile $ReminderFile}
|
|
|
|
#---------------- DON'T CHANGE STUFF BELOW HERE ------------------
|
|
|
|
# Is Monday in first column?
|
|
set MondayFirst 0
|
|
|
|
# Month names in English
|
|
set MonthNames {January February March April May June July August September October November December}
|
|
|
|
# Day names in Remind's pre-selected language
|
|
set DayNames {}
|
|
|
|
# Day name in English
|
|
set EnglishDayNames {Sunday Monday Tuesday Wednesday Thursday Friday Saturday}
|
|
|
|
# Current month and year -- will be set by Initialize procedure
|
|
set CurMonth -1
|
|
set CurYear -1
|
|
|
|
# Background reminder counter
|
|
set BgCounter 0
|
|
|
|
# Absolutely today -- unlike the CurMonth and CurYear, these won't change
|
|
set TodayMonth -1
|
|
set TodayYear -1
|
|
set TodayDay -1
|
|
|
|
# Reminder option types and skip types
|
|
set OptionType 1
|
|
set SkipType 1
|
|
|
|
# Remind command line
|
|
set CommandLine {}
|
|
set PSCmd {}
|
|
|
|
# Print options -- destination file; letter-size; landscape; fill page
|
|
set PrintDest file
|
|
set PrintSize letter
|
|
set PrintOrient landscape
|
|
set PrintFill 1
|
|
|
|
# Highest tag seen so far. Array of tags is stored in ReminderTags()
|
|
set HighestTagSoFar 0
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: Initialize
|
|
# %ARGUMENTS:
|
|
# None
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Initializes TkRemind -- sets day names, Remind command line,
|
|
# MondayFirst flag, current date, etc.
|
|
#***********************************************************************
|
|
proc Initialize {} {
|
|
|
|
global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd
|
|
global MondayFirst
|
|
|
|
set CommandLine "|$Remind -itkremind=1 -p"
|
|
set PSCmd "$Remind -p"
|
|
set i 0
|
|
while {$i < $argc} {
|
|
if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} {
|
|
append CommandLine " [lindex $argv $i]"
|
|
append PSCmd " [lindex $argv $i]"
|
|
if {[regexp -- {m} [lindex $argv $i]]} {
|
|
set MondayFirst 1
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
incr i
|
|
}
|
|
if {$i < $argc} {
|
|
set ReminderFile [lindex $argv $i]
|
|
set AppendFile $ReminderFile
|
|
incr i
|
|
if {$i < $argc} {
|
|
set AppendFile [lindex $argv $i]
|
|
incr i
|
|
}
|
|
}
|
|
|
|
# Check system sanity
|
|
if {! [file readable $ReminderFile]} {
|
|
set ans [tk_dialog .error "TkRemind: Warning" "Can't read reminder file `$ReminderFile'" warning 0 "Create it and continue" "Exit"]
|
|
if {$ans != 0} {
|
|
exit 1
|
|
}
|
|
catch {close [open "$ReminderFile" w]}
|
|
}
|
|
if {! [file readable $ReminderFile]} {
|
|
tk_dialog .error "TkRemind: Error" "Could not create reminder file `$ReminderFile'" error 0 "Exit"
|
|
exit 1
|
|
}
|
|
|
|
if {! [file writable $AppendFile]} {
|
|
tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok
|
|
exit 1
|
|
}
|
|
|
|
append CommandLine " $ReminderFile"
|
|
append PSCmd " $ReminderFile"
|
|
set DayNames [GetWeekdayNames]
|
|
# puts "CommandLine: $CommandLine"
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# GetWeekdayNames - Spawn a remind process and get the names of the weekdays
|
|
# Also sets CurMonth and CurYear.
|
|
#---------------------------------------------------------------------------
|
|
proc GetWeekdayNames {} {
|
|
global CurMonth CurYear TodayYear TodayMonth TodayDay Remind
|
|
set f [open "|$Remind - 2>/dev/null" r+]
|
|
puts $f "banner %"
|
|
set i 0
|
|
while { $i < 7 } {
|
|
puts $f "msg \[wkday($i)\]%"
|
|
incr i
|
|
}
|
|
|
|
# Get current month and year as long as we're running Remind
|
|
puts $f "msg %n%"
|
|
puts $f "msg %y%"
|
|
puts $f "msg %d%"
|
|
puts $f "FLUSH"
|
|
flush $f
|
|
set ans {}
|
|
set i 0
|
|
while { $i < 7 } {
|
|
lappend ans [gets $f]
|
|
incr i
|
|
}
|
|
set CurMonth [expr [gets $f] - 1]
|
|
set CurYear [gets $f]
|
|
set TodayDay [gets $f]
|
|
set TodayMonth $CurMonth
|
|
set TodayYear $CurYear
|
|
close $f
|
|
return $ans
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: CalEntryOffset
|
|
# %ARGUMENTS:
|
|
# firstDay -- first day of month (0=Sunday, 6=Saturday)
|
|
# %RETURNS:
|
|
# Offset mapping day numbers (1-31) to window numbers (0-41)
|
|
# %DESCRIPTION:
|
|
# Computes offset from day number to window number
|
|
#***********************************************************************
|
|
proc CalEntryOffset { firstDay } {
|
|
global MondayFirst
|
|
if {$MondayFirst} {
|
|
incr firstDay -1
|
|
if {$firstDay < 0} {
|
|
set firstDay 6
|
|
}
|
|
}
|
|
return [expr $firstDay-1]
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: CreateCalFrame
|
|
# %ARGUMENTS:
|
|
# w -- name of frame window
|
|
# dayNames -- names of weekdays
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Creates a frame holding a grid of labels and a grid of text entries
|
|
#***********************************************************************
|
|
proc CreateCalFrame { w dayNames } {
|
|
global MondayFirst
|
|
frame $w
|
|
for {set i 0} {$i < 7} {incr i} {
|
|
if {$MondayFirst} {
|
|
set index [expr ($i+1)%7]
|
|
} else {
|
|
set index $i
|
|
}
|
|
|
|
label $w.day$i -text [lindex $dayNames $index] -justify center
|
|
grid configure $w.day$i -row 0 -column $i -sticky ew
|
|
}
|
|
for {set i 0} {$i < 6} {incr i} {
|
|
set n [expr $i*7]
|
|
for {set j 0} {$j < 7} {incr j} {
|
|
set f [expr $n+$j]
|
|
button $w.l$f -text "" -justify center -command "" \
|
|
-state disabled -relief flat
|
|
text $w.t$f -width 12 -height 5 -wrap word -relief flat \
|
|
-state disabled -takefocus 0 -cursor {}
|
|
$w.t$f tag bind TAGGED <Enter> "TaggedEnter $w.t$f"
|
|
$w.t$f tag bind TAGGED <Leave> "TaggedLeave $w.t$f"
|
|
$w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f"
|
|
grid configure $w.l$f -row [expr $i*2+1] -column $j -sticky ew
|
|
grid configure $w.t$f -row [expr $i*2+2] -column $j -sticky nsew
|
|
}
|
|
}
|
|
|
|
for {set i 0} {$i < 7} {incr i} {
|
|
grid columnconfigure $w $i -weight 1
|
|
}
|
|
for {set i 2} {$i < 14} {incr i 2} {
|
|
grid rowconfigure $w $i -weight 1
|
|
}
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: ConfigureCalFrame
|
|
# %ARGUMENTS:
|
|
# w -- window name of calendar frame
|
|
# firstDay -- first weekday of month
|
|
# numDays -- number of days in month
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Sets up button labels; configures text justification
|
|
#***********************************************************************
|
|
proc ConfigureCalFrame { w firstDay numDays } {
|
|
global CurMonth CurYear TodayMonth TodayYear TodayDay
|
|
set offset [CalEntryOffset $firstDay]
|
|
set first [expr $offset+1]
|
|
set last [expr $offset+$numDays]
|
|
|
|
for {set i 0} {$i < $first} {incr i} {
|
|
grid $w.l$i $w.t$i
|
|
$w.l$i configure -text "" -command "" -state disabled -relief flat
|
|
$w.t$i configure -relief flat -takefocus 0 -state normal
|
|
$w.t$i delete 1.0 end
|
|
$w.t$i configure -state disabled
|
|
$w.t$i configure -background [lindex [$w.t$i configure -background] 3]
|
|
$w.l$i configure -background [lindex [$w.l$i configure -background] 3]
|
|
}
|
|
for {set i $first} {$i <= $last} {incr i} {
|
|
grid $w.l$i $w.t$i
|
|
set d [expr $i-$first+1]
|
|
$w.l$i configure -text $d -state normal -relief flat \
|
|
-command "ModifyDay $d $firstDay"
|
|
$w.t$i configure -relief sunken -takefocus 1 -state normal
|
|
$w.t$i delete 1.0 end
|
|
$w.t$i configure -state disabled
|
|
$w.t$i configure -background [lindex [$w.t$i configure -background] 3]
|
|
$w.l$i configure -background [lindex [$w.l$i configure -background] 3]
|
|
}
|
|
set forgetIt 0
|
|
for {set i [expr $last+1]} {$i < 42} {incr i} {
|
|
if {$i%7 == 0} {
|
|
set forgetIt 1
|
|
}
|
|
set row [expr ($i/7)*2+1]
|
|
if {$forgetIt} {
|
|
grid remove $w.l$i $w.t$i
|
|
grid rowconfigure $w $row -weight 0
|
|
grid rowconfigure $w [expr $row+1] -weight 0
|
|
} else {
|
|
grid rowconfigure $w $row -weight 1
|
|
grid rowconfigure $w [expr $row+1] -weight 1
|
|
}
|
|
$w.l$i configure -text "" -command "" -state disabled -relief flat
|
|
$w.t$i configure -relief flat -takefocus 0 -state normal
|
|
$w.t$i delete 1.0 end
|
|
$w.t$i configure -state disabled
|
|
$w.t$i configure -background [lindex [$w.t$i configure -background] 3]
|
|
$w.l$i configure -background [lindex [$w.l$i configure -background] 3]
|
|
}
|
|
if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } {
|
|
set n [expr $TodayDay + $offset]
|
|
$w.l$n configure -background "#00c0c0"
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateCalWindow -- create the calendar window.
|
|
# Arguments:
|
|
# dayNames -- names of weekdays in current language {Sun .. Sat}
|
|
#---------------------------------------------------------------------------
|
|
proc CreateCalWindow { dayNames } {
|
|
global Option
|
|
frame .h
|
|
label .h.title -text "" -justify center -pady 2 -relief raised
|
|
pack .h.title -side top -fill x
|
|
pack .h -side top -expand 0 -fill x
|
|
|
|
CreateCalFrame .cal $dayNames
|
|
pack .cal -side top -fill both -expand 1
|
|
|
|
frame .b
|
|
button .b.prev -text {<-} -command {MoveMonth -1}
|
|
button .b.this -text {Today} -command {ThisMonth}
|
|
button .b.next -text {->} -command {MoveMonth 1}
|
|
button .b.goto -text {Go To Date...} -command {GotoDialog}
|
|
button .b.print -text {Print...} -command {DoPrint}
|
|
button .b.quit -text {Quit} -command {Quit}
|
|
button .b.options -text {Options...} -command EditOptions
|
|
label .b.status -text "" -width 25 -relief sunken
|
|
label .b.nqueued -text "" -width 20 -relief sunken
|
|
pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.quit -side left -fill x
|
|
pack .b.status -side left -fill x -expand 1
|
|
pack .b.nqueued -side left -fill x
|
|
pack .b -side top -fill x -expand 0
|
|
wm title . "TkRemind"
|
|
wm iconname . ""
|
|
wm protocol . WM_DELETE_WINDOW Quit
|
|
wm deiconify .
|
|
if {$Option(StartIconified)} {
|
|
wm iconify .
|
|
}
|
|
update
|
|
grid propagate .cal 0
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: EditOptions
|
|
# %ARGUMENTS:
|
|
# None
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Lets user edit options
|
|
#***********************************************************************
|
|
proc EditOptions {} {
|
|
global Option tmpOpt
|
|
|
|
# Make a working copy of current option set
|
|
foreach name [array names Option] {
|
|
set tmpOpt($name) $Option($name)
|
|
}
|
|
|
|
set w .opt
|
|
catch { destroy $w }
|
|
toplevel $w
|
|
wm title $w "TkRemind Options"
|
|
wm iconname $w "Options"
|
|
frame $w.f
|
|
frame $w.b
|
|
pack $w.f -side top -expand 1 -fill both
|
|
pack $w.b -side top -expand 0 -fill x
|
|
|
|
# Start iconified
|
|
checkbutton $w.startIconified -text "Start up Iconified" \
|
|
-anchor w -justify left \
|
|
-variable tmpOpt(StartIconified)
|
|
|
|
# Confirm quit
|
|
checkbutton $w.confirmQuit -text "Confirm Quit" -anchor w -justify left \
|
|
-variable tmpOpt(ConfirmQuit)
|
|
|
|
# Bring down reminder windows after one minute
|
|
checkbutton $w.bringDown \
|
|
-text "Automatically close pop-up reminders after a minute" \
|
|
-anchor w -justify left -variable tmpOpt(AutoClose)
|
|
|
|
# Ring bell when popping up reminder
|
|
checkbutton $w.ring -text "Beep terminal when popping up a reminder" \
|
|
-anchor w -justify left -variable tmpOpt(RingBell)
|
|
|
|
checkbutton $w.deic -text "Deiconify calendar window when popping up a reminder" \
|
|
-anchor w -justify left -variable tmpOpt(Deiconify)
|
|
|
|
# Run command when popping up reminder
|
|
frame $w.rf
|
|
label $w.rl -text "Run command when popping up reminder:" -anchor w \
|
|
-justify left
|
|
entry $w.cmd -width 30
|
|
pack $w.rl -in $w.rf -side left -expand 0 -fill none
|
|
pack $w.cmd -in $w.rf -side left -expand 1 -fill x
|
|
$w.cmd insert 0 $tmpOpt(RunCmd)
|
|
|
|
frame $w.sep1 -border 1 -relief sunken
|
|
frame $w.sep2 -border 1 -relief sunken
|
|
|
|
checkbutton $w.feed \
|
|
-text "Feed popped-up reminder to command's standard input" \
|
|
-variable tmpOpt(FeedReminder) -anchor w -justify left
|
|
|
|
pack $w.startIconified -in $w.f -side top -expand 0 -fill x
|
|
pack $w.confirmQuit -in $w.f -side top -expand 0 -fill x
|
|
pack $w.bringDown -in $w.f -side top -expand 0 -fill x
|
|
pack $w.ring -in $w.f -side top -expand 0 -fill x
|
|
pack $w.deic -in $w.f -side top -expand 0 -fill x
|
|
pack $w.sep1 -in $w.f -side top -expand 0 -fill x -ipady 1
|
|
pack $w.rf -in $w.f -side top -expand 0 -fill x
|
|
pack $w.feed -in $w.f -side top -expand 0 -fill x
|
|
pack $w.sep2 -in $w.f -side top -expand 0 -fill x -ipady 1
|
|
|
|
button $w.apply -text "Apply Options" -command "ApplyOptions $w; destroy $w"
|
|
button $w.save -text "Save Options" -command "SaveOptions $w; destroy $w"
|
|
button $w.cancel -text "Cancel" -command "destroy $w"
|
|
|
|
pack $w.apply $w.save $w.cancel -in $w.b -side left -expand 0 -fill x
|
|
CenterWindow $w
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: ApplyOptions
|
|
# %ARGUMENTS:
|
|
# w -- edit options window path
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Applies options set in the edit options box.
|
|
#***********************************************************************
|
|
proc ApplyOptions { w } {
|
|
global Option tmpOpt
|
|
set tmpOpt(RunCmd) [$w.cmd get]
|
|
# Copy working copy to real option set
|
|
foreach name [array names tmpOpt] {
|
|
set Option($name) $tmpOpt($name)
|
|
}
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: SaveOptions
|
|
# %ARGUMENTS:
|
|
# w -- edit options window path
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Saves options in $HOME/.tkremindrc
|
|
#***********************************************************************
|
|
proc SaveOptions { w } {
|
|
global Option OptDescr
|
|
ApplyOptions $w
|
|
|
|
set problem [catch {set f [open ~/.tkremindrc "w"]} err]
|
|
if {$problem} {
|
|
tk_dialog .error Error "Can't write ~/.tkremindrc: $err" 0 OK
|
|
return
|
|
}
|
|
|
|
puts $f "# TkRemind option file -- created automatically"
|
|
puts $f "# [clock format [clock seconds]]"
|
|
puts $f "# Format of each line is 'key value' where 'key'"
|
|
puts $f "# specifies the option name, and 'value' is a"
|
|
puts $f "# *legal Tcl list element* specifying the option value."
|
|
foreach name [lsort [array names Option]] {
|
|
puts $f ""
|
|
puts $f "# $OptDescr($name)"
|
|
puts $f [list $name $Option($name)]
|
|
}
|
|
close $f
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: LoadOptions
|
|
# %ARGUMENTS:
|
|
# None
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Loads options from ~/.tkremindrc
|
|
#***********************************************************************
|
|
proc LoadOptions {} {
|
|
global Option
|
|
set problem [catch {set f [open "~/.tkremindrc" "r"]}]
|
|
if {$problem} {
|
|
return
|
|
}
|
|
while {[gets $f line] >= 0} {
|
|
if {[string match "#*" $line]} { continue }
|
|
if {$line == ""} { continue }
|
|
foreach {key val} $line {}
|
|
if {![info exists Option($key)]} {
|
|
puts "Unknown option in ~/.tkremindrc: $key"
|
|
continue
|
|
}
|
|
set Option($key) $val
|
|
}
|
|
close $f
|
|
}
|
|
|
|
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: ConfigureCalWindow
|
|
# %ARGUMENTS:
|
|
# month -- month name
|
|
# year -- the year
|
|
# firstDay -- first day in month
|
|
# numDays -- number of days in month
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Configures the calendar window for a month and year
|
|
# %PRECONDITIONS:
|
|
# Any preconditions
|
|
# %POSTCONDITIONS:
|
|
# Any postconditions
|
|
# %SIDE EFFECTS:
|
|
# Any side effects
|
|
#***********************************************************************
|
|
proc ConfigureCalWindow { month year firstDay numDays } {
|
|
.h.title configure -text "$month $year"
|
|
wm title . "TkRemind - $month $year"
|
|
wm iconname . "$month $year"
|
|
ConfigureCalFrame .cal $firstDay $numDays
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# FillCalWindow -- Fill in the calendar for global CurMonth and CurYear.
|
|
#---------------------------------------------------------------------------
|
|
proc FillCalWindow {} {
|
|
global DayNames CurYear CurMonth MonthNames CommandLine
|
|
|
|
Status "Firing off Remind..."
|
|
set month [lindex $MonthNames $CurMonth]
|
|
|
|
set file [open "$CommandLine $month $CurYear" r]
|
|
# Look for # rem2ps begin line
|
|
while { [gets $file line] >= 0 } {
|
|
if { [string compare "$line" "# rem2ps begin"] == 0 } { break }
|
|
}
|
|
|
|
if { [string compare "$line" "# rem2ps begin"] != 0 } {
|
|
Status "Problem reading results from Remind!"
|
|
after 5000 DisplayTime
|
|
catch { close $file }
|
|
return 0
|
|
}
|
|
|
|
# Read month name, year, number of days in month, first weekday, Mon flag
|
|
gets $file line
|
|
regexp {^([^ ]*) ([0-9][0-9][0-9][0-9]) ([0-9][0-9]?) ([0-9]) ([0-9])} $line dummy monthName year daysInMonth firstWkday mondayFirst
|
|
|
|
# Skip day names -- we already have them
|
|
gets $file line
|
|
ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
|
|
set offset [CalEntryOffset $firstWkday]
|
|
while { [gets $file line] >= 0 } {
|
|
if { [regexp {^([0-9][0-9][0-9][0-9])/([0-9][0-9])/([0-9][0-9]) +([^ ]+) +([^ ]+) +[^ ]+ +[^ ]+(.*)} $line all year month day type tag stuff] == 0 } {
|
|
continue
|
|
}
|
|
set day [string trimleft $day 0]
|
|
set n [expr $day+$offset]
|
|
set month [string trimleft $month 0]
|
|
switch -exact -- $type {
|
|
"SHADE" {
|
|
DoShadeSpecial $n $stuff
|
|
continue
|
|
}
|
|
"MOON" {
|
|
DoMoonSpecial $n $stuff
|
|
continue
|
|
}
|
|
}
|
|
if { $type != "*"} {
|
|
continue
|
|
}
|
|
.cal.t$n configure -state normal
|
|
if { [string length [string trim [.cal.t$n get 1.0]]] != 0} {
|
|
.cal.t$n insert end " .....\n"
|
|
}
|
|
if {[regexp {TKTAG([0-9])+} $tag all tagno]} {
|
|
.cal.t$n insert end [string trim $stuff] "TAGGED TKTAG$tagno"
|
|
} else {
|
|
.cal.t$n insert end [string trim $stuff]
|
|
}
|
|
.cal.t$n insert end "\n"
|
|
.cal.t$n configure -state disabled
|
|
|
|
}
|
|
set problem [catch { close $file } errmsg]
|
|
if {$problem} {
|
|
tk_dialog .error Error "There was a problem running Remind: $errmsg" error 0 OK
|
|
exit 1
|
|
}
|
|
DisplayTime
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# MoveMonth -- move by +1 or -1 months
|
|
# Arguments:
|
|
# delta -- +1 or -1 -- months to move.
|
|
#---------------------------------------------------------------------------
|
|
proc MoveMonth {delta} {
|
|
global CurMonth CurYear
|
|
set CurMonth [expr $CurMonth + $delta]
|
|
if {$CurMonth < 0} {
|
|
set CurMonth 11
|
|
set CurYear [expr $CurYear-1]
|
|
}
|
|
|
|
if {$CurMonth > 11} {
|
|
set CurMonth 0
|
|
incr CurYear
|
|
}
|
|
|
|
FillCalWindow
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# ThisMonth -- move to current month
|
|
#---------------------------------------------------------------------------
|
|
proc ThisMonth {} {
|
|
global CurMonth CurYear TodayMonth TodayYear
|
|
|
|
# Do nothing if already there
|
|
if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } {
|
|
return 0;
|
|
}
|
|
set CurMonth $TodayMonth
|
|
set CurYear $TodayYear
|
|
FillCalWindow
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# Status -- set status string
|
|
# Arguments:
|
|
# stuff -- what to set string to.
|
|
#---------------------------------------------------------------------------
|
|
proc Status { stuff } {
|
|
catch { .b.status configure -text $stuff }
|
|
update idletasks
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# DoPrint -- print a calendar
|
|
# Arguments:
|
|
# None
|
|
#---------------------------------------------------------------------------
|
|
proc DoPrint {} {
|
|
global PrintDest PrintSize PrintOrient PrintFill PrintStatus Rem2PS PSCmd
|
|
global CurMonth CurYear MonthNames
|
|
catch {destroy .p}
|
|
toplevel .p
|
|
wm title .p "TkRemind Print..."
|
|
wm iconname .p "Print..."
|
|
frame .p.f1 -relief sunken -border 2
|
|
frame .p.f11
|
|
frame .p.f12
|
|
frame .p.f2 -relief sunken -border 2
|
|
frame .p.f3 -relief sunken -border 2
|
|
frame .p.f4
|
|
|
|
radiobutton .p.tofile -text "To file: " -variable PrintDest -value file
|
|
entry .p.filename
|
|
button .p.browse -text "Browse..." -command PrintFileBrowse
|
|
radiobutton .p.tocmd -text "To command: " -variable PrintDest -value command
|
|
entry .p.command
|
|
.p.command insert end "lpr"
|
|
|
|
label .p.size -text "Paper Size:"
|
|
radiobutton .p.letter -text "Letter" -variable PrintSize -value letter
|
|
radiobutton .p.a4 -text "A4" -variable PrintSize -value a4
|
|
|
|
label .p.orient -text "Orientation:"
|
|
radiobutton .p.landscape -text "Landscape" -variable PrintOrient -value landscape
|
|
radiobutton .p.portrait -text "Portrait" -variable PrintOrient -value portrait
|
|
|
|
checkbutton .p.fill -text "Fill page" -variable PrintFill
|
|
|
|
button .p.print -text "Print" -command {set PrintStatus print}
|
|
button .p.cancel -text "Cancel" -command {set PrintStatus cancel}
|
|
|
|
pack .p.f1 .p.f2 .p.f3 -side top -fill both -expand 1 -anchor w
|
|
pack .p.fill -side top -anchor w -fill none -expand 0
|
|
pack .p.f4 -side top -fill both -expand 1 -anchor w
|
|
pack .p.f11 .p.f12 -in .p.f1 -side top -fill none -expand 0 -anchor w
|
|
pack .p.tofile .p.filename .p.browse -in .p.f11 -side left -fill none -expand 0 -anchor w
|
|
pack .p.tocmd .p.command -in .p.f12 -side left -fill none -expand 0 -anchor w
|
|
pack .p.size .p.letter .p.a4 -in .p.f2 -side top -fill none -expand 0 -anchor w
|
|
pack .p.orient .p.landscape .p.portrait -in .p.f3 -side top -fill none -expand 0 -anchor w
|
|
pack .p.print .p.cancel -in .p.f4 -side left -fill none -expand 0
|
|
|
|
bind .p <KeyPress-Escape> ".p.cancel flash; .p.cancel invoke"
|
|
bind .p <KeyPress-Return> ".p.print flash; .p.print invoke"
|
|
set PrintStatus 2
|
|
CenterWindow .p
|
|
tkwait visibility .p
|
|
set oldFocus [focus]
|
|
focus .p.filename
|
|
grab .p
|
|
tkwait variable PrintStatus
|
|
catch {focus $oldFocus}
|
|
set fname [.p.filename get]
|
|
set cmd [.p.command get]
|
|
destroy .p
|
|
if {$PrintStatus == "cancel"} {
|
|
return
|
|
}
|
|
if {$PrintDest == "file"} {
|
|
if {$fname == ""} {
|
|
tk_dialog .error Error "No filename specified" error 0 Ok
|
|
return
|
|
}
|
|
if {[file isdirectory $fname]} {
|
|
tk_dialog .error Error "$fname is a directory" error 0 Ok
|
|
return
|
|
}
|
|
if {[file readable $fname]} {
|
|
set ans [tk_dialog .error Overwrite? "Overwrite $fname?" question 0 No Yes]
|
|
if {$ans == 0} {
|
|
return
|
|
}
|
|
}
|
|
set fname "> $fname"
|
|
} else {
|
|
set fname "| $cmd"
|
|
}
|
|
|
|
# Build the command line
|
|
set cmd "$PSCmd 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PS -c3"
|
|
if {$PrintSize == "letter"} {
|
|
append cmd " -m Letter"
|
|
} else {
|
|
append cmd " -m A4"
|
|
}
|
|
|
|
if {$PrintOrient == "landscape"} {
|
|
append cmd " -l"
|
|
}
|
|
|
|
if {$PrintFill} {
|
|
append cmd " -e"
|
|
}
|
|
|
|
append cmd " $fname"
|
|
Status "Printing..."
|
|
if {[catch {eval "exec $cmd"} err]} {
|
|
tk_dialog .error Error "Error during printing: $err" error 0 Ok
|
|
}
|
|
DisplayTime
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# PrintFileBrowse -- browse for a filename for Print dialog
|
|
# Arguments: none
|
|
#---------------------------------------------------------------------------
|
|
proc PrintFileBrowse {} {
|
|
set ans [BrowseForFile .filebrowse "Print to file..." "Ok" 0 "*.ps"]
|
|
if {$ans != ""} {
|
|
.p.filename delete 0 end
|
|
.p.filename insert end $ans
|
|
.p.filename icursor end
|
|
.p.filename xview end
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# GotoDialog -- Do the "Goto..." dialog
|
|
#---------------------------------------------------------------------------
|
|
proc GotoDialog {} {
|
|
global CurMonth MonthNames CurYear
|
|
catch { destroy .g }
|
|
|
|
set month [lindex $MonthNames $CurMonth]
|
|
toplevel .g
|
|
wm title .g "Go To Date"
|
|
menubutton .g.mon -text "$month" -menu .g.mon.menu -relief raised
|
|
menu .g.mon.menu -tearoff 0
|
|
|
|
foreach m $MonthNames {
|
|
.g.mon.menu add command -label $m -command ".g.mon configure -text $m"
|
|
}
|
|
|
|
frame .g.y
|
|
label .g.y.lab -text "Year: "
|
|
entry .g.y.e -width 4
|
|
.g.y.e insert end $CurYear
|
|
bind .g.y.e <Return> ".g.b.go flash; .g.b.go invoke"
|
|
frame .g.b
|
|
button .g.b.go -text "Go" -command {DoGoto}
|
|
button .g.b.cancel -text "Cancel" -command { destroy .g }
|
|
pack .g.b.go .g.b.cancel -expand 1 -fill x -side left
|
|
pack .g.mon -fill x -expand 1
|
|
|
|
pack .g.y.lab -side left
|
|
pack .g.y.e -side left -fill x -expand 1
|
|
pack .g.y -expand 1 -fill x
|
|
pack .g.b -expand 1 -fill x
|
|
bind .g <KeyPress-Escape> ".g.b.cancel flash; .g.b.cancel invoke"
|
|
CenterWindow .g
|
|
set oldFocus [focus]
|
|
grab .g
|
|
focus .g.y.e
|
|
tkwait window .g
|
|
catch {focus $oldFocus}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# DoGoto -- go to specified date
|
|
#---------------------------------------------------------------------------
|
|
proc DoGoto {} {
|
|
global CurYear CurMonth MonthNames
|
|
set year [.g.y.e get]
|
|
if { ! [regexp {^[0-9]+$} $year] } {
|
|
tk_dialog .error Error {Illegal year specified (1990-2078)} error 0 Ok
|
|
return
|
|
}
|
|
if { $year < 1990 || $year > 2078 } {
|
|
tk_dialog .error Error {Illegal year specified (1990-2078)} error 0 Ok
|
|
return
|
|
}
|
|
set month [lsearch -exact $MonthNames [.g.mon cget -text]]
|
|
set CurMonth $month
|
|
set CurYear $year
|
|
destroy .g
|
|
FillCalWindow
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# Quit -- handle the Quit button
|
|
#---------------------------------------------------------------------------
|
|
proc Quit {} {
|
|
global Option
|
|
if { !$Option(ConfirmQuit) } {
|
|
destroy .
|
|
StopBackgroundRemindDaemon
|
|
exit
|
|
}
|
|
if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
|
|
destroy .
|
|
StopBackgroundRemindDaemon
|
|
exit
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateModifyDialog -- create dialog for adding a reminder
|
|
# Arguments:
|
|
# w -- path of parent window
|
|
# day -- day number of month
|
|
# firstDay -- day number of first day of month
|
|
# args -- buttons to add to bottom frame. First sets result to 1, next
|
|
# to 2, and so on. FIRST BUTTON MUST BE "Cancel"
|
|
#---------------------------------------------------------------------------
|
|
proc CreateModifyDialog {w day firstDay args} {
|
|
|
|
# Set up: Year, Month, Day, WeekdayName
|
|
global CurYear CurMonth EnglishDayNames MonthNames OptionType SkipType
|
|
global ModifyDialogResult
|
|
|
|
set OptionType 1
|
|
set SkipType 1
|
|
|
|
set year $CurYear
|
|
set month [lindex $MonthNames $CurMonth]
|
|
set wkday [lindex $EnglishDayNames [expr ($day+$firstDay-1) % 7]]
|
|
|
|
frame $w.o -border 4 -relief ridge
|
|
frame $w.o1 -border 4
|
|
frame $w.o2 -border 4
|
|
frame $w.o3 -border 4
|
|
frame $w.exp -border 4
|
|
frame $w.adv -border 4
|
|
frame $w.weekend -border 4
|
|
frame $w.time -border 4
|
|
frame $w.hol -border 4
|
|
frame $w.msg
|
|
frame $w.buttons
|
|
pack $w.o1 $w.o2 $w.o3 -side top -anchor w -in $w.o
|
|
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.hol $w.msg -side top -anchor w -pady 4 -expand 1 -fill both
|
|
pack $w.buttons -side top -anchor w -pady 4 -expand 1 -fill x
|
|
|
|
# TYPE 1 REMINDER
|
|
radiobutton $w.type1 -variable OptionType -value 1
|
|
menubutton $w.day1 -text $day -relief raised -menu $w.day1.menu
|
|
CreateDayMenu $w.day1
|
|
menubutton $w.mon1 -text $month -relief raised -menu $w.mon1.menu
|
|
CreateMonthMenu $w.mon1
|
|
menubutton $w.year1 -text $year -relief raised -menu $w.year1.menu
|
|
CreateYearMenu $w.year1
|
|
checkbutton $w.repbut -text "and repeating every"
|
|
$w.repbut deselect
|
|
menubutton $w.repdays -text 1 -relief raised -menu $w.repdays.menu
|
|
CreateDayMenu $w.repdays 1 28 0
|
|
label $w.label1a -text "day(s) thereafter"
|
|
pack $w.type1 $w.day1 $w.mon1 $w.year1 $w.repbut $w.repbut $w.repdays $w.label1a -side left -anchor w -in $w.o1
|
|
|
|
# TYPE 2 REMINDER
|
|
radiobutton $w.type2 -variable OptionType -value 2
|
|
label $w.label2a -text First
|
|
menubutton $w.wkday2 -text $wkday -relief raised -menu $w.wkday2.menu
|
|
CreateWeekdayMenu $w.wkday2
|
|
label $w.label2b -text "on or after"
|
|
menubutton $w.day2 -text $day -relief raised -menu $w.day2.menu
|
|
CreateDayMenu $w.day2 1 31 0
|
|
menubutton $w.mon2 -text $month -relief raised -menu $w.mon2.menu
|
|
CreateMonthMenu $w.mon2
|
|
menubutton $w.year2 -text $year -relief raised -menu $w.year2.menu
|
|
CreateYearMenu $w.year2
|
|
pack $w.type2 $w.label2a $w.wkday2 $w.label2b $w.day2 $w.mon2 $w.year2 -side left -anchor w -in $w.o2
|
|
|
|
# TYPE 3 REMINDER
|
|
if { $day <= 7 } {
|
|
set which "First"
|
|
} elseif {$day <= 14} {
|
|
set which "Second"
|
|
} elseif {$day <= 21} {
|
|
set which "Third"
|
|
} elseif {$day <= 28} {
|
|
set which "Fourth"
|
|
} else {
|
|
set which "Last"
|
|
}
|
|
radiobutton $w.type3 -variable OptionType -value 3
|
|
menubutton $w.ordinal -text $which -relief raised -menu $w.ordinal.menu
|
|
menu $w.ordinal.menu -tearoff 0
|
|
$w.ordinal.menu add command -label "First" -command "$w.ordinal configure -text First"
|
|
$w.ordinal.menu add command -label "Second" -command "$w.ordinal configure -text Second"
|
|
$w.ordinal.menu add command -label "Third" -command "$w.ordinal configure -text Third"
|
|
$w.ordinal.menu add command -label "Fourth" -command "$w.ordinal configure -text Fourth"
|
|
$w.ordinal.menu add command -label "Last" -command "$w.ordinal configure -text Last"
|
|
$w.ordinal.menu add command -label "Every" -command "$w.ordinal configure -text Every"
|
|
menubutton $w.wkday3 -text $wkday -relief raised -menu $w.wkday3.menu
|
|
CreateWeekdayMenu $w.wkday3
|
|
label $w.label3 -text "in"
|
|
menubutton $w.mon3 -text $month -relief raised -menu $w.mon3.menu
|
|
CreateMonthMenu $w.mon3
|
|
menubutton $w.year3 -text $year -relief raised -menu $w.year3.menu
|
|
CreateYearMenu $w.year3
|
|
pack $w.type3 $w.ordinal $w.wkday3 $w.label3 $w.mon3 $w.year3 -side left -anchor w -in $w.o3
|
|
|
|
# EXPIRY DATE
|
|
checkbutton $w.expbut -text "Expire after"
|
|
$w.expbut deselect
|
|
menubutton $w.expday -text $day -relief raised -menu $w.expday.menu
|
|
CreateDayMenu $w.expday 1 31 0
|
|
menubutton $w.expmon -text $month -relief raised -menu $w.expmon.menu
|
|
CreateMonthMenu $w.expmon 0
|
|
menubutton $w.expyear -text $year -relief raised -menu $w.expyear.menu
|
|
CreateYearMenu $w.expyear 0
|
|
|
|
pack $w.expbut $w.expday $w.expmon $w.expyear -side left -anchor w -in $w.exp
|
|
|
|
# ADVANCE NOTICE
|
|
checkbutton $w.advbut -text "Issue"
|
|
$w.advbut deselect
|
|
menubutton $w.advdays -text 3 -menu $w.advdays.menu -relief raised
|
|
CreateDayMenu $w.advdays 1 10 0
|
|
label $w.advlab -text "day(s) in advance"
|
|
checkbutton $w.advcount -text "not counting holidays/weekend"
|
|
$w.advcount select
|
|
pack $w.advbut $w.advdays $w.advlab $w.advcount -side left -anchor w -in $w.adv
|
|
|
|
# WEEKEND
|
|
label $w.weeklab -text "Weekend is: "
|
|
pack $w.weeklab -side left -anchor w -in $w.weekend
|
|
foreach d $EnglishDayNames {
|
|
checkbutton $w.d$d -text $d
|
|
$w.d$d deselect
|
|
pack $w.d$d -side left -anchor w -in $w.weekend
|
|
}
|
|
$w.dSaturday select
|
|
$w.dSunday select
|
|
|
|
# TIMED REMINDER
|
|
checkbutton $w.timebut -text "Timed reminder at"
|
|
$w.timebut deselect
|
|
menubutton $w.timehour -text "12" -menu $w.timehour.menu -relief raised
|
|
CreateDayMenu $w.timehour 1 12 0
|
|
menubutton $w.timemin -text "00" -menu $w.timemin.menu -relief raised
|
|
menu $w.timemin.menu -tearoff 0
|
|
$w.timemin.menu add command -label "00" -command "$w.timemin configure -text {00}"
|
|
$w.timemin.menu add command -label "15" -command "$w.timemin configure -text {15}"
|
|
$w.timemin.menu add command -label "30" -command "$w.timemin configure -text {30}"
|
|
$w.timemin.menu add command -label "45" -command "$w.timemin configure -text {45}"
|
|
|
|
menubutton $w.ampm -text "PM" -menu $w.ampm.menu -relief raised
|
|
menu $w.ampm.menu -tearoff 0
|
|
$w.ampm.menu add command -label "AM" -command "$w.ampm configure -text {AM}"
|
|
$w.ampm.menu add command -label "PM" -command "$w.ampm configure -text {PM}"
|
|
|
|
checkbutton $w.timeadvbut -text "with"
|
|
$w.timeadvbut deselect
|
|
menubutton $w.timeadv -text "15" -menu $w.timeadv.menu -relief raised
|
|
menu $w.timeadv.menu -tearoff 0
|
|
foreach i {5 10 15 30 45 60} {
|
|
$w.timeadv.menu add command -label $i -command "$w.timeadv configure -text $i"
|
|
}
|
|
label $w.timelab1 -text "minutes advance notice"
|
|
|
|
checkbutton $w.timerepbut -text "repeated every"
|
|
$w.timerepbut deselect
|
|
menubutton $w.timerep -text "5" -menu $w.timerep.menu -relief raised
|
|
menu $w.timerep.menu -tearoff 0
|
|
foreach i {3 5 10 15 30} {
|
|
$w.timerep.menu add command -label $i -command "$w.timerep configure -text $i"
|
|
}
|
|
label $w.timelab2 -text "minutes"
|
|
pack $w.timebut $w.timehour $w.timemin $w.ampm $w.timeadvbut $w.timeadv $w.timelab1 $w.timerepbut $w.timerep $w.timelab2 -side left -anchor w -in $w.time
|
|
|
|
# SKIP TYPE
|
|
label $w.labhol -text "On holidays or weekends:"
|
|
radiobutton $w.issue -variable SkipType -value 1 -text "Issue reminder as usual"
|
|
radiobutton $w.skip -variable SkipType -value 2 -text "Skip reminder"
|
|
radiobutton $w.before -variable SkipType -value 3 -text "Move reminder before holiday or weekend"
|
|
radiobutton $w.after -variable SkipType -value 4 -text "Move reminder after holiday or weekend"
|
|
pack $w.labhol $w.issue $w.skip $w.before $w.after -side top -anchor w -in $w.hol
|
|
|
|
# TEXT ENTRY
|
|
label $w.msglab -text "Body:"
|
|
entry $w.entry
|
|
pack $w.msglab -side left -anchor w -in $w.msg
|
|
pack $w.entry -side left -anchor w -expand 1 -fill x -in $w.msg
|
|
|
|
# BUTTONS
|
|
set nbut 0
|
|
foreach but $args {
|
|
incr nbut
|
|
button $w.but$nbut -text $but -command "set ModifyDialogResult $nbut"
|
|
pack $w.but$nbut -side left -anchor w -in $w.buttons -expand 1 -fill x
|
|
}
|
|
|
|
bind $w <KeyPress-Escape> "$w.but1 invoke"
|
|
set ModifyDialogResult 0
|
|
|
|
# Center the window on the root
|
|
CenterWindow $w
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: RemindDialogToOptions
|
|
# %ARGUMENTS:
|
|
# w -- dialog window
|
|
# %RETURNS:
|
|
# A list of flag/value pairs representing the current state of
|
|
# the "create reminder" dialog.
|
|
#***********************************************************************
|
|
proc RemindDialogToOptions { w } {
|
|
global OptionType SkipType repbut expbut advbut advcount
|
|
global timebut timeadvbut timerepbut
|
|
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
|
set ans {}
|
|
lappend ans "-global-OptionType" $OptionType
|
|
lappend ans "-global-SkipType" $SkipType
|
|
foreach win [winfo children $w] {
|
|
set winstem [winfo name $win]
|
|
switch -exact -- [winfo class $win] {
|
|
"Menubutton" {
|
|
lappend ans "-text-$winstem" [$win cget -text]
|
|
}
|
|
"Checkbutton" {
|
|
lappend ans "-global-$winstem" [eval set $winstem]
|
|
}
|
|
"Entry" {
|
|
lappend ans "-entry-$winstem" [$win get]
|
|
}
|
|
}
|
|
}
|
|
return $ans
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: OptionsToRemindDialog
|
|
# %ARGUMENTS:
|
|
# w -- Remind dialog window
|
|
# opts -- option list set by RemindDialogToOptions
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Sets parameters in the dialog box according to saved options.
|
|
#***********************************************************************
|
|
proc OptionsToRemindDialog { w opts } {
|
|
global OptionType SkipType repbut expbut advbut advcount
|
|
global timebut timeadvbut timerepbut
|
|
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
|
foreach {flag value} $opts {
|
|
switch -glob -- $flag {
|
|
"-text-*" {
|
|
set win [string range $flag 6 end]
|
|
$w.$win configure -text $value
|
|
}
|
|
"-global-*" {
|
|
set win [string range $flag 8 end]
|
|
set $win $value
|
|
}
|
|
"-entry-*" {
|
|
set win [string range $flag 7 end]
|
|
$w.$win delete 0 end
|
|
$w.$win insert end $value
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateMonthMenu -- create a menu with all the months of the year
|
|
# Arguments:
|
|
# w -- menu button -- becomes parent of menu
|
|
# every -- if true, include an "every month" entry
|
|
#---------------------------------------------------------------------------
|
|
proc CreateMonthMenu {w {every 1}} {
|
|
global MonthNames
|
|
menu $w.menu -tearoff 0
|
|
|
|
if {$every} {
|
|
$w.menu add command -label "every month" -command "$w configure -text {every month}"
|
|
}
|
|
|
|
foreach month $MonthNames {
|
|
$w.menu add command -label $month -command "$w configure -text $month"
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateWeekdayMenu -- create a menu with all the weekdays
|
|
# Arguments:
|
|
# w -- menu button -- becomes parent of menu
|
|
#---------------------------------------------------------------------------
|
|
proc CreateWeekdayMenu {w} {
|
|
global EnglishDayNames
|
|
menu $w.menu -tearoff 0
|
|
|
|
foreach d $EnglishDayNames {
|
|
$w.menu add command -label $d -command "$w configure -text $d"
|
|
}
|
|
$w.menu add command -label "weekday" -command "$w configure -text weekday"
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateDayMenu -- create a menu with entries 1-31 and possibly "every day"
|
|
# Arguments:
|
|
# w -- menu button -- becomes parent of menu
|
|
# min -- minimum day to start from.
|
|
# max -- maximum day to go up to
|
|
# every -- if true, include an "every day" entry
|
|
#---------------------------------------------------------------------------
|
|
proc CreateDayMenu {w {min 1} {max 31} {every 1}} {
|
|
menu $w.menu -tearoff 0
|
|
if {$every} {
|
|
$w.menu add command -label "every day" -command "$w configure -text {every day}"
|
|
}
|
|
set d $min
|
|
while { $d <= $max } {
|
|
$w.menu add command -label $d -command "$w configure -text $d"
|
|
incr d
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateYearMenu -- create a menu with entries from this year to this year+10
|
|
# and possibly "every year"
|
|
# Arguments:
|
|
# w -- menu button -- becomes parent of menu
|
|
# every -- if true, include an "every year" entry
|
|
#---------------------------------------------------------------------------
|
|
proc CreateYearMenu {w {every 1}} {
|
|
menu $w.menu -tearoff 0
|
|
if {$every} {
|
|
$w.menu add command -label "every year" -command "$w configure -text {every year}"
|
|
}
|
|
global CurYear
|
|
set d $CurYear
|
|
while { $d < [expr $CurYear + 11] } {
|
|
$w.menu add command -label $d -command "$w configure -text $d"
|
|
incr d
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# ModifyDay -- bring up dialog for adding reminder.
|
|
# Arguments:
|
|
# d -- which day to modify
|
|
# firstDay -- first weekday in month (0-6)
|
|
#---------------------------------------------------------------------------
|
|
proc ModifyDay {d firstDay} {
|
|
global ModifyDialogResult AppendFile HighestTagSoFar ReminderTags
|
|
catch {destroy .mod}
|
|
toplevel .mod
|
|
CreateModifyDialog .mod $d $firstDay "Cancel" "Add to reminder file" "Preview reminder"
|
|
wm title .mod "TkRemind Add Reminder..."
|
|
wm iconname .mod "Add Reminder"
|
|
tkwait visibility .mod
|
|
set oldFocus [focus]
|
|
while {1} {
|
|
grab .mod
|
|
focus .mod.entry
|
|
set ModifyDialogResult -1
|
|
tkwait variable ModifyDialogResult
|
|
if {$ModifyDialogResult == 1} {
|
|
catch {focus $oldFocus}
|
|
destroy .mod
|
|
return 0
|
|
}
|
|
set problem [catch {set rem [CreateReminder .mod]} err]
|
|
if {$problem} {
|
|
tk_dialog .error Error "$err" error 0 Ok
|
|
} else {
|
|
if {$ModifyDialogResult == 3} {
|
|
set rem [EditReminder $rem Cancel "Add reminder"]
|
|
if {$ModifyDialogResult == 1} {
|
|
continue
|
|
}
|
|
}
|
|
set opts [RemindDialogToOptions .mod]
|
|
catch {focus $oldFocus}
|
|
destroy .mod
|
|
Status "Writing reminder..."
|
|
set f [open $AppendFile a]
|
|
incr HighestTagSoFar
|
|
set ReminderTags($HighestTagSoFar) 1
|
|
|
|
WriteReminder $f TKTAG$HighestTagSoFar $rem $opts
|
|
close $f
|
|
|
|
FillCalWindow
|
|
RestartBackgroundRemindDaemon
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CenterWindow -- center a window on the screen. Stolen from tk_dialog code
|
|
# Arguments:
|
|
# w -- window to center
|
|
#---------------------------------------------------------------------------
|
|
proc CenterWindow {w} {
|
|
wm withdraw $w
|
|
update idletasks
|
|
set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
|
|
- [winfo vrootx [winfo parent $w]]]
|
|
set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
|
|
- [winfo vrooty [winfo parent $w]]]
|
|
wm geom $w +$x+$y
|
|
wm deiconify $w
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateReminder -- create the reminder
|
|
# Arguments:
|
|
# w -- the window containing the add reminder dialog box.
|
|
# Returns:
|
|
# The reminder as a string.
|
|
#---------------------------------------------------------------------------
|
|
proc CreateReminder {w} {
|
|
global DidOmit
|
|
|
|
set body [string trim [$w.entry get]]
|
|
|
|
if {"$body" == ""} {
|
|
error "Blank body in reminder"
|
|
}
|
|
|
|
set DidOmit 0
|
|
set needOmit 0
|
|
# Delegate the first part to CreateReminder1, CreateReminder2, or
|
|
# CreateReminder3
|
|
global OptionType SkipType repbut expbut advbut advcount
|
|
global timebut timeadvbut timerepbut
|
|
|
|
set rem [CreateReminder$OptionType $w]
|
|
|
|
# Do the "until" part
|
|
if {$expbut} {
|
|
append rem " UNTIL [$w.expday cget -text] [$w.expmon cget -text] [$w.expyear cget -text]"
|
|
}
|
|
|
|
# Advance warning
|
|
if {$advbut} {
|
|
append rem " +"
|
|
if {!$advcount} {
|
|
append rem "+"
|
|
} else {
|
|
set needOmit 1
|
|
}
|
|
append rem [$w.advdays cget -text]
|
|
}
|
|
|
|
# Timed reminder
|
|
if {$timebut} {
|
|
set hour [$w.timehour cget -text]
|
|
set min [$w.timemin cget -text]
|
|
if {[$w.ampm cget -text] == "PM"} {
|
|
if {$hour < 12} {
|
|
incr hour 12
|
|
}
|
|
} else {
|
|
if {$hour == 12} {
|
|
set hour 0
|
|
}
|
|
}
|
|
append rem " AT $hour:$min"
|
|
if {$timeadvbut} {
|
|
append rem " +[$w.timeadv cget -text]"
|
|
}
|
|
if {$timerepbut} {
|
|
append rem " *[$w.timerep cget -text]"
|
|
}
|
|
}
|
|
|
|
global SkipType
|
|
if {$SkipType == 2} {
|
|
append rem " SKIP"
|
|
set needOmit 1
|
|
} elseif {$SkipType == 3} {
|
|
append rem " BEFORE"
|
|
set needOmit 1
|
|
} elseif {$SkipType == 4} {
|
|
append rem " AFTER"
|
|
set needOmit 1
|
|
}
|
|
|
|
if {$needOmit && !$DidOmit} {
|
|
append rem " OMIT [GetWeekend $w 1]"
|
|
}
|
|
|
|
|
|
# Check it out!
|
|
global Remind
|
|
set f [open "|$Remind -arq -e -" r+]
|
|
puts $f "BANNER %"
|
|
puts $f "$rem MSG %"
|
|
puts $f "MSG %_%_%_%_"
|
|
puts $f "FLUSH"
|
|
flush $f
|
|
set err {}
|
|
catch {set err [gets $f]}
|
|
catch {close $f}
|
|
if {"$err" != ""} {
|
|
# Clean up the message a bit
|
|
regsub -- {^-stdin-\([0-9]*\): } $err {} err
|
|
error "Error from Remind: $err"
|
|
}
|
|
append rem " MSG $body"
|
|
return $rem
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateReminder1 -- Create the first part of a type-1 reminder
|
|
# Arguments:
|
|
# w -- add reminder dialog window
|
|
# Returns: first part of reminder
|
|
#---------------------------------------------------------------------------
|
|
proc CreateReminder1 {w} {
|
|
|
|
global repbut
|
|
|
|
set rem "REM"
|
|
set gotDay 0
|
|
set gotMon 0
|
|
set gotYear 0
|
|
set d [$w.day1 cget -text]
|
|
if {"$d" != "every day"} {
|
|
append rem " $d"
|
|
set gotDay 1
|
|
}
|
|
set m [$w.mon1 cget -text]
|
|
if {"$m" != "every month"} {
|
|
append rem " $m"
|
|
set gotMon 1
|
|
}
|
|
set y [$w.year1 cget -text]
|
|
if {"$y" != "every year"} {
|
|
append rem " $y"
|
|
set gotYear 1
|
|
}
|
|
|
|
# Check for repetition
|
|
if {$repbut} {
|
|
if {!$gotDay || !$gotMon || !$gotYear} {
|
|
error "All components of a date must be specified if you wish to use the repeat feature."
|
|
}
|
|
append rem " *[$w.repdays cget -text]"
|
|
}
|
|
|
|
return $rem
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateReminder2 -- Create the first part of a type-2 reminder
|
|
# Arguments:
|
|
# w -- add reminder dialog window
|
|
# Returns: first part of reminder
|
|
#---------------------------------------------------------------------------
|
|
proc CreateReminder2 {w} {
|
|
set wkday [$w.wkday2 cget -text]
|
|
if {"$wkday" == "weekday"} {
|
|
set wkday [GetWeekend $w 0]
|
|
}
|
|
set day [$w.day2 cget -text]
|
|
set mon [$w.mon2 cget -text]
|
|
set year [$w.year2 cget -text]
|
|
set rem "REM $wkday $day"
|
|
if {$mon != "every month"} {
|
|
append rem " $mon"
|
|
}
|
|
if {$year != "every year"} {
|
|
append rem " $year"
|
|
}
|
|
return $rem
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# CreateReminder3 -- Create the first part of a type-3 reminder
|
|
# Arguments:
|
|
# w -- add reminder dialog window
|
|
# Returns: first part of reminder
|
|
#---------------------------------------------------------------------------
|
|
proc CreateReminder3 {w} {
|
|
global MonthNames DidOmit
|
|
set which [$w.ordinal cget -text]
|
|
set day [$w.wkday3 cget -text]
|
|
set mon [$w.mon3 cget -text]
|
|
set year [$w.year3 cget -text]
|
|
set rem "REM"
|
|
if {$which != "Last"} {
|
|
if {$which == "First"} {
|
|
append rem " 1"
|
|
} elseif {$which == "Second"} {
|
|
append rem " 8"
|
|
} elseif {$which == "Third"} {
|
|
append rem " 15"
|
|
} elseif {$which == "Fourth"} {
|
|
append rem " 22"
|
|
}
|
|
if {$day != "weekday"} {
|
|
append rem " $day"
|
|
} else {
|
|
append rem " [GetWeekend $w 0]"
|
|
}
|
|
if {$mon != "every month"} {
|
|
append rem " $mon"
|
|
}
|
|
if {$year != "every year"} {
|
|
append rem " $year"
|
|
}
|
|
} else {
|
|
if {$day != "weekday"} {
|
|
append rem " $day 1 --7"
|
|
} else {
|
|
append rem " 1 -1 OMIT [GetWeekend $w 1]"
|
|
set DidOmit 1
|
|
}
|
|
if {$mon != "every month"} {
|
|
set i [lsearch -exact $MonthNames $mon]
|
|
if {$i == 11} {
|
|
set i 0
|
|
} else {
|
|
incr i
|
|
}
|
|
append rem " [lindex $MonthNames $i]"
|
|
}
|
|
if {$year != "every year"} {
|
|
if {$mon == "December"} {
|
|
incr year
|
|
}
|
|
append rem " $year"
|
|
}
|
|
}
|
|
return $rem
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# GetWeekend -- returns a list of weekdays or weekend days
|
|
# Arguments:
|
|
# w -- add reminder dialog window
|
|
# wkend -- if 1, we want weekend. If 0, we want weekdays.
|
|
# Returns:
|
|
# list of weekdays or weekend-days
|
|
#---------------------------------------------------------------------------
|
|
proc GetWeekend {w wkend} {
|
|
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
|
global EnglishDayNames
|
|
set ret {}
|
|
foreach d $EnglishDayNames {
|
|
set v [set d$d]
|
|
if {$v == $wkend} {
|
|
lappend ret $d
|
|
}
|
|
}
|
|
return $ret
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# EditReminder -- allow user to edit what gets put in reminder file
|
|
# Arguments:
|
|
# rem -- current reminder
|
|
# args -- buttons to add to bottom
|
|
# Returns:
|
|
# edited version of rem
|
|
#---------------------------------------------------------------------------
|
|
proc EditReminder {rem args} {
|
|
catch {destroy .edit}
|
|
global ModifyDialogResult
|
|
toplevel .edit
|
|
wm title .edit "TkRemind Preview reminder"
|
|
wm iconname .edit "Preview reminder"
|
|
text .edit.t -width 80 -height 5 -relief sunken
|
|
.edit.t insert end $rem
|
|
frame .edit.f
|
|
set n 0
|
|
foreach but $args {
|
|
incr n
|
|
button .edit.but$n -text $but -command "set ModifyDialogResult $n"
|
|
pack .edit.but$n -in .edit.f -side left -fill x -expand 1
|
|
}
|
|
pack .edit.t -side top -fill both -expand 1
|
|
pack .edit.f -side top -fill x -expand 1
|
|
bind .edit <KeyPress-Escape> ".edit.but1 invoke"
|
|
set ModifyDialogResult 0
|
|
CenterWindow .edit
|
|
tkwait visibility .edit
|
|
set oldFocus [focus]
|
|
focus .edit.t
|
|
grab .edit
|
|
tkwait variable ModifyDialogResult
|
|
catch {focus $oldFocus}
|
|
set rem [.edit.t get 1.0 end]
|
|
catch {destroy .edit}
|
|
return $rem
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# SetWinAttr -- sets an attribute for a window
|
|
# Arguments:
|
|
# w -- window name
|
|
# attr -- attribute name
|
|
# val -- value to set it to
|
|
# Returns:
|
|
# $val
|
|
#---------------------------------------------------------------------------
|
|
proc SetWinAttr {w attr val} {
|
|
global attrPriv
|
|
set attrPriv($w-$attr) $val
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# GetWinAttr -- gets an attribute for a window
|
|
# Arguments:
|
|
# w -- window name
|
|
# attr -- attribute name
|
|
# Returns:
|
|
# Value of attribute
|
|
#---------------------------------------------------------------------------
|
|
proc GetWinAttr {w attr} {
|
|
global attrPriv
|
|
return $attrPriv($w-$attr)
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# WaitWinAttr -- wait for a window attribute to change
|
|
# Arguments:
|
|
# w -- window name
|
|
# attr -- attribute name
|
|
# Returns:
|
|
# Value of attribute
|
|
#---------------------------------------------------------------------------
|
|
proc WaitWinAttr {w attr} {
|
|
global attrPriv
|
|
tkwait variable attrPriv($w-$attr)
|
|
return $attrPriv($w-$attr)
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# BrowseForFile -- creates and operates a file browser dialog.
|
|
# Arguments:
|
|
# w -- dialog window.
|
|
# title -- dialog title
|
|
# oktext -- text for "OK" button
|
|
# showdots -- if non-zero, shows "dot" files as well.
|
|
# Returns:
|
|
# complete path of filename chosen, or "" if Cancel pressed.
|
|
#---------------------------------------------------------------------------
|
|
proc BrowseForFile {w title {oktext "OK"} {showdots 0} {filter "*"}} {
|
|
catch {destroy $w}
|
|
toplevel $w
|
|
wm title $w $title
|
|
|
|
# Global array to hold window attributes
|
|
global a${w}
|
|
|
|
SetWinAttr $w status busy
|
|
SetWinAttr $w showdots $showdots
|
|
|
|
frame $w.fileframe
|
|
frame $w.butframe
|
|
label $w.cwd -text [pwd]
|
|
entry $w.entry
|
|
label $w.masklab -text "Match: "
|
|
listbox $w.list -yscrollcommand "$w.scroll set"
|
|
scrollbar $w.scroll -command "$w.list yview"
|
|
button $w.ok -text $oktext -command "BrowseForFileOK $w"
|
|
button $w.cancel -text "Cancel" -command "BrowseForFileCancel $w"
|
|
entry $w.filter -width 7
|
|
$w.filter insert end $filter
|
|
|
|
pack $w.cwd $w.entry -side top -expand 0 -fill x
|
|
pack $w.fileframe -side top -expand 1 -fill both
|
|
pack $w.butframe -side top -expand 0 -fill x
|
|
pack $w.list -in $w.fileframe -side left -expand 1 -fill both
|
|
pack $w.scroll -in $w.fileframe -side left -expand 0 -fill y
|
|
pack $w.ok -in $w.butframe -side left -expand 1 -fill x
|
|
pack $w.cancel -in $w.butframe -side left -expand 1 -fill x
|
|
pack $w.masklab -in $w.butframe -side left -expand 0
|
|
pack $w.filter -in $w.butframe -side left -expand 1 -fill x
|
|
|
|
# Fill in the box and wait for status to change
|
|
BrowseForFileRead $w [pwd]
|
|
|
|
bind $w <KeyPress-Escape> "$w.cancel flash; $w.cancel invoke"
|
|
bind $w.list <Button-1> "$w.entry delete 0 end; $w.entry insert 0 \[selection get\]"
|
|
bind $w.list <Double-Button-1> "$w.ok flash; $w.ok invoke"
|
|
bind $w.list <Return> "$w.entry delete 0 end; $w.entry insert 0 \[selection get\]; $w.ok flash; $w.ok invoke"
|
|
bind $w.entry <Return> "$w.ok flash; $w.ok invoke"
|
|
bind $w.filter <Return> "BrowseForFileRead $w"
|
|
bind $w.entry <KeyPress> "CompleteFile $w"
|
|
bind $w.entry <KeyPress-space> "ExpandFile $w"
|
|
bindtags $w.entry "Entry $w.entry $w all"
|
|
|
|
bindtags $w.list "Listbox $w.list $w all"
|
|
CenterWindow $w
|
|
set oldFocus [focus]
|
|
tkwait visibility $w
|
|
focus $w.entry
|
|
set oldGrab [grab current $w]
|
|
grab set $w
|
|
WaitWinAttr $w status
|
|
catch {focus $oldFocus}
|
|
catch {grab set $oldGrab}
|
|
set ans [GetWinAttr $w status]
|
|
destroy $w
|
|
return $ans
|
|
}
|
|
|
|
proc CompleteFile {w} {
|
|
set index [lsearch [$w.list get 0 end] [$w.entry get]* ]
|
|
if {$index > -1} {
|
|
$w.list see $index
|
|
$w.list selection clear 0 end
|
|
$w.list selection set $index
|
|
}
|
|
}
|
|
|
|
proc ExpandFile {w} {
|
|
set stuff [$w.list curselection]
|
|
if {[string compare $stuff ""]} {
|
|
$w.entry delete 0 end
|
|
$w.entry insert end [$w.list get $stuff]
|
|
}
|
|
}
|
|
|
|
proc BrowseForFileCancel {w} {
|
|
SetWinAttr $w status {}
|
|
}
|
|
|
|
proc BrowseForFileOK {w} {
|
|
set fname [$w.entry get]
|
|
if {[string compare $fname ""]} {
|
|
# If it starts with a slash, handle it specially.
|
|
if {[string match "/*" $fname]} {
|
|
if {[file isdirectory $fname]} {
|
|
BrowseForFileRead $w $fname
|
|
return
|
|
} else {
|
|
SetWinAttr $w status $fname
|
|
return
|
|
}
|
|
}
|
|
if {[string match */ $fname]} {
|
|
set fname [string trimright $fname /]
|
|
}
|
|
if {[$w.cwd cget -text] == "/"} {
|
|
set fname "/$fname"
|
|
} else {
|
|
set fname "[$w.cwd cget -text]/$fname"
|
|
}
|
|
# If it's a directory, change directories
|
|
if {[file isdirectory $fname]} {
|
|
BrowseForFileRead $w $fname
|
|
} else {
|
|
SetWinAttr $w status $fname
|
|
}
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# BrowseForFileRead -- read the current directory into the file browser
|
|
# Arguments:
|
|
# w -- window name
|
|
# dir -- directory
|
|
# Returns:
|
|
# nothing
|
|
#---------------------------------------------------------------------------
|
|
proc BrowseForFileRead {w {dir ""}} {
|
|
# Save working dir
|
|
set cwd [pwd]
|
|
if {$dir == ""} {
|
|
set dir [$w.cwd cget -text]
|
|
}
|
|
if {[catch "cd $dir" err]} {
|
|
tk_dialog .error Error "$err" error 0 Ok
|
|
return
|
|
}
|
|
$w.cwd configure -text [pwd]
|
|
if {[GetWinAttr $w showdots]} {
|
|
set flist [glob -nocomplain .* *]
|
|
} else {
|
|
set flist [glob -nocomplain *]
|
|
}
|
|
set flist [lsort $flist]
|
|
set filter [$w.filter get]
|
|
if {$filter == ""} {
|
|
set filter "*"
|
|
}
|
|
$w.list delete 0 end
|
|
foreach item $flist {
|
|
if {$item != "." && $item != ".."} {
|
|
if {[file isdirectory $item]} {
|
|
$w.list insert end "$item/"
|
|
} else {
|
|
if {[string match $filter $item]} {
|
|
$w.list insert end $item
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if {[pwd] != "/"} {
|
|
$w.list insert 0 "../"
|
|
}
|
|
cd $cwd
|
|
$w.entry delete 0 end
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# StartBackgroundRemindDaemon
|
|
# Arguments:
|
|
# none
|
|
# Returns:
|
|
# nothing
|
|
# Description:
|
|
# Starts a background Remind daemon to handle timed reminders
|
|
#---------------------------------------------------------------------------
|
|
proc StartBackgroundRemindDaemon {} {
|
|
global Remind DaemonFile ReminderFile
|
|
set problem [catch { set DaemonFile [open "|$Remind -z0 $ReminderFile" "r+"] } err]
|
|
if {$problem} {
|
|
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
|
|
} else {
|
|
fileevent $DaemonFile readable "DaemonReadable $DaemonFile"
|
|
puts $DaemonFile "STATUS"
|
|
flush $DaemonFile
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# StopBackgroundRemindDaemon
|
|
# Arguments:
|
|
# none
|
|
# Returns:
|
|
# nothing
|
|
# Description:
|
|
# Stops the background Remind daemon
|
|
#---------------------------------------------------------------------------
|
|
proc StopBackgroundRemindDaemon {} {
|
|
global DaemonFile
|
|
catch {
|
|
puts $DaemonFile "EXIT"
|
|
flush $DaemonFile
|
|
close $DaemonFile
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# RestartBackgroundRemindDaemon
|
|
# Arguments:
|
|
# none
|
|
# Returns:
|
|
# nothing
|
|
# Description:
|
|
# Restarts the background Remind daemon
|
|
#---------------------------------------------------------------------------
|
|
proc RestartBackgroundRemindDaemon {} {
|
|
global DaemonFile
|
|
catch {
|
|
puts $DaemonFile "REREAD"
|
|
flush $DaemonFile
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# DaemonReadable
|
|
# Arguments:
|
|
# file -- file channel that is readable
|
|
# Returns:
|
|
# nothing
|
|
# Description:
|
|
# Reads data from the Remind daemon and handles it appropriately
|
|
#---------------------------------------------------------------------------
|
|
proc DaemonReadable { file } {
|
|
global Ignore
|
|
set line ""
|
|
catch { set num [gets $file line] }
|
|
if {$num < 0} {
|
|
catch { close $file }
|
|
return
|
|
}
|
|
switch -glob -- $line {
|
|
"NOTE reminder*" {
|
|
scan $line "NOTE reminder %s %s %s" time now tag
|
|
IssueBackgroundReminder $file $time $now $tag
|
|
}
|
|
"NOTE newdate" {
|
|
# Date has rolled over -- clear "ignore" list
|
|
catch { unset Ignore}
|
|
Initialize
|
|
FillCalWindow
|
|
}
|
|
"NOTE reread" {
|
|
puts $file "STATUS"
|
|
flush $file
|
|
}
|
|
"NOTE queued*" {
|
|
scan $line "NOTE queued %d" n
|
|
if {$n == 1} {
|
|
.b.nqueued configure -text "1 reminder queued"
|
|
} else {
|
|
.b.nqueued configure -text "$n reminders queued"
|
|
}
|
|
}
|
|
default {
|
|
puts "Unknown message from daemon: $line\n"
|
|
}
|
|
}
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
# IssueBackgroundReminder
|
|
# Arguments:
|
|
# file -- file channel that is readable
|
|
# time -- time of reminder
|
|
# now -- current time according to Remind daemon
|
|
# tag -- tag for reminder, or "*" if no tag
|
|
# Returns:
|
|
# nothing
|
|
# Description:
|
|
# Reads a background reminder from daemon and pops up window.
|
|
#---------------------------------------------------------------------------
|
|
proc IssueBackgroundReminder { file time now tag } {
|
|
global BgCounter Option Ignore
|
|
if {$Option(Deiconify)} {
|
|
wm deiconify .
|
|
}
|
|
|
|
set msg ""
|
|
set line ""
|
|
while (1) {
|
|
gets $file line
|
|
if {$line == "NOTE endreminder"} {
|
|
break
|
|
}
|
|
if {$msg != ""} {
|
|
append msg "\n";
|
|
}
|
|
append msg $line
|
|
}
|
|
# Do nothing if it's blank -- was probably a RUN-type reminder.
|
|
if {$msg == ""} {
|
|
return
|
|
}
|
|
|
|
# Do nothing if user told us to ignore this reminder
|
|
if {[info exists Ignore($tag)]} {
|
|
return
|
|
}
|
|
|
|
incr BgCounter
|
|
set w .bg$BgCounter
|
|
toplevel $w
|
|
wm iconname $w "Reminder"
|
|
wm title $w "Timed reminder ($time)"
|
|
label $w.l -text "Reminder for $time issued at $now"
|
|
message $w.msg -width 6i -text $msg
|
|
frame $w.b
|
|
button $w.ok -text "OK" -command "destroy $w"
|
|
if {$tag != "*"} {
|
|
button $w.nomore -text "Don't remind me again" -command \
|
|
"destroy $w; set Ignore($tag) 1"
|
|
}
|
|
pack $w.l -side top
|
|
pack $w.msg -side top -expand 1 -fill both
|
|
pack $w.b -side top
|
|
pack $w.ok -in $w.b -side left
|
|
if {$tag != "*"} {
|
|
pack $w.nomore -in $w.b -side left
|
|
}
|
|
|
|
CenterWindow $w
|
|
|
|
# Automatically shut down window after a minute if option says so
|
|
if {$Option(AutoClose)} {
|
|
after 60000 "catch { destroy $w }"
|
|
}
|
|
|
|
update
|
|
if {$Option(RingBell)} {
|
|
bell
|
|
}
|
|
if {$Option(RunCmd) != ""} {
|
|
if {$Option(FeedReminder)} {
|
|
FeedReminderToCommand $Option(RunCmd) $msg
|
|
} else {
|
|
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
|
}
|
|
}
|
|
|
|
# reread status
|
|
if {$file != "stdin"} {
|
|
puts $file "STATUS"
|
|
flush $file
|
|
}
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: FeedReminderToCommand
|
|
# %ARGUMENTS:
|
|
# cmd -- command to execute
|
|
# msg -- what to feed it
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Feeds "$msg" to a command.
|
|
#***********************************************************************
|
|
proc FeedReminderToCommand { cmd msg } {
|
|
catch {
|
|
set f [open "|$cmd" "w"]
|
|
fconfigure $f -blocking 0
|
|
fileevent $f writable [list CommandWritable $f $msg]
|
|
}
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: CommandWritable
|
|
# %ARGUMENTS:
|
|
# f -- file which is writable
|
|
# msg -- message to write
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Writes $msg to $f; closes $f.
|
|
#***********************************************************************
|
|
proc CommandWritable { f msg } {
|
|
puts $f $msg
|
|
flush $f
|
|
close $f
|
|
}
|
|
|
|
|
|
proc main {} {
|
|
global AppendFile HighestTagSoFar DayNames
|
|
puts "\nTkRemind Copyright (c) 1996-1998 by David F. Skoll\n"
|
|
LoadOptions
|
|
CreateMoonImages
|
|
Initialize
|
|
ScanForTags $AppendFile
|
|
CreateCalWindow $DayNames
|
|
FillCalWindow
|
|
StartBackgroundRemindDaemon
|
|
DisplayTimeContinuously
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: ScanForTags
|
|
# %ARGUMENTS:
|
|
# fname -- name of file to scan
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Scans the file for all tags of the form "TKTAGnnnn" and builds
|
|
# the tag array. Also adjusts HighestTagSoFar
|
|
#***********************************************************************
|
|
proc ScanForTags { fname } {
|
|
global HighestTagSoFar ReminderTags
|
|
if {[catch { set f [open $fname "r"]}]} {
|
|
return
|
|
}
|
|
while {[gets $f line] >= 0} {
|
|
switch -regexp -- $line {
|
|
{^# TKTAG[0-9]+} {
|
|
regexp {^# TKTAG([0-9]+)} $line dummy tagno
|
|
if {$tagno > $HighestTagSoFar} {
|
|
set HighestTagSoFar $tagno
|
|
}
|
|
set ReminderTags($tagno) 1
|
|
}
|
|
}
|
|
}
|
|
close $f
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: ReadTaggedOptions
|
|
# %ARGUMENTS:
|
|
# tag -- tag to match
|
|
# %RETURNS:
|
|
# A list of options for the dialog box for the tagged reminder
|
|
# %DESCRIPTION:
|
|
# Scans the file for specified tag and returns the "options" list for the
|
|
# reminder.
|
|
#***********************************************************************
|
|
proc ReadTaggedOptions { tag } {
|
|
global AppendFile
|
|
if {[catch { set f [open $AppendFile "r"]}]} {
|
|
return ""
|
|
}
|
|
while {[gets $f line] >= 0} {
|
|
if {[string match "# $tag *" $line]} {
|
|
gets $f line
|
|
close $f
|
|
return [string range $line 2 end]
|
|
}
|
|
}
|
|
close $f
|
|
return ""
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: GetCurrentReminder
|
|
# %ARGUMENTS:
|
|
# w -- text window
|
|
# %RETURNS:
|
|
# The tag (TKTAGnnnn) for current editable reminder, or "" if no
|
|
# current editable reminder.
|
|
#***********************************************************************
|
|
proc GetCurrentReminder { w } {
|
|
set tags [$w tag names current]
|
|
set index [lsearch -glob $tags "TKTAG*"]
|
|
if {$index < 0} {
|
|
return ""
|
|
}
|
|
set tag [lindex $tags $index]
|
|
return $tag
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: TaggedEnter
|
|
# %ARGUMENTS:
|
|
# w -- text window
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Highlights an "editable" reminder as mouse moves into it
|
|
#***********************************************************************
|
|
proc TaggedEnter { w } {
|
|
set tag [GetCurrentReminder $w]
|
|
if {$tag != ""} {
|
|
$w tag configure $tag -foreground #FF0000
|
|
}
|
|
}
|
|
#***********************************************************************
|
|
# %PROCEDURE: TaggedLeave
|
|
# %ARGUMENTS:
|
|
# w -- text window
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Removes highlight from an "editable" reminder as mouse leaves it
|
|
#***********************************************************************
|
|
proc TaggedLeave { w } {
|
|
set tag [GetCurrentReminder $w]
|
|
if {$tag != ""} {
|
|
$w tag configure $tag -foreground #000000
|
|
}
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: EditTaggedReminder
|
|
# %ARGUMENTS:
|
|
# w -- text window
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Opens a dialog box to edit the current editable reminder
|
|
#***********************************************************************
|
|
proc EditTaggedReminder { w } {
|
|
global ModifyDialogResult
|
|
set tag [GetCurrentReminder $w]
|
|
if {$tag == ""} {
|
|
return
|
|
}
|
|
|
|
# Read in options
|
|
set opts [ReadTaggedOptions $tag]
|
|
if {$opts == ""} {
|
|
return
|
|
}
|
|
|
|
toplevel .mod
|
|
CreateModifyDialog .mod 1 0 "Cancel" "Replace reminder" "Delete reminder" "Preview reminder"
|
|
wm title .mod "TkRemind Edit Reminder..."
|
|
wm iconname .mod "Edit Reminder"
|
|
OptionsToRemindDialog .mod $opts
|
|
|
|
tkwait visibility .mod
|
|
set oldFocus [focus]
|
|
while {1} {
|
|
grab .mod
|
|
focus .mod.entry
|
|
set ModifyDialogResult -1
|
|
tkwait variable ModifyDialogResult
|
|
if {$ModifyDialogResult == 1} {
|
|
catch {focus $oldFocus}
|
|
destroy .mod
|
|
return 0
|
|
}
|
|
set problem [catch {set rem [CreateReminder .mod]} err]
|
|
if {$problem} {
|
|
tk_dialog .error Error "$err" error 0 Ok
|
|
continue
|
|
}
|
|
if {$ModifyDialogResult == 4} {
|
|
set rem [EditReminder $rem "Cancel" "Replace reminder"]
|
|
if {$ModifyDialogResult == 1} {
|
|
continue
|
|
}
|
|
}
|
|
set opts [RemindDialogToOptions .mod]
|
|
catch {focus $oldFocus}
|
|
destroy .mod
|
|
set problem [catch {
|
|
if {$ModifyDialogResult == 2} {
|
|
ReplaceTaggedReminder $tag $rem $opts
|
|
} else {
|
|
DeleteTaggedReminder $tag
|
|
}
|
|
} err]
|
|
if {$problem} {
|
|
tk_dialog .error Error "Error: $err" error 0 Ok
|
|
return 1
|
|
}
|
|
|
|
FillCalWindow
|
|
RestartBackgroundRemindDaemon
|
|
return 0
|
|
}
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: UniqueFileName
|
|
# %ARGUMENTS:
|
|
# stem -- base name of file
|
|
# %RETURNS:
|
|
# A filename of the form "stem.xxx" which does not exist
|
|
#***********************************************************************
|
|
proc UniqueFileName { stem } {
|
|
set n 1
|
|
while {[file exists $stem.$n]} {
|
|
incr n
|
|
}
|
|
return $stem.$n
|
|
}
|
|
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: DeleteTaggedReminder
|
|
# %ARGUMENTS:
|
|
# tag -- tag of reminder to delete
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Deletes tagged reminder from reminder file
|
|
#***********************************************************************
|
|
proc DeleteTaggedReminder { tag } {
|
|
global AppendFile
|
|
|
|
set tmpfile [UniqueFileName $AppendFile]
|
|
set out [open $tmpfile "w"]
|
|
set in [open $AppendFile "r"]
|
|
|
|
set foundStart 0
|
|
set foundEnd 0
|
|
|
|
while {[gets $in line] >= 0} {
|
|
if {[string match "# $tag *" $line]} {
|
|
set foundStart 1
|
|
break
|
|
}
|
|
puts $out $line
|
|
}
|
|
|
|
if {! $foundStart} {
|
|
close $in
|
|
close $out
|
|
file delete $tmpfile
|
|
error "Did not find start of reminder with tag $tag"
|
|
}
|
|
|
|
while {[gets $in line] >= 0} {
|
|
if { $line == "# TKEND"} {
|
|
set foundEnd 1
|
|
break
|
|
}
|
|
}
|
|
|
|
if {! $foundEnd} {
|
|
close $in
|
|
close $out
|
|
file delete $tmpfile
|
|
error "Did not find end of reminder with tag $tag"
|
|
}
|
|
|
|
while {[gets $in line] >= 0} {
|
|
puts $out $line
|
|
}
|
|
close $in
|
|
close $out
|
|
file rename -force -- $tmpfile $AppendFile
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: ReplaceTaggedReminder
|
|
# %ARGUMENTS:
|
|
# tag -- tag of reminder to replace
|
|
# rem -- text to replace it with
|
|
# opts -- edit options
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Replaces a tagged reminder in the reminder file
|
|
#***********************************************************************
|
|
proc ReplaceTaggedReminder { tag rem opts } {
|
|
global AppendFile
|
|
|
|
set tmpfile [UniqueFileName $AppendFile]
|
|
set out [open $tmpfile "w"]
|
|
set in [open $AppendFile "r"]
|
|
|
|
set foundStart 0
|
|
set foundEnd 0
|
|
|
|
while {[gets $in line] >= 0} {
|
|
if {[string match "# $tag *" $line]} {
|
|
set foundStart 1
|
|
break
|
|
}
|
|
puts $out $line
|
|
}
|
|
|
|
if {! $foundStart} {
|
|
close $in
|
|
close $out
|
|
file delete $tmpfile
|
|
error "Did not find start of reminder with tag $tag"
|
|
}
|
|
|
|
# Consume the old reminder
|
|
while {[gets $in line] >= 0} {
|
|
if { $line == "# TKEND"} {
|
|
set foundEnd 1
|
|
break
|
|
}
|
|
}
|
|
|
|
if {! $foundEnd} {
|
|
close $in
|
|
close $out
|
|
file delete $tmpfile
|
|
error "Did not find end of reminder with tag $tag"
|
|
}
|
|
|
|
# Write the new reminder
|
|
WriteReminder $out $tag $rem $opts
|
|
|
|
# Copy rest of file over
|
|
while {[gets $in line] >= 0} {
|
|
puts $out $line
|
|
}
|
|
close $in
|
|
close $out
|
|
file rename -force -- $tmpfile $AppendFile
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: WriteReminder
|
|
# %ARGUMENTS:
|
|
# out -- file to write to
|
|
# tag -- reminder tag
|
|
# rem -- reminder body
|
|
# opts -- edit options
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Writes a reminder to a file
|
|
#***********************************************************************
|
|
proc WriteReminder { out tag rem opts } {
|
|
puts $out "# $tag Next reminder was created with TkRemind. DO NOT EDIT"
|
|
puts $out "# $opts"
|
|
if {[string range $rem 0 3] == "REM "} {
|
|
puts $out "REM TAG $tag [string range $rem 4 end]"
|
|
} else {
|
|
puts $out $rem
|
|
}
|
|
puts $out "# TKEND"
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: DoShadeSpecial
|
|
# %ARGUMENTS:
|
|
# n -- calendar box to shade
|
|
# stuff -- Remind command line
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Handles the "SHADE" special -- shades a box.
|
|
#***********************************************************************
|
|
proc DoShadeSpecial { n stuff } {
|
|
set num [scan $stuff "%d %d %d" r g b]
|
|
if {$num == 1} {
|
|
set g $r
|
|
set b $r
|
|
} elseif {$num != 3} {
|
|
return
|
|
}
|
|
if {$r < 0 || $r > 255 || $g < 0 || $g > 255 || $b < 0 || $b > 255} {
|
|
return
|
|
}
|
|
set bg [format "#%02x%02x%02x" $r $g $b]
|
|
.cal.t$n configure -background $bg
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: DoMoonSpecial
|
|
# %ARGUMENTS:
|
|
# n -- calendar box for moon
|
|
# stuff -- Remind command line
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Handles the "MOON" special -- draws a moon symbol
|
|
#***********************************************************************
|
|
proc DoMoonSpecial { n stuff } {
|
|
set msg ""
|
|
set num [scan $stuff "%d %d %d %s" phase junk1 junk2 msg]
|
|
if {$num < 1} {
|
|
return
|
|
}
|
|
if {$phase < 0 || $phase > 3} {
|
|
return
|
|
}
|
|
switch -exact -- $phase {
|
|
0 { set image new }
|
|
1 { set image first }
|
|
2 { set image full }
|
|
3 { set image last }
|
|
}
|
|
.cal.t$n configure -state normal
|
|
.cal.t$n image create end -image $image
|
|
|
|
if {$msg != ""} {
|
|
.cal.t$n insert end " $msg"
|
|
}
|
|
.cal.t$n insert end "\n"
|
|
.cal.t$n configure -state disabled
|
|
}
|
|
#***********************************************************************
|
|
# %PROCEDURE: DisplayTime
|
|
# %ARGUMENTS:
|
|
# None
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Displays current date and time in status window
|
|
#***********************************************************************
|
|
proc DisplayTime {} {
|
|
set msg [clock format [clock seconds] -format "%e %b %Y %I:%M%p"]
|
|
Status $msg
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: CreateMoonImages
|
|
# %ARGUMENTS:
|
|
# None
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Creates the moon images "new", "first", "full" and "last"
|
|
#***********************************************************************
|
|
proc CreateMoonImages {} {
|
|
image create bitmap full -foreground black \
|
|
-data "#define newmoon_width 16\n#define newmoon_height 16\nstatic unsigned char newmoon_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0x30, 0x06, 0x0c, 0x18, 0x04, 0x10, 0x02, 0x20,\n0x02, 0x20, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x02, 0x20, 0x02, 0x20,\n0x04, 0x10, 0x0c, 0x18, 0x30, 0x06, 0xc0, 0x01};"
|
|
image create bitmap first -foreground black \
|
|
-data "#define firstquarter_width 16\n#define firstquarter_height 16\nstatic unsigned char firstquarter_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0xf0, 0x06, 0xfc, 0x18, 0xfc, 0x10, 0xfe, 0x20,\n0xfe, 0x20, 0xff, 0x40, 0xff, 0x40, 0xff, 0x40, 0xfe, 0x20, 0xfe, 0x20,\n0xfc, 0x10, 0xfc, 0x18, 0xf0, 0x06, 0xc0, 0x01};"
|
|
image create bitmap new -foreground black \
|
|
-data "#define fullmoon_width 16\n#define fullmoon_height 16\nstatic unsigned char fullmoon_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0xf0, 0x07, 0xfc, 0x1f, 0xfc, 0x1f, 0xfe, 0x3f,\n0xfe, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xfe, 0x3f, 0xfe, 0x3f,\n0xfc, 0x1f, 0xfc, 0x1f, 0xf0, 0x07, 0xc0, 0x01};"
|
|
image create bitmap last -foreground black \
|
|
-data "#define lastquarter_width 16\n#define lastquarter_height 16\nstatic unsigned char lastquarter_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0xb0, 0x07, 0x8c, 0x1f, 0x84, 0x1f, 0x82, 0x3f,\n0x82, 0x3f, 0x81, 0x7f, 0x81, 0x7f, 0x81, 0x7f, 0x82, 0x3f, 0x82, 0x3f,\n0x84, 0x1f, 0x8c, 0x1f, 0xb0, 0x07, 0xc0, 0x01};"
|
|
}
|
|
|
|
#***********************************************************************
|
|
# %PROCEDURE: DisplayTimeContinuously
|
|
# %ARGUMENTS:
|
|
# None
|
|
# %RETURNS:
|
|
# Nothing
|
|
# %DESCRIPTION:
|
|
# Continuously displays current date and time in status window,
|
|
# updating once a minute
|
|
#***********************************************************************
|
|
proc DisplayTimeContinuously {} {
|
|
DisplayTime
|
|
set secs [clock format [clock seconds] -format "%S"]
|
|
# Doh -- don't interpret as an octal number if leading zero
|
|
scan $secs "%d" decSecs
|
|
set decSecs [expr 60 - $decSecs]
|
|
after [expr $decSecs * 1000] DisplayTimeContinuously
|
|
}
|
|
main
|
|
|
|
# For debugging only...
|
|
#fileevent stdin readable "DaemonReadable stdin"
|
|
#Initialize
|
|
#CreateCalWindow $DayNames
|
|
#ConfigureCalWindow March 1998 0 31
|