4200 lines
		
	
	
		
			130 KiB
		
	
	
	
		
			Tcl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4200 lines
		
	
	
		
			130 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-2022 Dianne Skoll
 | |
| #
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| # the next line restarts using wish \
 | |
| exec /usr/local/bin/wish8.6 "$0" ${1+"$@"}
 | |
| 
 | |
| # We need at least version 8.5 because of {*} list expansion operator
 | |
| if {[catch {package require Tcl 8.5}]} {
 | |
|     puts stderr "This program requires Tcl 8.5 or higher."
 | |
|     puts stderr "You have version [info tclversion]"
 | |
|     exit 1
 | |
| }
 | |
| 
 | |
| wm withdraw .
 | |
| 
 | |
| set Hostname [exec hostname]
 | |
| 
 | |
| # Our icon photo
 | |
| catch {
 | |
|     image create photo rpicon -data {
 | |
| R0lGODlhFwAgAOecABUTERYTERYUERcVEhgWExkXFBkXFRoXFRsZFhwZFxwa
 | |
| GB0bGR4cGR4cGh8dGiAeHCEfHCEfHSIgHSIgHiQiHyYkISknJCooJispJywq
 | |
| Jy4sKTIwLjUzMDUzMTo4Njs5Nzs5ODw7ODw7OT07OT48OkE/PUJAPkNBP0RC
 | |
| QEVDQUVEQkdFQ0lIRkpJR01LSU5MSlBPTVFQTlNSUFRSUFRSUVVTUlVUUllY
 | |
| VltZV1xaWF1cWmBfXmJgX2RiYGZlY2dmZGppZ2tqaG1ram9tbHFwb3Jwb3Rz
 | |
| cXV0c3Z0c3Z1c3Z1dHd1dHh2dXh3dnt5eHx7eXx7en18en59e4B/foGAf4KB
 | |
| f4SDgYWEgoWEg4eGhIiHhouKiI2Mio6Ni46NjJCQj5KRkJSTkZeWlpiXlpmY
 | |
| l5qZmJybmp6dnKCfnqGgoKKhoKOioaSjoqinp6qpqKurqq+urbCvrrCwr7Gw
 | |
| r7OysbW1tLi3tri3t7u6ur28vMTDw8TEw8XFxMbFxcfGxsfHxsrJycrKyczM
 | |
| y83My83MzM3NzdDQz9LR0dPS0tPT09fX19jY19ra2dvb29zc29zc3Ojn5+jo
 | |
| 6Orq6uzs7O/v7/T09PX19fb29vf39/r6+vv7+/7+/v//////////////////
 | |
| ////////////////////////////////////////////////////////////
 | |
| ////////////////////////////////////////////////////////////
 | |
| ////////////////////////////////////////////////////////////
 | |
| ////////////////////////////////////////////////////////////
 | |
| ////////////////////////////////////////////////////////////
 | |
| ////////////////////////////////////////////////////////////
 | |
| /////////////////////yH5BAEKAP8ALAAAAAAXACAAAAj+AP8JHEiwoMGD
 | |
| CAcusRAAQEKDBQIcEBAAwUODAQJAsBGAwsWCBzJuUBLgI0ENGVM2dACg5UWV
 | |
| KU+Y/JfRQBknPoq8ATQz4wxOQIFa6vMx5ZSgQetczJDSClKgcF6mFDEnE9I2
 | |
| D0fADOChUdA1D7dmTBEUTditDQRQAnomIQaxICpoAmomoUoAGS2YIBIUDEIu
 | |
| YndI8FAJaBaEMlIuSEkloxugUBBOSLkh44AvGfkAPYJQpYqMLIQEILB205DO
 | |
| KW9kJHMhQAmgkaKgzsgjggM5GbEAxaNmdoAPOoz8CCAgEVAtg3wPEPMnQQAU
 | |
| QWsg5AAzDZSMbIBeaoHwAUwSDAI2XMAENA8ThAPEBvAStEkc3yonrOW0aUMk
 | |
| +BkBVAlaKATC8Fsp8Igid5ABgxMHtaTgggy6ZFBAADs=    }
 | |
| 
 | |
|     wm iconphoto . -default rpicon
 | |
| }
 | |
| 
 | |
| proc missing_tcllib { pkg } {
 | |
|     catch { puts stderr "Could not find the '$pkg' package -- you must install tcllib.\nPlease see http://tcllib.sourceforge.net/" }
 | |
|     tk_dialog .err "Error: tcllib not installed" "Could not find the '$pkg' package -- you must install tcllib.  Please see http://tcllib.sourceforge.net/" error 0 OK
 | |
|     exit 1
 | |
| }
 | |
| if {[catch {package require mime}]} {
 | |
|     missing_tcllib mime
 | |
| }
 | |
| 
 | |
| if {[catch {package require smtp}]} {
 | |
|     missing_tcllib smtp
 | |
| }
 | |
| if {[catch {package require json}]} {
 | |
|     missing_tcllib json
 | |
| }
 | |
| 
 | |
| if {$tcl_platform(platform) == "windows"} {
 | |
|     tk_dialog .error Error "Please do not port Remind to 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(ShowTodaysReminders) 1
 | |
| set OptDescr(ShowTodaysReminders) "(0/1) If 1, TkRemind shows all of today's non-timed reminders in a window at startup and when the date changes"
 | |
| 
 | |
| 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)"
 | |
| 
 | |
| set Option(DayAnchor) "center"
 | |
| set OptDescr(DayAnchor) "(w/center/e) Anchor the day number to the left (w), center or right (e) of its container"
 | |
| 
 | |
| set Option(Editor) "emacs +%d %s"
 | |
| set OptDescr(Editor) "(String) Specify command to edit a file.  %d is replaced with line number and %s with filename"
 | |
| 
 | |
| set Option(MailAddr) ""
 | |
| set OptDescr(MailAddr) "(String) Specify an e-mail address to which reminders should be sent if the popup window is not manually dismissed"
 | |
| 
 | |
| set Option(SMTPServer) "127.0.0.1"
 | |
| set OptDescr(SMTPServer) "(String) IP address or host name of SMTP server to use for sending e-mail"
 | |
| 
 | |
| set Option(ExtraRemindArgs) ""
 | |
| set OptDescr(ExtraRemindArgs) "(String) Extra arguments when invoking remind"
 | |
| 
 | |
| set Option(CalboxFont) [font actual TkFixedFont]
 | |
| set OptDescr(CalboxFont) "Font to use in calendar boxes in Tk font format"
 | |
| 
 | |
| set Option(HeadingFont) [font actual TkDefaultFont]
 | |
| set OptDescr(HeadingFont) "Font to use in calendar headings in Tk font format"
 | |
| 
 | |
| set Option(BackgroundColor) "#d9d9d9"
 | |
| set OptDescr(BackgroundColor) "Default background color of calendar boxes"
 | |
| 
 | |
| set Option(TextColor) "#000000"
 | |
| set OptDescr(TextColor) "Default text color in calendar boxes"
 | |
| 
 | |
| set Option(TodayColor) "#00C0C0"
 | |
| set OptDescr(TodayColor) "Background color for today heading"
 | |
| 
 | |
| set Option(LineColor) "#000000"
 | |
| set OptDescr(LineColor) "Color of gridlines on calendar"
 | |
| 
 | |
| set Option(LabelColor) "#000000"
 | |
| set OptDescr(LabelColor) "Default label color for headings"
 | |
| 
 | |
| set Option(WinBackground) "#d9d9d9"
 | |
| set OptDescr(WinBackground) "Background color of calendar window"
 | |
| 
 | |
| set TimerUpdateForChanges ""
 | |
| 
 | |
| # Remind program to execute -- supply full path if you want
 | |
| set Remind "remind"
 | |
| 
 | |
| # Rem2PS program to execute -- supply full path if you want
 | |
| set Rem2PS "rem2ps"
 | |
| 
 | |
| # Rem2PDF program to execute -- supply full path if you want
 | |
| set Rem2PDF "rem2pdf"
 | |
| 
 | |
| # Check if we have Rem2PDF
 | |
| set HaveRem2PDF 0
 | |
| 
 | |
| set a [exec sh -c "$Rem2PDF < /dev/null 2>&1 || true"]
 | |
| 
 | |
| if {[string match "rem2pdf:*" "$a"]} {
 | |
|     set HaveRem2PDF 1
 | |
| }
 | |
| 
 | |
| # Reminder file to source -- default
 | |
| set ReminderFile {NOSUCHFILE}
 | |
| set ReminderFile [file nativename "~/.reminders"]
 | |
| 
 | |
| # Default options file
 | |
| set ConfigFile ""
 | |
| 
 | |
| set EditorPid -1
 | |
| 
 | |
| # Inotify file
 | |
| set InotifyFP ""
 | |
| 
 | |
| # Errors from last remind run
 | |
| set RemindErrors ""
 | |
| 
 | |
| # Reminder file to append to -- default
 | |
| set AppendFile {NOSUCHFILE}
 | |
| catch {set AppendFile $ReminderFile}
 | |
| 
 | |
| # Array of tags -> JSON dicts
 | |
| array unset TagToObj
 | |
| 
 | |
| set SetFontsWorked 0
 | |
| #---------------- DON'T CHANGE STUFF BELOW HERE ------------------
 | |
| 
 | |
| # 24-hour clock mode
 | |
| set TwentyFourHourMode 0
 | |
| 
 | |
| # 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 name in English
 | |
| set EnglishDayNames {Sunday Monday Tuesday Wednesday Thursday Friday Saturday}
 | |
| 
 | |
| # Day names in Remind's pre-selected language - will be overwritten
 | |
| set DayNames $EnglishDayNames
 | |
| 
 | |
| # 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 now [clock seconds]
 | |
| 
 | |
| set TodayMonth [expr [string trim [clock format $now -format %N]] - 1]
 | |
| set TodayYear [clock format $now -format %Y]
 | |
| set TodayDay [string trim [clock format $now -format %e]]
 | |
| set CurMonth $TodayMonth
 | |
| set CurYear $TodayYear
 | |
| 
 | |
| # 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; default
 | |
| # encoding; 36pt margins; print small calendars
 | |
| set OptDescr(PrintDest) "Print destination: file or command"
 | |
| set Option(PrintDest) file
 | |
| 
 | |
| set OptDescr(PrintSize) "Page size: a4 or letter"
 | |
| set Option(PrintSize) letter
 | |
| 
 | |
| set OptDescr(PrintOrient) "Page orientation: portrait or landscape"
 | |
| set Option(PrintOrient) landscape
 | |
| 
 | |
| set OptDescr(PrintFill) "(0/1) If 1, fill entire page when printing"
 | |
| set Option(PrintFill) 1
 | |
| 
 | |
| set OptDescr(PrintDaysRight) "(0/1) If 1, put day numbers in the top-right of each calendar box"
 | |
| set Option(PrintDaysRight) 1
 | |
| 
 | |
| set OptDescr(PrintEncoding) "(0/1) If 1, apply ISO-8859-1 encoding to PostScript output"
 | |
| set Option(PrintEncoding) 0
 | |
| 
 | |
| set OptDescr(PrintMargins) "Print margins: One of 24pt, 36pt or 48pt"
 | |
| set Option(PrintMargins) 36pt
 | |
| 
 | |
| set OptDescr(PrintSmallCalendars) "(0/1) If 1, print small calendars in PostScript output"
 | |
| set Option(PrintSmallCalendars) 1
 | |
| 
 | |
| set OptDescr(PrintFormat) "Print format: pdf or ps"
 | |
| set Option(PrintFormat) ps
 | |
| 
 | |
| set WarningHeaders [list "# Lines staring with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
 | |
| 
 | |
| # Highest tag seen so far.  Array of tags is stored in ReminderTags()
 | |
| set HighestTagSoFar 0
 | |
| 
 | |
| proc get_weekday { yyyymmdd } {
 | |
|     global EnglishDayNames
 | |
|     return [lindex $EnglishDayNames [clock format [clock scan $yyyymmdd] -format %w -locale C]]
 | |
| }
 | |
| 
 | |
| proc write_warning_headers { out } {
 | |
|     global WarningHeaders
 | |
|     foreach h $WarningHeaders {
 | |
| 	puts $out $h
 | |
|     }
 | |
| }
 | |
| 
 | |
| proc is_warning_header { line } {
 | |
|     global WarningHeaders
 | |
|     foreach h $WarningHeaders {
 | |
| 	if {"$line" == "$h"} {
 | |
| 	    return 1
 | |
| 	}
 | |
|     }
 | |
|     return 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 TwentyFourHourMode ReminderFileModTime
 | |
|     global TodayDay TodayMonth TodayYear
 | |
| 
 | |
|     global Option ConfigFile
 | |
| 
 | |
|     # In case date has rolled over, recalculate Today* values
 | |
|     set now [clock seconds]
 | |
| 
 | |
|     set TodayMonth [expr [string trim [clock format $now -format %N]] - 1]
 | |
|     set TodayYear [clock format $now -format %Y]
 | |
|     set TodayDay [string trim [clock format $now -format %e]]
 | |
| 
 | |
|     set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA"
 | |
|     set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp -l EXTRA"
 | |
|     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
 | |
| 	    }
 | |
| 	    if {"[lindex $argv $i]" == "-b1"} {
 | |
| 		set TwentyFourHourMode 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
 | |
|             if {$i < $argc} {
 | |
|                 set ConfigFile [lindex $argv $i]
 | |
|                 incr i
 | |
|             }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     # If reminder file is a directory and appendfile is the same as
 | |
|     # reminder file, choose append file to be $ReminderFile/100-tkremind.rem
 | |
|     if {[file isdirectory $ReminderFile]} {
 | |
| 	if {"$ReminderFile" == "$AppendFile"} {
 | |
| 	    set AppendFile [file join $ReminderFile "100-tkremind.rem"]
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     # 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 {
 | |
| 	    set out [open $ReminderFile w]
 | |
| 	    write_warning_headers $out
 | |
| 	    puts $out ""
 | |
| 	    close $out
 | |
| 	}
 | |
|     }
 | |
|     if {! [file readable $ReminderFile]} {
 | |
| 	tk_dialog .error "TkRemind: Error" "Could not create reminder file `$ReminderFile'" error 0 "Exit"
 | |
| 	exit 1
 | |
|     }
 | |
| 
 | |
|     if {[file isdirectory $ReminderFile] && ! [file exists $AppendFile]} {
 | |
| 	if {![catch {
 | |
| 	    set out [open $AppendFile "a"]
 | |
| 	    write_warning_headers $out
 | |
| 	    puts $out ""
 | |
| 	    close $out}]} {
 | |
| 	    tk_dialog .error "Created File" "Created blank file `$AppendFile'" info 0 "OK"
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     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"
 | |
| 
 | |
|     # Get modification time of ReminderFile
 | |
|     set ReminderFileModTime -1
 | |
|     catch {
 | |
| 	set ReminderFileModTime [file mtime $ReminderFile]
 | |
|     }
 | |
| 
 | |
|     MonitorReminderFile
 | |
| 
 | |
| #   puts "CommandLine: $CommandLine"
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # MonitorReminderFile
 | |
| # If Reminder File modtime changes, restart daemon
 | |
| #---------------------------------------------------------------------------
 | |
| proc MonitorReminderFile {} {
 | |
|     global ReminderFileModTime ReminderFile
 | |
| 
 | |
|     if {$ReminderFileModTime < 0} {
 | |
| 	# Could not stat file
 | |
| 	return
 | |
|     }
 | |
| 
 | |
|     set mtime -1
 | |
|     catch {
 | |
| 	set mtime [file mtime $ReminderFile]
 | |
|     }
 | |
|     if {$mtime < 0} {
 | |
| 	# Doh!
 | |
| 	return
 | |
|     }
 | |
| 
 | |
|     # Run ourselves again
 | |
|     after 60000 MonitorReminderFile
 | |
| 
 | |
|     # Redraw calendar and restart daemon if needed
 | |
|     if {$ReminderFileModTime < $mtime} {
 | |
| 	set ReminderFileModTime $mtime
 | |
|         ScheduleUpdateForChanges
 | |
|     }
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %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 } {
 | |
|     # Figure out reasonable height for text frames
 | |
|     global SetFontsWorked
 | |
|     global Option
 | |
|     global MondayFirst
 | |
|     set h [winfo screenheight .]
 | |
|     if {$h <= 480} {
 | |
| 	if {$SetFontsWorked} {
 | |
| 	    set h 3
 | |
| 	} else {
 | |
| 	    set h 2
 | |
| 	}
 | |
|     } elseif {$h <= 600} {
 | |
| 	set h 4
 | |
|     } else {
 | |
| 	set h 5
 | |
|     }
 | |
| 
 | |
|     frame $w -background $Option(LineColor)
 | |
|     for {set i 0} {$i < 7} {incr i} {
 | |
| 	if {$MondayFirst} {
 | |
| 	    set index [expr ($i+1)%7]
 | |
| 	} else {
 | |
| 	    set index $i
 | |
| 	}
 | |
| 
 | |
| 	label $w.day$i -bd 0 -text [lindex $dayNames $index] -justify center -font HeadingFont -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
 | |
| 	grid configure $w.day$i -row 0 -column $i -sticky ew -padx 1 -pady 1
 | |
|     }
 | |
|     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 "" -anchor $Option(DayAnchor) \
 | |
| 		-state disabled -relief flat -bd 0 -padx 0 -pady 0 -font HeadingFont -highlightthickness 1
 | |
| 	    text $w.t$f -width 12 -height $h -bd 0 -spacing3 3 -wrap word -relief flat \
 | |
| 		-state disabled -takefocus 0 -cursor {} -font CalboxFont -foreground $Option(TextColor) -background $Option(BackgroundColor) \
 | |
|                 -highlightthickness 0
 | |
|             frame $w.f$f -padx 0 -pady 0 -highlightthickness 0 -relief flat -bd 0
 | |
| 	    $w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f"
 | |
| 	    $w.t$f tag bind REM <ButtonPress-3> "FireEditor $w.t$f"
 | |
|             pack $w.l$f -in $w.f$f -side top -expand 0 -fill x
 | |
|             pack $w.t$f -in $w.f$f -side top -expand 1 -fill both
 | |
|             grid configure $w.f$f -row [expr $i+1] -column $j -sticky nsew -padx 1 -pady 1
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     for {set i 0} {$i < 7} {incr i} {
 | |
| 	grid columnconfigure $w $i -weight 1
 | |
|     }
 | |
|     for {set i 1} {$i < 7} {incr i} {
 | |
| 	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
 | |
|     global tk_version Option
 | |
| 
 | |
|     CreateMoonWindows
 | |
|     set offset [CalEntryOffset $firstDay]
 | |
|     set first [expr $offset+1]
 | |
|     set last [expr $offset+$numDays]
 | |
| 
 | |
|     for {set i 0} {$i < $first} {incr i} {
 | |
| 	grid $w.f$i
 | |
|         pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
 | |
|         pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
 | |
|         raise $w.l$i
 | |
|         raise $w.t$i
 | |
| 	$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|         $w.l$i configure -state disabled
 | |
| 	balloon_add_help $w.l$i ""
 | |
| 	$w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground)
 | |
| 	$w.t$i delete 1.0 end
 | |
| 	foreach t [$w.t$i tag names] {
 | |
| 	    $w.t$i tag delete $t
 | |
| 	}
 | |
| 	$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
 | |
| 	$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
 | |
| 	$w.t$i configure -state disabled -takefocus 0
 | |
|     }
 | |
|     for {set i $first} {$i <= $last} {incr i} {
 | |
| 	set row [expr ($i/7)+1]
 | |
| 	grid $w.f$i
 | |
|         grid rowconfigure $w $row -weight 1
 | |
|         pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
 | |
|         pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
 | |
|         raise $w.l$i
 | |
|         raise $w.t$i
 | |
| 	set d [expr $i-$first+1]
 | |
| 	$w.l$i configure -text $d -state normal -relief flat \
 | |
| 		-command "ModifyDay $d $firstDay" -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
| 	balloon_add_help $w.l$i "Add a reminder..."
 | |
| 	$w.t$i configure -relief sunken -takefocus 1 -state normal -foreground $Option(TextColor) -background $Option(BackgroundColor)
 | |
| 	$w.t$i delete 1.0 end
 | |
| 	foreach t [$w.t$i tag names] {
 | |
| 	    $w.t$i tag delete $t
 | |
| 	}
 | |
| 	$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
 | |
| 	$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
 | |
| 	$w.t$i configure -state disabled -takefocus 0
 | |
|     }
 | |
|     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)+1]
 | |
| 	if {$forgetIt} {
 | |
| 	    grid remove $w.f$i
 | |
| 	    grid rowconfigure $w $row -weight 0
 | |
| 	    grid rowconfigure $w [expr $row+1] -weight 0
 | |
| 	} else {
 | |
| 	    grid $w.f$i
 | |
|             pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
 | |
|             pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
 | |
|             raise $w.l$i
 | |
|             raise $w.t$i
 | |
| 	    grid rowconfigure $w $row -weight 1
 | |
| 	}
 | |
| 	$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|         $w.l$i configure -state disabled
 | |
| 	balloon_add_help $w.l$i ""
 | |
| 	$w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground)
 | |
| 	$w.t$i delete 1.0 end
 | |
| 	foreach t [$w.t$i tag names] {
 | |
| 	    $w.t$i tag delete $t
 | |
| 	}
 | |
| 	$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
 | |
| 	$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
 | |
| 	$w.t$i configure -state disabled -takefocus 0
 | |
|     }
 | |
|     if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } {
 | |
| 	set n [expr $TodayDay + $offset]
 | |
| 	$w.l$n configure -background $Option(TodayColor)
 | |
|     }
 | |
| }
 | |
| 
 | |
| proc DoQueue {} {
 | |
|     global DaemonFile
 | |
|     puts $DaemonFile "JSONQUEUE"
 | |
|     flush $DaemonFile
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # CreateCalWindow -- create the calendar window.
 | |
| # Arguments:
 | |
| #   dayNames -- names of weekdays in current language {Sun .. Sat}
 | |
| #---------------------------------------------------------------------------
 | |
| proc CreateCalWindow { dayNames } {
 | |
|     global Option
 | |
|     frame .h -background $Option(LineColor)
 | |
|     label .h.title -text "" -justify center -pady 2 -bd 0 -relief flat -font HeadingFont -background $Option(WinBackground) -foreground $Option(LabelColor)
 | |
|     pack .h.title -side top -fill x -pady 1 -padx 1
 | |
|     pack .h -side top -expand 0 -fill x
 | |
|     . configure -background $Option(LineColor)
 | |
|     CreateCalFrame .cal $dayNames
 | |
| 
 | |
|     frame .b -background $Option(LineColor)
 | |
|     button .b.prev -text "\u2b9c" -command {MoveMonth -1} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.prev "Go to previous month"
 | |
|     button .b.this -text {Today} -command {ThisMonth} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.this "Go to this month"
 | |
|     button .b.next -text "\u2b9e" -command {MoveMonth 1} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.next "Go to next month"
 | |
|     button .b.goto -text {Go To Date...} -command {GotoDialog} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.goto "Go to a specific date"
 | |
|     button .b.print -text {Print...} -command {DoPrint} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.print "Print a PostScript or PDF calendar"
 | |
|     button .b.options -text {Options...} -command EditOptions -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.options "Set TkRemind options"
 | |
|     button .b.queue -text {Queue...} -command {DoQueue} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.queue "See the queue of pending reminders (debugging purposes only)"
 | |
|     button .b.quit -text {Quit} -command {Quit} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
 | |
|     balloon_add_help .b.quit "Quit TkRemind"
 | |
|     label .b.status -text "" -width 25 -relief flat -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
 | |
|     label .b.nqueued -text "" -width 20 -relief flat -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
 | |
|     pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.queue .b.quit -side left -fill both -padx 1
 | |
|     pack .b.status -side left -fill both -expand 1 -padx 1
 | |
|     pack .b.nqueued -side left -fill both -padx 1
 | |
|     pack .b -side bottom -fill x -expand 0 -pady 1
 | |
|     pack .cal -side top -fill both -expand 1
 | |
|     wm title . "TkRemind"
 | |
|     wm iconname . ""
 | |
|     wm protocol . WM_DELETE_WINDOW Quit
 | |
|     wm deiconify .
 | |
|     bind . <Control-KeyPress-q> Quit
 | |
|     bind . <KeyPress-Left> ".b.prev flash; .b.prev invoke"
 | |
|     bind . <KeyPress-Right> ".b.next flash; .b.next invoke"
 | |
|     bind . <KeyPress-Prior> ".b.prev flash; .b.prev invoke"
 | |
|     bind . <KeyPress-Next> ".b.next flash; .b.next invoke"
 | |
|     bind . <KeyPress-Home> ".b.this flash; .b.this invoke"
 | |
| 
 | |
|     . configure -background $Option(WinBackground)
 | |
|     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)
 | |
| 
 | |
|     # Show today's reminders on startup
 | |
|     checkbutton $w.showTodays -text "Show Today's Reminders on Startup" \
 | |
| 	    -anchor w -justify left \
 | |
| 	    -variable tmpOpt(ShowTodaysReminders)
 | |
| 
 | |
|     # 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.sep3 -bd 1 -relief sunken
 | |
|     # E-mail reminder if popup not dismissed
 | |
|     frame $w.eml
 | |
|     label $w.lab_email_address -text "E-mail reminders here if popup not dismissed:" -anchor w -justify left
 | |
|     entry $w.email_address -width 30
 | |
|     pack $w.lab_email_address -in $w.eml -side left -expand 0 -fill none
 | |
|     pack $w.email_address -in $w.eml -side left -expand 1 -fill x
 | |
|     $w.email_address insert 0 $tmpOpt(MailAddr)
 | |
| 
 | |
|     frame $w.fsmtp
 | |
|     label $w.lab_smtp -text "Name or IP address of SMTP server:" -anchor w -justify left
 | |
|     entry $w.smtp -width 30
 | |
|     pack $w.lab_smtp -in $w.fsmtp -side left -expand 0 -fill none
 | |
|     pack $w.smtp -in $w.fsmtp -side left -expand 1 -fill x
 | |
|     $w.smtp insert 0 $tmpOpt(SMTPServer)
 | |
| 
 | |
|     # Editor
 | |
|     frame $w.ef
 | |
|     label $w.el -text "Text Editor:" -anchor w -justify left
 | |
|     entry $w.editor -width 30
 | |
|     pack $w.el -in $w.ef -side left -expand 0 -fill none
 | |
|     pack $w.editor -in $w.ef -side left -expand 1 -fill x
 | |
|     $w.editor insert 0 $tmpOpt(Editor)
 | |
| 
 | |
|     # extra args
 | |
|     frame $w.eaf
 | |
|     label $w.eal -text "Extra Arguments for Remind:" -anchor w -justify left
 | |
|     entry $w.extraargs -width 30
 | |
|     pack $w.eal -in $w.eaf -side left -expand 0 -fill none
 | |
|     pack $w.extraargs -in $w.eaf -side left -expand 1 -fill x
 | |
|     $w.extraargs insert 0 $tmpOpt(ExtraRemindArgs)
 | |
| 
 | |
|     # Fonts
 | |
|     frame $w.fframe
 | |
|     button $w.font -text "Change entry font..." -command "ChooseCalboxFont"
 | |
|     button $w.hfont -text "Change heading font..." -command "ChooseHeadingFont"
 | |
|     pack $w.font $w.hfont -in $w.fframe -side left -expand 1 -fill x
 | |
| 
 | |
|     # Colors
 | |
|     frame $w.colors1
 | |
|     label $w.textcolor -text "Text Color:"
 | |
|     button $w.btextcolor -background $Option(TextColor) -command [list PickColor TextColor $w.btextcolor] -text ...
 | |
|     label $w.bgcolor -text "  Background color:"
 | |
|     button $w.bbgcolor -background $Option(BackgroundColor) -command [list PickColor BackgroundColor $w.bbgcolor] -text ...
 | |
| 
 | |
|     label $w.tbgcolor -text "Color for highlighting \"today\":"
 | |
|     button $w.tbbgcolor -background $Option(TodayColor) -command [list PickColor TodayColor $w.tbbgcolor] -text ...
 | |
| 
 | |
|     label $w.gridcolor -text "  Gridline color:"
 | |
|     button $w.gridbcolor -background $Option(LineColor) -command [list PickColor LineColor $w.gridbcolor] -text ...
 | |
| 
 | |
|     grid $w.textcolor $w.btextcolor $w.bgcolor $w.bbgcolor -in $w.colors1
 | |
|     grid $w.bgcolor $w.bbgcolor -in $w.colors1
 | |
| 
 | |
|     label $w.headcolor -text "Heading Color:"
 | |
|     button $w.bheadcolor -background $Option(LabelColor) -command [list PickColor LabelColor $w.bheadcolor] -text ...
 | |
|     label $w.wincolor -text "  Window color:"
 | |
|     button $w.bwincolor -background $Option(WinBackground) -command [list PickColor WinBackground $w.bwincolor] -text ...
 | |
|     grid $w.headcolor $w.bheadcolor $w.wincolor $w.bwincolor -in $w.colors1
 | |
|     grid $w.tbgcolor $w.tbbgcolor $w.gridcolor $w.gridbcolor -in $w.colors1
 | |
|     
 | |
|     grid columnconfigure $w.colors1 0 -weight 1
 | |
|     grid columnconfigure $w.colors1 2 -weight 1
 | |
|     frame $w.sep1 -bd 1 -relief sunken
 | |
|     frame $w.sep2 -bd 1 -relief sunken
 | |
| 
 | |
|     checkbutton $w.feed \
 | |
| 	    -text "Feed popped-up reminder to command's standard input" \
 | |
| 	    -variable tmpOpt(FeedReminder) -anchor w -justify left
 | |
| 
 | |
|     frame $w.ancFrame
 | |
|     label $w.ancLabel -text "Anchor day numbers to:"
 | |
|     radiobutton $w.ancLeft \
 | |
| 	    -text "Left" \
 | |
| 	    -variable tmpOpt(DayAnchor) -value "w" -anchor w -justify left
 | |
|     radiobutton $w.ancCenter \
 | |
| 	    -text "Center" \
 | |
| 	    -variable tmpOpt(DayAnchor) -value "center" -anchor w -justify left
 | |
|     radiobutton $w.ancRight \
 | |
| 	    -text "Right" \
 | |
| 	    -variable tmpOpt(DayAnchor) -value "e" -anchor w -justify left
 | |
|     pack $w.ancLabel $w.ancLeft $w.ancCenter $w.ancRight -in $w.ancFrame -side left
 | |
| 
 | |
|     pack $w.startIconified -in $w.f -side top -expand 0 -fill x
 | |
|     pack $w.showTodays -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.ancFrame -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.sep3 -in $w.f -side top -expand 0 -fill x -ipady 1
 | |
|     pack $w.eml -in $w.f -side top -expand 0 -fill x
 | |
|     pack $w.fsmtp -in $w.f -side top -expand 0 -fill x
 | |
|     pack $w.ef -in $w.f -side top -expand 0 -fill x
 | |
|     pack $w.eaf -in $w.f -side top -expand 0 -fill x
 | |
|     pack $w.fframe -in $w.f -side top -expand 0 -fill x
 | |
|     pack $w.colors1 -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.default -text "Light Theme" -command [list set_default_colors $w]
 | |
|     button $w.dark -text "Dark Theme" -command [list set_dark_colors $w]
 | |
|     button $w.save -text "Save Options" -command "SaveOptions $w; destroy $w"
 | |
|     button $w.cancel -text "Cancel" -command "CancelOptions; destroy $w"
 | |
|     wm protocol $w WM_DELETE_WINDOW "CancelOptions; destroy $w"
 | |
|     pack $w.default $w.dark $w.save $w.cancel -in $w.b -side left -expand 0 -fill x
 | |
|     CenterWindow $w .
 | |
| }
 | |
| 
 | |
| proc CancelOptions { } {
 | |
|     global Option
 | |
|     font configure CalboxFont {*}$Option(CalboxFont)
 | |
|     font configure HeadingFont {*}$Option(HeadingFont)
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %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]
 | |
|     set tmpOpt(Editor) [$w.editor get]
 | |
|     set tmpOpt(ExtraRemindArgs) [$w.extraargs get]
 | |
|     set tmpOpt(MailAddr) [$w.email_address get]
 | |
|     set tmpOpt(SMTPServer) [$w.smtp get]
 | |
| 
 | |
|     set need_restart 0
 | |
|     if {"$tmpOpt(ExtraRemindArgs)" != "$Option(ExtraRemindArgs)"} {
 | |
| 	set need_restart 1
 | |
|     }
 | |
|     # Copy working copy to real option set
 | |
|     foreach name [array names tmpOpt] {
 | |
| 	set Option($name) $tmpOpt($name)
 | |
|     }
 | |
|     if {$need_restart != 0} {
 | |
| 	FillCalWindow
 | |
| 	StopBackgroundRemindDaemon
 | |
| 	StartBackgroundRemindDaemon
 | |
|     }
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: SaveOptions
 | |
| # %ARGUMENTS:
 | |
| #  w -- edit options window path
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Saves options in specified config file
 | |
| #***********************************************************************
 | |
| proc SaveOptions { w } {
 | |
|     global Option OptDescr
 | |
|     ApplyOptions $w
 | |
|     WriteOptionsToFile
 | |
|     FillCalWindow
 | |
|     .h.title configure -background $Option(WinBackground) -foreground $Option(LabelColor)
 | |
|     for {set i 0} {$i < 7} {incr i} {
 | |
|         .cal.day$i configure  -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     }
 | |
|     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]
 | |
|             .cal.l$f configure -anchor $Option(DayAnchor);
 | |
|         }
 | |
|     }
 | |
|     .b.status configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.nqueued configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b configure -background $Option(WinBackground)
 | |
|     .b.prev configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.this configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.next configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.goto configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.print configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.queue configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.quit configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     .b.options configure -foreground $Option(LabelColor) -background $Option(WinBackground)
 | |
|     . configure -background $Option(LineColor);
 | |
|     .h configure -background $Option(LineColor);
 | |
|     .cal configure -background $Option(LineColor)
 | |
|     .b configure -background $Option(LineColor)
 | |
| }
 | |
| 
 | |
| proc WriteOptionsToFile {} {
 | |
|     global ConfigFile
 | |
|     global Option OptDescr
 | |
|     set problem [catch {set f [open "$ConfigFile.tmp" "w"]} err]
 | |
|     if {$problem} {
 | |
| 	tk_dialog .error Error "Can't write $ConfigFile.tmp: $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)]
 | |
|     }
 | |
|     puts $f ""
 | |
|     close $f
 | |
|     file rename -force "$ConfigFile.tmp" $ConfigFile
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: LoadOptions
 | |
| # %ARGUMENTS:
 | |
| #  None
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Loads options from $ConfigFile
 | |
| #***********************************************************************
 | |
| proc LoadOptions {} {
 | |
|     global Option ConfigFile
 | |
|     global MondayFirst
 | |
|     set problem [catch {set f [open "$ConfigFile" "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 stderr "Unknown option in $ConfigFile: $key"
 | |
|             continue
 | |
|         }
 | |
|         set Option($key) $val
 | |
|     }
 | |
|     close $f
 | |
|     if {[regexp -- {-m.*} $Option(ExtraRemindArgs)]} {
 | |
| 	set MondayFirst 1
 | |
|     }
 | |
|     font configure CalboxFont {*}$Option(CalboxFont)
 | |
|     font configure HeadingFont {*}$Option(HeadingFont)
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| #***********************************************************************
 | |
| # %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 } {
 | |
|     global Hostname
 | |
|     .h.title configure -text "$month $year"
 | |
|     wm title . "$month $year - TkRemind on $Hostname"
 | |
|     wm iconname . "$month $year"
 | |
|     ConfigureCalFrame .cal $firstDay $numDays
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # FillCalWindow -- Fill in the calendar for global CurMonth and CurYear.
 | |
| #---------------------------------------------------------------------------
 | |
| proc FillCalWindow {} {
 | |
|     set FileName ""
 | |
|     set LineNo 0
 | |
|     global DayNames CurYear CurMonth MonthNames CommandLine Option TagToObj RemindErrors MondayFirst
 | |
| 
 | |
|     array unset TagToObj
 | |
| 
 | |
|     Status "Firing off Remind..."
 | |
|     set_button_to_queue
 | |
|     set month [lindex $MonthNames $CurMonth]
 | |
| 
 | |
|     set cmd [regsub EXTRA $CommandLine $Option(ExtraRemindArgs)]
 | |
|     set file [open "$cmd $month $CurYear" r]
 | |
|     # Look for # rem2ps2 begin line
 | |
|     while { [gets $file line] >= 0 } {
 | |
| 	if { [string compare "$line" "# rem2ps2 begin"] == 0 } { break }
 | |
|     }
 | |
| 
 | |
|     if { [string compare "$line" "# rem2ps2 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
 | |
| 
 | |
|     set monthName [regsub -all {_} $monthName " "]
 | |
|     # Get the day names
 | |
|     gets $file line
 | |
|     set DayNames {}
 | |
|     foreach day $line {
 | |
|         set day [regsub -all {_} $day " "];
 | |
|         lappend DayNames $day
 | |
|     }
 | |
| 
 | |
|     ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
 | |
| 
 | |
|     # Update the day names in the calendar window
 | |
|     for {set i 0} {$i < 7} {incr i} {
 | |
| 	if {$MondayFirst} {
 | |
| 	    set index [expr ($i+1)%7]
 | |
| 	} else {
 | |
| 	    set index $i
 | |
| 	}
 | |
|         .cal.day$i configure -text [lindex $DayNames $index]
 | |
|     }
 | |
|     set offset [CalEntryOffset $firstWkday]
 | |
| 
 | |
|     while { [gets $file line] >= 0 } {
 | |
|         set fntag "x"
 | |
| 	# Ignore unless begins with left brace
 | |
| 	if { ! [string match "\{*" $line]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 
 | |
| 	if {[catch {set obj [::json::json2dict $line]}]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 
 | |
| 	if {[dict exists $obj filename]} {
 | |
|             set fname [dict get $obj filename]
 | |
|             # Don't make INCLUDECMD output editable
 | |
|             if {![string match "*|" $fname]} {
 | |
|                 set fntag [string cat "FILE_" [dict get $obj lineno] "_" $fname]
 | |
|             }
 | |
| 	}
 | |
| 
 | |
| 	set date [dict get $obj date]
 | |
| 	regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $date all year month day
 | |
| 	if {[dict exists $obj passthru]} {
 | |
| 	    set type [dict get $obj passthru]
 | |
| 	} else {
 | |
| 	    set type "*"
 | |
| 	}
 | |
| 	if {[dict exist $obj tags]} {
 | |
| 	    set tag [dict get $obj tags]
 | |
| 	} else {
 | |
| 	    set tag "*"
 | |
| 	}
 | |
|         if {[dict exists $obj calendar_body]} {
 | |
|             set stuff [dict get $obj calendar_body]
 | |
|         } elseif  {[dict exists $obj plain_body]} {
 | |
|             set stuff [dict get $obj plain_body]
 | |
|         } else {
 | |
|             set stuff [dict get $obj body]
 | |
|         }
 | |
| 	set day [string trimleft $day 0]
 | |
| 	set n [expr $day+$offset]
 | |
| 	set month [string trimleft $month 0]
 | |
| 	set extratags ""
 | |
| 	switch -nocase -- $type {
 | |
| 	    "WEEK" {
 | |
| 		set stuff [string trimleft $stuff]
 | |
| 		set stuff [string trimright $stuff]
 | |
| 		set offset [CalEntryOffset $firstWkday]
 | |
| 		set label [expr $offset + $day]
 | |
| 		.cal.l$label configure -text "$day $stuff"
 | |
| 		continue
 | |
| 	    }
 | |
| 	    "SHADE" {
 | |
| 		DoShadeSpecial $n [dict get $obj r] [dict get $obj g] [dict get $obj b]
 | |
| 		continue
 | |
| 	    }
 | |
| 	    "MOON" {
 | |
| 		DoMoonSpecial $n $stuff $fntag $day
 | |
| 		continue
 | |
| 	    }
 | |
| 	    "COLOUR" -
 | |
| 	    "COLOR" {
 | |
|                 set r [dict get $obj r]
 | |
|                 set g [dict get $obj g]
 | |
|                 set b [dict get $obj b]
 | |
|                 if {$r > 255} {
 | |
|                     set r 255
 | |
|                 } elseif {$r < 0} {
 | |
|                     set r 0
 | |
|                 }
 | |
|                 if {$g > 255} {
 | |
|                     set g 255
 | |
|                 } elseif {$g < 0} {
 | |
|                     set g 0
 | |
|                 }
 | |
|                 if {$b > 255} {
 | |
|                     set b 255
 | |
|                 } elseif {$b < 0} {
 | |
|                     set b 0
 | |
|                 }
 | |
|                 set color [format "%02X%02X%02X" $r $g $b]
 | |
|                 set extratags "clr$color"
 | |
|                 .cal.t$n configure -state normal
 | |
|                 .cal.t$n tag configure $extratags -foreground "#$color"
 | |
|                 .cal.t$n configure -state disabled -takefocus 0
 | |
|                 set stuff $stuff
 | |
|                 set type "COLOR"
 | |
| 	    }
 | |
| 	}
 | |
| 	if { $type != "*" && $type != "COLOR" && $type != "COLOUR"} {
 | |
| 	    continue
 | |
| 	}
 | |
| 	.cal.t$n configure -state normal
 | |
| 	if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
 | |
| 	    .cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
 | |
| 	    .cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
 | |
| 	    .cal.t$n tag bind "TKTAG$tagno" <Leave> "TaggedLeave .cal.t$n"
 | |
| 	    set TagToObj(TKTAG$tagno) $obj
 | |
| 	} else {
 | |
|             if {"$fntag" == "x" } {
 | |
|                 .cal.t$n insert end [string trim $stuff] [list REM $extratags]
 | |
|             } else {
 | |
|                 .cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
 | |
|                 .cal.t$n tag bind $fntag <Enter> "EditableEnter .cal.t$n"
 | |
|                 .cal.t$n tag bind $fntag <Leave> "EditableLeave .cal.t$n"
 | |
|                 .cal.t$n tag bind $fntag <ButtonPress-1> "FireEditor .cal.t$n"
 | |
|             }
 | |
| 	}
 | |
| 	.cal.t$n insert end "\n"
 | |
| 	.cal.t$n configure -state disabled -takefocus 0
 | |
| 
 | |
|     }
 | |
|     set problem [catch { close $file } errmsg]
 | |
|     if {$problem} {
 | |
|         set RemindErrors [unique_lines $errmsg]
 | |
|         set_button_to_errors
 | |
|     }
 | |
|     DisplayTime
 | |
| }
 | |
| 
 | |
| proc unique_lines { s } {
 | |
|     set l [split $s "\n"]
 | |
|     foreach line $l {
 | |
|         if {"$line" != ""} {
 | |
|             dict set d $line 1
 | |
|         }
 | |
|     }
 | |
|     return [join [dict keys $d] "\n"]
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # 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 Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus
 | |
|     global CurMonth CurYear MonthNames
 | |
| 
 | |
|     catch {destroy .p}
 | |
|     toplevel .p
 | |
|     wm title .p "TkRemind Print..."
 | |
|     wm iconname .p "Print..."
 | |
|     frame .p.f1 -relief sunken -bd 2
 | |
|     frame .p.f11
 | |
|     frame .p.f12
 | |
|     frame .p.f2 -relief sunken -bd 2
 | |
|     frame .p.f2a -relief sunken -bd 2
 | |
|     frame .p.f3 -relief sunken -bd 2
 | |
|     frame .p.f3a -relief sunken -bd 2
 | |
|     frame .p.f4
 | |
| 
 | |
|     radiobutton .p.tofile -text "To file: " -variable Option(PrintDest) -value file
 | |
|     entry .p.filename
 | |
|     button .p.browse -text "Browse..." -command PrintFileBrowse
 | |
|     radiobutton .p.tocmd -text "To command: " -variable Option(PrintDest) -value command
 | |
|     entry .p.command
 | |
|     .p.command insert end "lpr"
 | |
| 
 | |
|     if { $HaveRem2PDF } {
 | |
|         frame .p.ff -relief sunken -bd 2
 | |
|         label .p.format -text "Output Format:"
 | |
|         radiobutton .p.pdf -text "PDF" -variable Option(PrintFormat) -value pdf
 | |
|         radiobutton .p.ps -text "PostScript" -variable Option(PrintFormat) -value ps
 | |
|     }
 | |
| 
 | |
|     label .p.size -text "Paper Size:"
 | |
|     radiobutton .p.letter -text "Letter" -variable Option(PrintSize) -value letter
 | |
|     radiobutton .p.a4 -text "A4" -variable Option(PrintSize) -value a4
 | |
| 
 | |
|     label .p.margin -text "Margins:"
 | |
|     radiobutton .p.24pt -text "24pt margins" -variable Option(PrintMargins) -value 24pt
 | |
|     radiobutton .p.36pt -text "36pt margins" -variable Option(PrintMargins) -value 36pt
 | |
|     radiobutton .p.48pt -text "48pt margins" -variable Option(PrintMargins) -value 48pt
 | |
| 
 | |
|     label .p.orient -text "Orientation:"
 | |
|     radiobutton .p.landscape -text "Landscape" -variable Option(PrintOrient) -value landscape
 | |
|     radiobutton .p.portrait -text "Portrait" -variable Option(PrintOrient) -value portrait
 | |
| 
 | |
|     checkbutton .p.fill -text "Fill page" -variable Option(PrintFill)
 | |
|     checkbutton .p.right -text "Day numbers at top-right" -variable Option(PrintDaysRight)
 | |
|     checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable Option(PrintEncoding)
 | |
|     checkbutton .p.calendars -text "Print small calendars" -variable Option(PrintSmallCalendars)
 | |
| 
 | |
|     button .p.print -text "Print" -command {set PrintStatus print}
 | |
|     button .p.cancel -text "Cancel" -command {set PrintStatus cancel}
 | |
| 
 | |
|     if {$HaveRem2PDF} {
 | |
|         pack .p.f1 .p.ff .p.f2 .p.f2a .p.f3 .p.f3a \
 | |
|             -side top -fill both -expand 1 -anchor w
 | |
|     } else {
 | |
|         pack .p.f1 .p.f2 .p.f2a .p.f3 .p.f3a \
 | |
|             -side top -fill both -expand 1 -anchor w
 | |
|     }
 | |
|     pack .p.fill .p.right .p.encoding .p.calendars -in .p.f3a \
 | |
| 	    -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
 | |
|     if { $HaveRem2PDF } {
 | |
|         pack .p.format .p.pdf .p.ps -in .p.ff -side top -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.margin .p.24pt .p.36pt .p.48pt -in .p.f2a -side top -anchor w -fill none -expand 0
 | |
|     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
 | |
|     }
 | |
|     WriteOptionsToFile
 | |
|     if {$Option(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"
 | |
|     }
 | |
| 
 | |
|     if {$HaveRem2PDF && $Option(PrintFormat) == "pdf"} {
 | |
|         set p [regsub EXTRA $PSCmd "-itkpdf=1 $Option(ExtraRemindArgs)"]
 | |
|         set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PDF"
 | |
|     } else {
 | |
|         set p [regsub EXTRA $PSCmd $Option(ExtraRemindArgs)]
 | |
|         set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PS"
 | |
|         set Option(PrintFormat) ps
 | |
|     }
 | |
| 
 | |
|     if {$Option(PrintSize) == "letter"} {
 | |
|         if {$Option(PrintFormat) == "ps"} {
 | |
|             append cmd " -m Letter"
 | |
|         } else {
 | |
|             append cmd " --media=Letter"
 | |
|         }
 | |
|     } else {
 | |
|         if {$Option(PrintFormat) == "ps"} {
 | |
|             append cmd " -m A4"
 | |
|         } else {
 | |
|             append cmd " --media=A4"
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if {$Option(PrintMargins) == "24pt"} {
 | |
|         if {$Option(PrintFormat) == "ps"} {
 | |
|             append cmd " -or 24 -ol 24 -ot 24 -ob 24"
 | |
|         } else {
 | |
|             append cmd " --margin-right=24 --margin-left=24 --margin-top=24 --margin-bottom=24"
 | |
|         }
 | |
|     } elseif {$Option(PrintMargins) == "36pt"} {
 | |
|         if {$Option(PrintFormat) == "ps"} {
 | |
|             append cmd " -or 36 -ol 36 -ot 36 -ob 36"
 | |
|         } else {
 | |
|             append cmd " --margin-right=36 --margin-left=36 --margin-top=36 --margin-bottom=36"
 | |
|         }
 | |
|     } else {
 | |
|         if {$Option(PrintFormat) == "ps"} {
 | |
|             append cmd " -or 48 -ol 48 -ot 48 -ob 48"
 | |
|         } else {
 | |
|             append cmd " --margin-right=48 --margin-left=48 --margin-top=48 --margin-bottom=48"
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if {$Option(PrintOrient) == "landscape"} {
 | |
| 	append cmd " -l"
 | |
|     }
 | |
| 
 | |
|     if {$Option(PrintFill)} {
 | |
| 	append cmd " -e"
 | |
|     }
 | |
| 
 | |
|     if {!$Option(PrintDaysRight)} {
 | |
|         append cmd " -x"
 | |
|     }
 | |
|     if {$Option(PrintEncoding)} {
 | |
|         if {$Option(PrintFormat) == "ps"} {
 | |
|             append cmd " -i"
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if {$Option(PrintSmallCalendars)} {
 | |
| 	append cmd " -c3"
 | |
|     } else {
 | |
| 	append cmd " -c0"
 | |
|     }
 | |
| 
 | |
|     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
 | |
|     balloon_add_help .g.mon "Select a month"
 | |
|     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
 | |
|     balloon_add_help .g.y.e "Enter a year"
 | |
|     .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}
 | |
|     balloon_add_help .g.b.go "Go to specified month and year"
 | |
|     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-5990)} error 0 Ok
 | |
| 	return
 | |
|     }
 | |
|     if { $year < 1990 || $year > 5990 } {
 | |
| 	tk_dialog .error Error {Illegal year specified (1990-5990)} 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
 | |
|     global InotifyFP
 | |
|     if { !$Option(ConfirmQuit) } {
 | |
| 	destroy .
 | |
| 	StopBackgroundRemindDaemon
 | |
|         catch { exec kill [pid $InotifyFP] }
 | |
|         catch { close $InotifyFP }
 | |
| 	exit 0
 | |
|     }
 | |
|     if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
 | |
| 	destroy .
 | |
| 	StopBackgroundRemindDaemon
 | |
|         catch { exec kill [pid $InotifyFP] }
 | |
|         catch { close $InotifyFP }
 | |
| 	exit 0
 | |
|     }
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # 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 TwentyFourHourMode
 | |
| 
 | |
|     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 -bd 4 -relief ridge
 | |
|     frame $w.o1 -bd 4
 | |
|     frame $w.o2 -bd 4
 | |
|     frame $w.o3 -bd 4
 | |
|     frame $w.exp -bd 4
 | |
|     frame $w.adv -bd 4
 | |
|     frame $w.weekend -bd 4
 | |
|     frame $w.durationbox -bd 4
 | |
|     frame $w.time -bd 4
 | |
|     frame $w.hol -bd 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.durationbox $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
 | |
|     balloon_add_help $w.day1 "Select a day"
 | |
|     CreateDayMenu $w.day1
 | |
|     menubutton $w.mon1 -text $month -relief raised -menu $w.mon1.menu
 | |
|     balloon_add_help $w.mon1 "Select a month"
 | |
|     CreateMonthMenu $w.mon1
 | |
|     menubutton $w.year1 -text $year -relief raised -menu $w.year1.menu
 | |
|     balloon_add_help $w.year1 "Select a year"
 | |
|     CreateYearMenu $w.year1
 | |
|     checkbutton $w.repbut -text "and repeating every"
 | |
|     balloon_add_help $w.repbut "Select to enable a recurring reminder"
 | |
|     $w.repbut deselect
 | |
|     menubutton $w.repdays -text 1 -relief raised -menu $w.repdays.menu
 | |
|     balloon_add_help $w.repdays "Select the repeat interval in days"
 | |
|     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
 | |
|     balloon_add_help $w.wkday2 "Select a day of the week"
 | |
|     CreateWeekdayMenu $w.wkday2
 | |
|     label $w.label2b -text "on or after"
 | |
|     menubutton $w.day2 -text $day -relief raised -menu $w.day2.menu
 | |
|     balloon_add_help $w.day2 "Select a day"
 | |
|     CreateDayMenu $w.day2 1 31 0
 | |
|     menubutton $w.mon2 -text $month -relief raised -menu $w.mon2.menu
 | |
|     balloon_add_help $w.mon2 "Select a month"
 | |
|     CreateMonthMenu $w.mon2
 | |
|     menubutton $w.year2 -text $year -relief raised -menu $w.year2.menu
 | |
|     balloon_add_help $w.year2 "Select a year"
 | |
|     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
 | |
|     balloon_add_help $w.ordinal "Select the first, second, etc. weekday in a month"
 | |
|     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
 | |
|     balloon_add_help $w.wkday3 "Select a day of the week"
 | |
|     CreateWeekdayMenu $w.wkday3
 | |
|     label $w.label3 -text "in"
 | |
|     menubutton $w.mon3 -text $month -relief raised -menu $w.mon3.menu
 | |
|     balloon_add_help $w.mon3 "Select a month"
 | |
|     CreateMonthMenu $w.mon3
 | |
|     menubutton $w.year3 -text $year -relief raised -menu $w.year3.menu
 | |
|     balloon_add_help $w.year3 "Select a year"
 | |
|     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"
 | |
|     balloon_add_help $w.expbut "Select to enable an expiry date"
 | |
|     $w.expbut deselect
 | |
|     menubutton $w.expday -text $day -relief raised -menu $w.expday.menu
 | |
|     balloon_add_help $w.expday "Select expiry day"
 | |
|     CreateDayMenu $w.expday 1 31 0
 | |
|     menubutton $w.expmon -text $month -relief raised -menu $w.expmon.menu
 | |
|     balloon_add_help $w.expmon "Select expiry month"
 | |
|     CreateMonthMenu $w.expmon 0
 | |
|     menubutton $w.expyear -text $year -relief raised -menu $w.expyear.menu
 | |
|     balloon_add_help $w.expyear "Select expiry year"
 | |
|     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"
 | |
|     balloon_add_help $w.advbut "Select to enable advance notification"
 | |
|     $w.advbut deselect
 | |
|     menubutton $w.advdays -text 3 -menu $w.advdays.menu -relief raised
 | |
|     balloon_add_help $w.advdays "Select number of days of advance warning"
 | |
|     CreateDayMenu $w.advdays 1 10 0
 | |
|     label $w.advlab -text "day(s) in advance"
 | |
|     checkbutton $w.advcount -text "not counting holidays/weekend"
 | |
|     balloon_add_help $w.advcount "Select to avoid counting holidays/weekend as in advance warning days"
 | |
|     $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
 | |
| 	balloon_add_help $w.d$d "Select to include $d in the definition of \"Weekend\""
 | |
| 	$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"
 | |
|     balloon_add_help $w.timebut "Select if this event starts at a specific time"
 | |
|     $w.timebut deselect
 | |
|     menubutton $w.timehour -text "12" -menu $w.timehour.menu -relief raised
 | |
|     balloon_add_help $w.timehour "Select the starting time's hour"
 | |
|     if {$TwentyFourHourMode} {
 | |
| 	CreateDayMenu $w.timehour 0 23 0
 | |
|     } else {
 | |
| 	CreateDayMenu $w.timehour 1 12 0
 | |
|     }
 | |
|     menubutton $w.timemin -text "00" -menu $w.timemin.menu -relief raised
 | |
|     balloon_add_help $w.timemin "Select the starting time's minute"
 | |
|     menu $w.timemin.menu -tearoff 0
 | |
|     foreach i {00 05 10 15 20 25 30 35 40 45 50 55} {
 | |
| 	$w.timemin.menu add command -label $i \
 | |
| 		-command "$w.timemin configure -text $i"
 | |
|     }
 | |
| 
 | |
|     if {!$TwentyFourHourMode} {
 | |
| 	menubutton $w.ampm -text "PM" -menu $w.ampm.menu -relief raised
 | |
| 	balloon_add_help $w.ampm "Select whether the time is AM or PM"
 | |
| 	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"
 | |
|     balloon_add_help $w.timeadvbut "Select to be given advance warning prior to the start time"
 | |
|     $w.timeadvbut deselect
 | |
|     menubutton $w.timeadv -text "15" -menu $w.timeadv.menu -relief raised
 | |
|     balloon_add_help $w.timeadv "Select the number of minutes of advance warning"
 | |
|     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"
 | |
|     balloon_add_help $w.timerepbut "Select to repeat the advance notice"
 | |
|     $w.timerepbut deselect
 | |
|     menubutton $w.timerep -text "5" -menu $w.timerep.menu -relief raised
 | |
|     balloon_add_help $w.timerep "Select how often to repeat the advance notice"
 | |
|     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"
 | |
|     if {$TwentyFourHourMode} {
 | |
| 	pack $w.timebut $w.timehour $w.timemin $w.timeadvbut $w.timeadv $w.timelab1 $w.timerepbut $w.timerep $w.timelab2 -side left -anchor w -in $w.time
 | |
|     } else {
 | |
| 	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
 | |
|     }
 | |
| 
 | |
|     # DURATION
 | |
|     checkbutton $w.durationbut -text "Duration"
 | |
|     balloon_add_help $w.durationbut "Select if this event has a specific duration"
 | |
|     $w.durationbut deselect
 | |
|     menubutton $w.durationh -text "1" -menu $w.durationh.menu -relief raised
 | |
|     balloon_add_help $w.durationh "Select how many hours the event lasts"
 | |
|     menu $w.durationh.menu -tearoff 0
 | |
|     foreach i {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24} {
 | |
| 	$w.durationh.menu add command -label $i -command "$w.durationh configure -text $i"
 | |
|     }
 | |
|     label $w.durationcolon -text ":"
 | |
|     menubutton $w.durationm -text "00" -menu $w.durationm.menu -relief raised
 | |
|     balloon_add_help $w.durationm "Select how many minutes the event lasts (in addition to the hours)"
 | |
|     menu $w.durationm.menu -tearoff 0
 | |
|     foreach i {00 15 30 45} {
 | |
| 	$w.durationm.menu add command -label $i -command "$w.durationm configure -text $i"
 | |
|     }
 | |
|     pack $w.durationbut $w.durationh $w.durationcolon $w.durationm -side left -anchor w -in $w.durationbox
 | |
| 
 | |
|     # 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
 | |
|     balloon_add_help $w.entry "Enter the text of the reminder"
 | |
|     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 flash; $w.but1 invoke"
 | |
|     if {$nbut >= 2} {
 | |
| 	bind $w.entry <KeyPress-Return> "$w.but2 flash; $w.but2 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 durationbut
 | |
|     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" [string map -nocase {"\n" " "} [$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 TwentyFourHourMode durationbut
 | |
|     global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
 | |
|     set hour ""
 | |
|     set ampm ""
 | |
|     foreach {flag value} $opts {
 | |
| 	switch -glob -- $flag {
 | |
| 	    "-text-*" {
 | |
| 		set win [string range $flag 6 end]
 | |
| 		catch { $w.$win configure -text $value }
 | |
| 		if {"$flag" == "-text-ampm"} {
 | |
| 		    set ampm $value
 | |
| 		} elseif {"$flag" == "-text-timehour"} {
 | |
| 		    set hour $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
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     if {"$hour" != ""} {
 | |
| 	if {$TwentyFourHourMode} {
 | |
| 	    if {"$ampm" != ""} {
 | |
| 		if {"$ampm" == "PM" && $hour < 12} {
 | |
| 		    incr hour 12
 | |
| 		    $w.timehour configure -text $hour
 | |
| 		}
 | |
| 	    }
 | |
| 	} else {
 | |
| 	    if {$hour > 12} {
 | |
| 		incr hour -12
 | |
| 		$w.timehour configure -text $hour
 | |
| 		$w.ampm configure -text "PM"
 | |
| 	    } else {
 | |
| 		if {"$ampm" == ""} {
 | |
| 		    $w.ampm configure -text "AM"
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # 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
 | |
|         raise .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
 | |
| 
 | |
|             ScheduleUpdateForChanges
 | |
| 	    return 0
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # CenterWindow -- center a window on the screen or over a parent.
 | |
| #                 Stolen from tk_dialog code
 | |
| # Arguments:
 | |
| #    w -- window to center
 | |
| #    parent -- window over which to center.  Defaults to screen if not supplied.
 | |
| #---------------------------------------------------------------------------
 | |
| proc CenterWindow {w {parent {}}} {
 | |
|     wm withdraw $w
 | |
|     update idletasks
 | |
|     if {"$parent" == ""} {
 | |
| 	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]]]
 | |
|     } else {
 | |
| 	set x [expr [winfo rootx $parent] + [winfo width $parent]/2 - [winfo reqwidth $w]/2]
 | |
| 	set y [expr [winfo rooty $parent] + [winfo height $parent]/2 - [winfo reqheight $w]/2]
 | |
|     }
 | |
|     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 TwentyFourHourMode
 | |
| 
 | |
|     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 durationbut
 | |
| 
 | |
|     set rem [CreateReminder$OptionType $w]
 | |
| 
 | |
|     # Do the "until" part
 | |
|     if {$expbut} {
 | |
| 	append rem " UNTIL "
 | |
| 	append rem [consolidate [$w.expyear cget -text] [$w.expmon cget -text] [$w.expday 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 {!$TwentyFourHourMode} {
 | |
| 	    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]"
 | |
| 	}
 | |
| 	if {$durationbut} {
 | |
| 	    append rem " DURATION [$w.durationh cget -text]:[$w.durationm 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 - 2>@1" 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 " [string map -nocase {"\n" " "} $body]
 | |
|     return $rem
 | |
| }
 | |
| 
 | |
| # We used to return YYYY-MM-DD, but reverted to
 | |
| # day monthname year because this lets Remind produce
 | |
| # much better error messages.
 | |
| proc consolidate {y m d} {
 | |
|     global MonthNames
 | |
|     if {![regexp {^[0-9]+$} $m]} {
 | |
| 	set m [lsearch -exact $MonthNames $m]
 | |
| 	incr m
 | |
|     }
 | |
|     set mname [lindex $MonthNames [expr $m-1]]
 | |
|     return "$d $mname $y"
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # 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]
 | |
|     set m [$w.mon1 cget -text]
 | |
|     set y [$w.year1 cget -text]
 | |
|     if {"$d" != "every day" && "$m" != "every month" && $y != "every year"} {
 | |
| 	set gotDay 1
 | |
| 	set gotMon 1
 | |
| 	set gotYear 1
 | |
| 	append rem " "
 | |
| 	append rem [consolidate $y $m $d]
 | |
|     } else {
 | |
| 	if {"$d" != "every day"} {
 | |
| 	    append rem " $d"
 | |
| 	    set gotDay 1
 | |
| 	}
 | |
| 	if {"$m" != "every month"} {
 | |
| 	    append rem " $m"
 | |
| 	    set gotMon 1
 | |
| 	}
 | |
| 	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]
 | |
|     if {$mon != "every month" && $year != "every year"} {
 | |
| 	set rem "REM $wkday "
 | |
| 	append rem [consolidate $year $mon $day]
 | |
|     } else {
 | |
| 	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 flash; .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 Option TwentyFourHourMode
 | |
|     if {$TwentyFourHourMode} {
 | |
|         set problem [catch { set DaemonFile [open "|$Remind -b1 -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
 | |
|     } else {
 | |
|         set problem [catch { set DaemonFile [open "|$Remind -z0 -itkremind=1 $Option(ExtraRemindArgs) $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 ReminderFile ReminderFileModTime
 | |
| 
 | |
|     # Don't let the background handler trigger another reread
 | |
|     catch {
 | |
| 	set mtime [file mtime $ReminderFile]
 | |
| 	set ReminderFileModTime $mtime
 | |
|     }
 | |
| 
 | |
|     catch {
 | |
| 	puts $DaemonFile "REREAD"
 | |
| 	flush $DaemonFile
 | |
|     }
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # ShowQueue
 | |
| # Arguments:
 | |
| #    file -- file channel that is readable
 | |
| # Returns:
 | |
| #    nothing
 | |
| # Description:
 | |
| #    Dumps the debugging queue listing
 | |
| #---------------------------------------------------------------------------
 | |
| proc ShowQueue { file } {
 | |
|     set w .queuedbg
 | |
|     catch { destroy $w }
 | |
|     toplevel $w
 | |
|     wm title $w "Queue (Debugging Output)"
 | |
|     wm iconname $w "Queue Dbg"
 | |
|     text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
 | |
|     scrollbar $w.sb -orient vertical -command "$w.text yview"
 | |
|     button $w.ok -text "OK" -command "destroy $w"
 | |
|     grid $w.t -row 0 -column 0 -sticky nsew
 | |
|     grid $w.sb -row 0 -column 1 -sticky ns
 | |
|     grid $w.ok -row 1 -column 0 -sticky w
 | |
|     grid columnconfigure $w 0 -weight 1
 | |
|     grid columnconfigure $w 1 -weight 0
 | |
|     grid rowconfigure $w 0 -weight 1
 | |
|     grid rowconfigure $w 1 -weight 0
 | |
|     CenterWindow $w .
 | |
|     while (1) {
 | |
| 	# We should only get one line
 | |
| 	gets $file line
 | |
| 	if {$line == "NOTE ENDJSONQUEUE"} {
 | |
| 	    break
 | |
| 	}
 | |
| 	if {[catch {set obj [::json::json2dict $line]}]} {
 | |
| 	    continue;
 | |
| 	}
 | |
|         set obj [lsort -command sort_q $obj]
 | |
| 	foreach q $obj {
 | |
| 	    $w.t insert end "$q\n"
 | |
| 	}
 | |
|     }
 | |
|     $w.t configure -state disabled
 | |
| }
 | |
| 
 | |
| proc sort_q { a b } {
 | |
|     set a_ttime [dict get $a nextttime]
 | |
|     set b_ttime [dict get $b nextttime]
 | |
|     if {$a_ttime < $b_ttime} {
 | |
|         return -1
 | |
|     }
 | |
|     if {$a_ttime > $b_ttime} {
 | |
|         return 1
 | |
|     }
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # 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 JSONQUEUE" {
 | |
| 	    ShowQueue $file
 | |
| 	}
 | |
| 	"NOTE newdate" {
 | |
| 	    # Date has rolled over -- clear "ignore" list
 | |
| 	    catch { unset Ignore}
 | |
| 	    Initialize
 | |
| 	    FillCalWindow
 | |
| 	    ShowTodaysReminders
 | |
| 	}
 | |
| 	"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 stderr "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
 | |
| 
 | |
|     # Automatically shut down window after a minute if option says so
 | |
|     set after_token [after 60000 [list ClosePopup $w "" $Option(MailAddr) $Option(AutoClose) "" $tag $msg $time]]
 | |
| 
 | |
|     wm protocol $w WM_DELETE_WINDOW [list ClosePopup $w $after_token "" 1 "" $tag $msg $time]
 | |
|     button $w.ok -text "OK" -command [list ClosePopup $w $after_token "" 1 "" $tag $msg $time]
 | |
|     if {$tag != "*"} {
 | |
| 	button $w.nomore -text "Don't remind me again today" -command [list ClosePopup $w $after_token "" 1 "ignore" $tag $msg $time]
 | |
| 	button $w.kill -text "Delete this reminder completely" -command [list ClosePopup $w $after_token "" 1 "kill" $tag $msg $time]
 | |
|     }
 | |
|     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 $w.kill -in $w.b -side left
 | |
|     }
 | |
| 
 | |
|     CenterWindow $w .
 | |
| 
 | |
|     update
 | |
|     if {$Option(RingBell)} {
 | |
| 	bell
 | |
|     }
 | |
|     if {$Option(RunCmd) != ""} {
 | |
| 	if {$Option(FeedReminder)} {
 | |
| 	    FeedReminderToCommand $Option(RunCmd) "$time: $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 ConfigFile
 | |
| 
 | |
|     font create CalboxFont {*}[font actual TkFixedFont]
 | |
|     font create HeadingFont {*}[font actual TkDefaultFont]
 | |
|     font configure TkTextFont -size 6
 | |
| 
 | |
|     global AppendFile HighestTagSoFar DayNames
 | |
|     catch {
 | |
| 	puts "\nTkRemind Copyright (C) 1996-2021 Dianne Skoll"
 | |
|     }
 | |
|     catch { SetFonts }
 | |
|     Initialize
 | |
| 
 | |
|     # If no $ConfigFile file, create an empty one
 | |
|     if {![file exists $ConfigFile]} {
 | |
| 	catch {
 | |
| 	    set f [open $ConfigFile "w"]
 | |
| 	    close $f
 | |
| 	}
 | |
|     }
 | |
|     FindConfigFile
 | |
|     LoadOptions
 | |
|     ShowTodaysReminders
 | |
|     ScanForTags $AppendFile
 | |
|     CreateCalWindow $DayNames
 | |
|     FillCalWindow
 | |
|     StartBackgroundRemindDaemon
 | |
|     SetupInotify
 | |
|     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 {
 | |
| 	    {^REM TAG TKTAG[0-9]+} {
 | |
| 		regexp {^REM TAG 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
 | |
| #  date -- today's date
 | |
| # %RETURNS:
 | |
| #  A list of options for the dialog box for the tagged reminder
 | |
| # %DESCRIPTION:
 | |
| #  Converts the JSON dictionary to a list of options for dialog box
 | |
| #***********************************************************************
 | |
| proc ReadTaggedOptions { tag date } {
 | |
|     global TagToObj MonthNames EnglishDayNames TwentyFourHourMode
 | |
|     if {![info exists TagToObj($tag)]} {
 | |
| 	return ""
 | |
|     }
 | |
|     set obj $TagToObj($tag)
 | |
|     set ans ""
 | |
|     regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $date all y m d
 | |
|     set m [string trimleft $m 0]
 | |
|     set d [string trimleft $d 0]
 | |
|     set y [string trimleft $y 0]
 | |
|     if {![dict exists $obj skip]} {
 | |
| 	lappend ans -global-SkipType 1
 | |
|     } else {
 | |
| 	set s [dict get $obj skip]
 | |
| 	if {"$s" == "SKIP"} {
 | |
| 	    lappend ans -global-SkipType 2
 | |
| 	} elseif {"$s" == "BEFORE"} {
 | |
| 	    lappend ans -global-SkipType 3
 | |
| 	} elseif {"$s" == "AFTER"} {
 | |
| 	    lappend ans -global-SkipType 4
 | |
| 	} else {
 | |
| 	    lappend ans -global-SkipType 1
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if {[dict exists $obj d]} {
 | |
| 	lappend ans -text-day1 [dict get $obj d]
 | |
| 	lappend ans -text-day2 [dict get $obj d]
 | |
|     } else {
 | |
| 	lappend ans -text-day1 {every day}
 | |
| 	lappend ans -text-day2 $d
 | |
|     }
 | |
|     if {[dict exists $obj m]} {
 | |
|         set m [dict get $obj m]
 | |
|         set mm [string trimleft $m 0]
 | |
| 	lappend ans -text-mon1 [lindex $MonthNames [expr $mm -1]]
 | |
| 	lappend ans -text-mon2 [lindex $MonthNames [expr $mm -1]]
 | |
| 	lappend ans -text-mon3 [lindex $MonthNames [expr $mm -1]]
 | |
|     } else {
 | |
| 	lappend ans -text-mon1 {every month}
 | |
| 	lappend ans -text-mon2 {every month}
 | |
| 	lappend ans -text-mon3 {every month}
 | |
|     }
 | |
|     if {[dict exists $obj y]} {
 | |
| 	lappend ans -text-year1 [dict get $obj y]
 | |
| 	lappend ans -text-year2 [dict get $obj y]
 | |
| 	lappend ans -text-year3 [dict get $obj y]
 | |
|     } else {
 | |
| 	lappend ans -text-year1 {every year}
 | |
| 	lappend ans -text-year2 {every year}
 | |
| 	lappend ans -text-year3 {every year}
 | |
|     }
 | |
| 
 | |
|     set wd {}
 | |
|     if {[dict exists $obj wd]} {
 | |
| 	set wd [dict get $obj wd]
 | |
| 	if {[llength $wd] == 1} {
 | |
| 	    lappend ans -text-wkday2 [lindex $wd 0]
 | |
| 	    lappend ans -text-wkday3 [lindex $wd 0]
 | |
| 	} elseif {"$wd" == "Monday Tuesday Wednesday Thursday Friday"} {
 | |
| 	    lappend ans -text-wkday2 weekday
 | |
| 	    lappend ans -text-wkday3 weekday
 | |
| 	}
 | |
|     } else {
 | |
| 	lappend ans -text-wkday2 [get_weekday $date]
 | |
| 	lappend ans -text-wkday3 [get_weekday $date]
 | |
|     }
 | |
| 
 | |
|     if {[llength $wd] > 0} {
 | |
| 	if {[dict exists $obj d]} {
 | |
| 	    set day [dict get $obj d]
 | |
| 	    if {$day < 8} {
 | |
| 		if {[dict exists $obj back]} {
 | |
| 		    lappend ans -text-ordinal Last
 | |
| 		    # Adjust month down and possibly year?
 | |
| 		    if {[dict exists $obj m]} {
 | |
|                         set mm [string trimleft [dict get $obj m] 0]
 | |
| 			set idx [expr $mm -1]
 | |
| 			if {$idx <= 0} {
 | |
| 			    set idx 12
 | |
| 			}
 | |
| 			lappend ans -text-mon1 [lindex $MonthNames [expr $idx -1]]
 | |
| 			lappend ans -text-mon2 [lindex $MonthNames [expr $idx -1]]
 | |
| 			lappend ans -text-mon3 [lindex $MonthNames [expr $idx -1]]
 | |
| 			if {[dict exists $obj y]} {
 | |
| 			    set year [dict get $obj y]
 | |
| 			    if {$idx == 12} {
 | |
| 				lappend ans -text-year1 [expr $year - 1]
 | |
| 				lappend ans -text-year2 [expr $year - 1]
 | |
| 				lappend ans -text-year3 [expr $year - 1]
 | |
| 			    }
 | |
| 			}
 | |
| 		    }
 | |
| 		} else {
 | |
| 		    lappend ans -text-ordinal First
 | |
| 		}
 | |
| 	    } elseif {$day < 15} {
 | |
| 		lappend ans -text-ordinal Second
 | |
| 	    } elseif {$day < 22} {
 | |
| 		lappend ans -text-ordinal Third
 | |
| 	    } else  {
 | |
| 		lappend ans -text-ordinal Fourth
 | |
| 	    }
 | |
| 	} else {
 | |
| 	    lappend ans -text-ordinal Every
 | |
| 	}
 | |
|     } else {
 | |
| 	if {$d < 8} {
 | |
| 	    lappend ans -text-ordinal First
 | |
| 	} elseif {$d < 15} {
 | |
| 	    lappend ans -text-ordinal Second
 | |
| 	} elseif {$d < 22} {
 | |
| 	    lappend ans -text-ordinal Third
 | |
| 	} elseif {$d < 29} {
 | |
| 	    lappend ans -text-ordinal Fourth
 | |
| 	} else {
 | |
| 	    lappend ans -text-ordinal Last
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if {[dict exists $obj until]} {
 | |
| 	set u [dict get $obj until]
 | |
| 	regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $u all yu mu du
 | |
|         # Trim leading zeros, or Tcl complains
 | |
|         set mu [string trimleft $mu 0]
 | |
| 	lappend ans -global-expbut 1
 | |
| 	lappend ans -text-expday $du
 | |
| 	lappend ans -text-expmon [lindex $MonthNames [expr $mu-1]]
 | |
| 	lappend ans -text-expyear $yu
 | |
| 
 | |
|     } else {
 | |
|         set mm [string trimleft $m 0]
 | |
| 	lappend ans -global-expbut 0
 | |
| 	lappend ans -text-expday $d
 | |
| 	lappend ans -text-expmon [lindex $MonthNames [expr $mm-1]]
 | |
| 	lappend ans -text-expyear $y
 | |
|     }
 | |
| 
 | |
|     if {[dict exists $obj delta]} {
 | |
| 	set delta [dict get $obj delta]
 | |
| 	if {$delta == 0} {
 | |
| 	    lappend ans -global-advbut 0
 | |
| 	    lappend ans -text-advdays 3
 | |
| 	    lappend ans -global-advcount 1
 | |
| 	} elseif {$delta < 0} {
 | |
| 	    set delta [expr abs($delta)]
 | |
| 	    lappend ans -global-advbut 1
 | |
| 	    lappend ans -text-advdays $delta
 | |
| 	    lappend ans -global-advcount 0
 | |
| 	} else {
 | |
| 	    lappend ans -global-advbut 1
 | |
| 	    lappend ans -text-advdays $delta
 | |
| 	    lappend ans -global-advcount 1
 | |
| 	}
 | |
|     } else {
 | |
| 	lappend ans -global-advbut 0
 | |
| 	lappend ans -text-advdays 3
 | |
| 	lappend ans -global-advcount 1
 | |
|     }
 | |
| 
 | |
|     if {[dict exists $obj localomit]} {
 | |
| 	set lo [dict get $obj localomit]
 | |
| 	foreach w $EnglishDayNames {
 | |
| 	    if {[lsearch -exact $lo $w] >= 0} {
 | |
| 		lappend ans "-global-d$w" 1
 | |
| 	    } else {
 | |
| 		lappend ans "-global-d$w" 0
 | |
| 	    }
 | |
| 	}
 | |
|     } else {
 | |
| 	lappend ans -global-dSunday 1
 | |
| 	lappend ans -global-dMonday 0
 | |
| 	lappend ans -global-dTuesday 0
 | |
| 	lappend ans -global-dWednesday 0
 | |
| 	lappend ans -global-dThursday 0
 | |
| 	lappend ans -global-dFriday 0
 | |
| 	lappend ans -global-dSaturday 1
 | |
|     }
 | |
|     if {[dict exists $obj rep]} {
 | |
| 	lappend ans -global-repbut 1
 | |
| 	lappend ans -text-repdays [dict get $obj rep]
 | |
|     } else {
 | |
| 	lappend ans -global-repbut 0
 | |
| 	lappend ans -text-repdays 1
 | |
|     }
 | |
| 
 | |
|     if {[dict exists $obj time]} {
 | |
| 	set t [dict get $obj time]
 | |
| 	lappend ans -global-timebut 1
 | |
| 	set hour [expr $t / 60]
 | |
| 	set minute [format %02d [expr $t % 60]]
 | |
| 	if {$hour == 0 && !$TwentyFourHourMode} {
 | |
| 	    lappend ans -text-timehour 12
 | |
| 	    lappend ans -text-ampm AM
 | |
| 	} else {
 | |
| 	    if {$TwentyFourHourMode} {
 | |
| 		lappend ans -text-timehour $hour
 | |
| 	    } else {
 | |
| 		if {$hour >= 12} {
 | |
| 		    incr $hour -12
 | |
| 		    lappend ans -text-timehour $hour
 | |
| 		    lappend ans -text-ampm PM
 | |
| 		} else {
 | |
| 		    lappend ans -text-timehour $hour
 | |
| 		    lappend ans -text-ampm AM
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	lappend ans -text-timemin $minute
 | |
| 	if {[dict exists $obj tdelta]} {
 | |
| 	    lappend ans -global-timeadvbut 1
 | |
| 	    lappend ans -text-timeadv [dict get $obj tdelta]
 | |
| 	} else {
 | |
| 	    lappend ans -global-timeadvbut 0
 | |
| 	    lappend ans -text-timeadv 15
 | |
| 	}
 | |
| 	if {[dict exists $obj trep]} {
 | |
| 	    lappend ans -global-timerepbut 1
 | |
| 	    lappend ans -text-timerep [dict get $obj trep]
 | |
| 	} else {
 | |
| 	    lappend ans -global-timerepbut 0
 | |
| 	    lappend ans -text-timerep 5
 | |
| 	}
 | |
| 	if {[dict exists $obj duration]} {
 | |
| 	    lappend ans -global-durationbut 1
 | |
| 	    set dur [dict get $obj duration]
 | |
| 	    lappend ans -text-durationh [expr $dur / 60]
 | |
| 	    lappend ans -text-durationm [format %02d [expr $dur % 60]]
 | |
| 	} else {
 | |
| 	    lappend ans -global-durationbut 0
 | |
| 	    lappend ans -text-durationh 1
 | |
| 	    lappend ans -text-durationm 00
 | |
| 	}
 | |
|     } else {
 | |
| 	lappend ans -global-timebut 0
 | |
| 	lappend ans -text-timehour 12
 | |
| 	lappend ans -text-timemin 00
 | |
| 	lappend ans -text-timeadv 15
 | |
| 	lappend ans -global-timerepbut 0
 | |
| 	lappend ans -text-timerep 5
 | |
| 	lappend ans -global-durationbut 0
 | |
| 	lappend ans -text-durationh 1
 | |
| 	lappend ans -text-durationm 00
 | |
|     }
 | |
|     if {[dict exists $obj rawbody]} {
 | |
| 	lappend ans -entry-entry [dict get $obj rawbody]
 | |
|     } else {
 | |
| 	lappend ans -entry-entry [dict get $obj body]
 | |
|     }
 | |
| 
 | |
|     # Figure out the reminder type
 | |
|     if {[dict exists $obj rep]} {
 | |
| 	# Repeat must be type 1
 | |
| 	lappend ans -global-OptionType 1
 | |
| 	lappend ans -text-day2 $d
 | |
| 	lappend ans -text-mon2 [lindex $MonthNames [expr $m - 1]]
 | |
| 	lappend ans -text-mon3 [lindex $MonthNames [expr $m - 1]]
 | |
| 	lappend ans -text-year2 $y
 | |
| 	lappend ans -text-year3 $y
 | |
|     } elseif {![dict exists $obj wd]} {
 | |
| 	# No weekdays - must be type 1
 | |
| 	lappend ans -global-OptionType 1
 | |
| 	lappend ans -text-day2 $d
 | |
| 	lappend ans -text-mon2 [lindex $MonthNames [expr $m - 1]]
 | |
| 	lappend ans -text-mon3 [lindex $MonthNames [expr $m - 1]]
 | |
| 	lappend ans -text-year2 $y
 | |
| 	lappend ans -text-year3 $y
 | |
|     } elseif {![dict exists $obj d]} {
 | |
| 	# No day... must be "every wkday in ..."
 | |
| 	lappend ans -global-OptionType 3
 | |
| 	lappend ans -text-day1 $d
 | |
| 	lappend ans -text-mon1 [lindex $MonthNames [expr $m - 1]]
 | |
| 	lappend ans -text-year1 $y
 | |
| 	lappend ans -text-day2 $d
 | |
| 	lappend ans -text-mon2 [lindex $MonthNames [expr $m - 1]]
 | |
| 	lappend ans -text-year2 $y
 | |
|     } else {
 | |
| 	set day [dict get $obj d]
 | |
| 	# Take a guess based on day
 | |
| 	if {$day == 1 || $day == 8 || $day == 15 || $day == 22} {
 | |
| 	    lappend ans -global-OptionType 3
 | |
| 	    lappend ans -text-day1 $d
 | |
| 	    lappend ans -text-mon1 [lindex $MonthNames [expr $m - 1]]
 | |
| 	    lappend ans -text-year1 $y
 | |
| 	    lappend ans -text-day2 $d
 | |
| 	    lappend ans -text-mon2 [lindex $MonthNames [expr $m - 1]]
 | |
| 	    lappend ans -text-year2 $y
 | |
| 	} else {
 | |
| 	    lappend ans -global-OptionType 2
 | |
| 	    lappend ans -text-day1 $d
 | |
| 	    lappend ans -text-mon1 [lindex $MonthNames [expr $m - 1]]
 | |
| 	    lappend ans -text-year1 $y
 | |
| 	    lappend ans -text-mon3 [lindex $MonthNames [expr $m - 1]]
 | |
| 	    lappend ans -text-year3 $y
 | |
| 	}
 | |
|     }
 | |
|     return $ans
 | |
| }
 | |
| proc FireEditor { w {fntag ""}} {
 | |
|     global Option
 | |
|     global EditorPid
 | |
|     if {"$fntag" == ""} {
 | |
|         set tags [$w tag names current]
 | |
|         set index [lsearch -glob $tags "FILE_*"]
 | |
|         if {$index < 0} {
 | |
|             return
 | |
|         }
 | |
|         set fntag [lindex $tags $index]
 | |
|     }
 | |
|     if {![regexp {^FILE_([0-9]+)_(.*)} $fntag all line file]} {
 | |
|         return
 | |
|     }
 | |
|     set editor $Option(Editor)
 | |
|     regsub -all "%s" $editor $file editor
 | |
|     regsub -all "%d" $editor $line editor
 | |
| 
 | |
|     # Don't fire up a second editor if first is running
 | |
|     if {$EditorPid >= 0} {
 | |
| 	if {![catch {exec kill -0 $EditorPid}]} {
 | |
| 	    Status "Editor already active!"
 | |
| 	    after 2500 DisplayTime
 | |
| 	    bell
 | |
| 	    return
 | |
| 	}
 | |
|     }
 | |
|     Status "Firing up editor..."
 | |
|     after 1500 DisplayTime
 | |
|     set EditorPid [exec sh -c $editor &]
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %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 } {
 | |
|     global Option
 | |
|     set tag [GetCurrentReminder $w]
 | |
|     if {$tag != ""} {
 | |
| 	set tags [$w tag names current]
 | |
| 	set index [lsearch -glob $tags "clr*"]
 | |
| 	if {$index < 0} {
 | |
| 	    set fg $Option(TextColor)
 | |
| 	} else {
 | |
| 	    set fg [string range [lindex $tags $index] 3 end]
 | |
| 	    set fg "#$fg"
 | |
| 	}
 | |
| 	$w tag configure $tag -foreground $fg
 | |
|     }
 | |
| }
 | |
| 
 | |
| proc EditableEnter { w } {
 | |
|     set tags [$w tag names current]
 | |
|     set index [lsearch -glob $tags "FILE_*"]
 | |
|     if {$index < 0} {
 | |
| 	return
 | |
|     }
 | |
|     set tag [lindex $tags $index]
 | |
| 
 | |
|     set c ""
 | |
|     set index [lsearch -glob $tags "clr*"]
 | |
|     if {$index >= 0} {
 | |
|         set ctag [lindex $tags $index]
 | |
|         set c [$w tag cget $ctag -foreground]
 | |
|     }
 | |
|     if {"$c" != ""} {
 | |
|         $w tag configure $tag -underline 1 -underlinefg $c
 | |
|     } else {
 | |
|         $w tag configure $tag -underline 1
 | |
|     }
 | |
| }
 | |
| proc EditableLeave { w } {
 | |
|     set tags [$w tag names current]
 | |
|     set index [lsearch -glob $tags "FILE_*"]
 | |
|     if {$index < 0} {
 | |
| 	return
 | |
|     }
 | |
|     set tag [lindex $tags $index]
 | |
|     $w tag configure $tag -underline 0
 | |
| }
 | |
| #***********************************************************************
 | |
| # %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
 | |
|     }
 | |
| 
 | |
|     # Get the date
 | |
|     set index [lsearch -glob [$w tag names current] "date_*"]
 | |
|     if {$index < 0} {
 | |
| 	return
 | |
|     }
 | |
|     set date [string range [lindex [$w tag names current] $index] 5 end]
 | |
|     # Read in options
 | |
|     set opts [ReadTaggedOptions $tag $date]
 | |
|     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} {
 | |
|         raise .mod
 | |
| 	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
 | |
| 	}
 | |
| 
 | |
|         ScheduleUpdateForChanges
 | |
| 	return 0
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: UpdateForChanges
 | |
| #  Updates the calendar window and restarts background daemon because
 | |
| #  something has changed.
 | |
| # %ARGUMENTS:
 | |
| #  None
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| #***********************************************************************
 | |
| proc UpdateForChanges {} {
 | |
|     global TimerUpdateForChanges
 | |
|     catch { after cancel $TimerUpdateForChanges }
 | |
|     FillCalWindow
 | |
|     RestartBackgroundRemindDaemon
 | |
| }
 | |
| 
 | |
| # Schedule an update for 100ms in the future.
 | |
| # That way, if we get a rapid succession of
 | |
| # change notifications, we (probably) only
 | |
| # end up doing one call to UpdateForChanges
 | |
| proc ScheduleUpdateForChanges {} {
 | |
|     global TimerUpdateForChanges
 | |
|     catch { after cancel $TimerUpdateForChanges }
 | |
|     set TimerUpdateForChanges [after 100 UpdateForChanges]
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %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
 | |
|     global HighestTagSoFar
 | |
| 
 | |
|     set tmpfile [UniqueFileName $AppendFile]
 | |
|     set out [open $tmpfile "w"]
 | |
|     write_warning_headers $out
 | |
|     set in [open $AppendFile "r"]
 | |
| 
 | |
|     set found 0
 | |
| 
 | |
|     set tagno 0
 | |
|     while {[gets $in line] >= 0} {
 | |
| 	if {[is_warning_header $line]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 	if {[string match "REM TAG $tag *" $line]} {
 | |
| 	    set found 1
 | |
| 	    continue
 | |
| 	}
 | |
| 	# Delete the old comment lines
 | |
| 	if {[string match "# TKTAG*" $line]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 	if {[string match "# -global-OptionType *" $line]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 	if {[string match "# TKEND" $line]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 
 | |
| 	# Renumber tags
 | |
| 	if {[regexp {^REM TAG TKTAG([0-9]+) (.*)$} $line all oldtag rest]} {
 | |
| 	    incr tagno
 | |
| 	    puts $out "REM TAG TKTAG$tagno $rest"
 | |
| 	} else {
 | |
| 	    puts $out $line
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if {! $found } {
 | |
| 	close $in
 | |
| 	close $out
 | |
| 	file delete $tmpfile
 | |
| 	error "Did not find reminder with tag $tag"
 | |
|     }
 | |
| 
 | |
|     set HighestTagSoFar $tagno
 | |
|     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"]
 | |
|     write_warning_headers $out
 | |
|     set in [open $AppendFile "r"]
 | |
| 
 | |
|     set found 0
 | |
| 
 | |
|     while {[gets $in line] >= 0} {
 | |
| 	if {[is_warning_header $line]} {
 | |
| 	    continue
 | |
| 	}
 | |
| 	if {[string match "REM TAG $tag *" $line]} {
 | |
| 	    # Write the new reminder
 | |
| 	    WriteReminder $out $tag $rem $opts
 | |
| 	    set found 1
 | |
| 	} else {
 | |
| 	    # Delete the old comment lines
 | |
| 	    if {[string match "# TKTAG*" $line]} {
 | |
| 		continue
 | |
| 	    }
 | |
| 	    if {[string match "# -global-OptionType *" $line]} {
 | |
| 		continue
 | |
| 	    }
 | |
| 	    if {[string match "# TKEND" $line]} {
 | |
| 		continue
 | |
| 	    }
 | |
| 	    puts $out $line
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if {! $found} {
 | |
| 	close $in
 | |
| 	close $out
 | |
| 	file delete $tmpfile
 | |
| 	error "Did not find reminder with tag $tag"
 | |
|     }
 | |
| 
 | |
|     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
 | |
| #  r, g, b -- colour components
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Handles the "SHADE" special -- shades a box.
 | |
| #***********************************************************************
 | |
| proc DoShadeSpecial { n r g b } {
 | |
|     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
 | |
| #  fntag - filename tag, if any
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Handles the "MOON" special -- draws a moon symbol
 | |
| #***********************************************************************
 | |
| proc DoMoonSpecial { n stuff fntag day } {
 | |
|     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 win .moon_new }
 | |
|         1 { set win .moon_first }
 | |
|         2 { set win .moon_full }
 | |
|         3 { set win .moon_last }
 | |
|     }
 | |
| 
 | |
|     # We need two sets of moon phase windows.  There can be
 | |
|     # two of a given phase in the same month, but Tk does
 | |
|     # not allow the same embedded window in two separate
 | |
|     # text boxes.  So we use this hack to make sure
 | |
|     # we use a different window if the same moon phase
 | |
|     # happens twice in a month.
 | |
|     if {$day > 16} {
 | |
|         append win "2"
 | |
|     }
 | |
| 
 | |
|     .cal.t$n configure -state normal
 | |
|     .cal.t$n window create 1.0 -window $win
 | |
| 
 | |
|     if {$msg != ""} {
 | |
|         if {"$fntag" == "x"} {
 | |
|             .cal.t$n insert 1.1 " $msg\n"
 | |
|         } else {
 | |
|             .cal.t$n insert 1.1 " $msg\n" [list REM $fntag]
 | |
|             .cal.t$n tag bind $fntag <Enter> "EditableEnter .cal.t$n"
 | |
|             .cal.t$n tag bind $fntag <Leave> "EditableLeave .cal.t$n"
 | |
|             .cal.t$n tag bind $fntag <ButtonPress-1> "FireEditor .cal.t$n $fntag"
 | |
|             bind $win <ButtonPress-1> "FireEditor .cal.t$n $fntag"
 | |
|             bind $win <ButtonPress-3> "FireEditor .cal.t$n $fntag"
 | |
|         }
 | |
|     } else {
 | |
|         if {"$fntag" == "x"} {
 | |
|             .cal.t$n insert 1.1 "\n"
 | |
|         } else {
 | |
|             .cal.t$n insert 1.1 "\n" [list REM $fntag]
 | |
|             .cal.t$n tag bind $fntag <Enter> "EditableEnter .cal.t$n"
 | |
|             .cal.t$n tag bind $fntag <Leave> "EditableLeave .cal.t$n"
 | |
|             .cal.t$n tag bind $fntag <ButtonPress-1> "FireEditor .cal.t$n $fntag"
 | |
|         }
 | |
|     }
 | |
|     .cal.t$n configure -state disabled -takefocus 0
 | |
| }
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: DisplayTime
 | |
| # %ARGUMENTS:
 | |
| #  None
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Displays current date and time in status window
 | |
| #***********************************************************************
 | |
| proc DisplayTime {} {
 | |
|     global TwentyFourHourMode
 | |
|     if {$TwentyFourHourMode} {
 | |
| 	set msg [clock format [clock seconds] -format "%e %b %Y %H:%M"]
 | |
|     } else {
 | |
| 	set msg [clock format [clock seconds] -format "%e %b %Y %I:%M%p"]
 | |
|     }
 | |
|     Status $msg
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: CreateMoonWindows
 | |
| # %ARGUMENTS:
 | |
| #  None
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Creates the moon windows .moon_new, .moon_first, .moon_full and
 | |
| #  .moon_last
 | |
| #***********************************************************************
 | |
| proc CreateMoonWindows {} {
 | |
|     global Option;
 | |
|     catch { destroy .moon_new   }
 | |
|     catch { destroy .moon_first }
 | |
|     catch { destroy .moon_full  }
 | |
|     catch { destroy .moon_last  }
 | |
| 
 | |
|     catch { destroy .moon_new2  }
 | |
|     catch { destroy .moon_first2}
 | |
|     catch { destroy .moon_full2 }
 | |
|     catch { destroy .moon_last2 }
 | |
| 
 | |
|     set extra 1
 | |
|     set wid [font metrics CalboxFont -ascent]
 | |
|     set orig_wid $wid
 | |
|     incr wid $extra
 | |
|     incr wid $extra
 | |
|     incr wid $extra
 | |
|     incr wid $extra
 | |
|     incr orig_wid $extra
 | |
|     incr orig_wid $extra
 | |
| 
 | |
|     set w [expr $extra+$orig_wid]
 | |
| 
 | |
|     foreach win {.moon_new .moon_new2 } {
 | |
|         canvas $win -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
 | |
|         $win create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
 | |
|         balloon_add_help $win "New Moon"
 | |
|     }
 | |
| 
 | |
|     foreach win {.moon_first .moon_first2 } {
 | |
|         canvas $win -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
 | |
|         $win create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
 | |
|         $win create arc $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -start 90 -extent 180 -outline {}
 | |
|         balloon_add_help $win "First Quarter"
 | |
|     }
 | |
| 
 | |
|     foreach win {.moon_full .moon_full2 } {
 | |
|         canvas $win -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
 | |
|         $win create oval $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -width 1
 | |
|         balloon_add_help $win  "Full Moon"
 | |
|     }
 | |
| 
 | |
|     foreach win {.moon_last .moon_last2 } {
 | |
|         canvas $win -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
 | |
|         $win create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
 | |
|         $win create arc $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -start 270 -extent 180 -outline {}
 | |
|         balloon_add_help $win  "Last Quarter"
 | |
|     }
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %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
 | |
| }
 | |
| 
 | |
| 
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: ShowTodaysReminders
 | |
| # %ARGUMENTS:
 | |
| #  None
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Shows all of today's non-timed reminders in a window
 | |
| #***********************************************************************
 | |
| proc ShowTodaysReminders {} {
 | |
|     global Option
 | |
|     global Remind
 | |
|     global ReminderFile
 | |
|     global TwentyFourHourMode
 | |
|     if {!$Option(ShowTodaysReminders)} {
 | |
| 	return
 | |
|     }
 | |
| 
 | |
|     set w .today
 | |
|     catch { destroy $w }
 | |
|     toplevel $w
 | |
|     wm title $w "Today's Reminders"
 | |
|     wm iconname $w "Reminders"
 | |
|     text $w.text -width 80 -height 20 -wrap word -yscrollcommand "$w.sb set"
 | |
|     scrollbar $w.sb -orient vertical -command "$w.text yview"
 | |
|     button $w.ok -text "OK" -command "destroy $w"
 | |
| 
 | |
|     grid $w.text -row 0 -column 0 -sticky nsew
 | |
|     grid $w.sb -row 0 -column 1 -sticky ns
 | |
|     grid $w.ok -row 1 -column 0 -sticky w
 | |
| 
 | |
|     CenterWindow $w .
 | |
| 
 | |
|     # Grab the reminders
 | |
|     set stuff ""
 | |
|     set cmdline "|$Remind -itkremind=1 -g -q -r "
 | |
|     if {$TwentyFourHourMode} {
 | |
|         append cmdline "-b1 "
 | |
|     }
 | |
|     append cmdline $Option(ExtraRemindArgs);
 | |
|     append cmdline " $ReminderFile 2>/dev/null"
 | |
|     set f [open $cmdline r]
 | |
|     while {[gets $f line] >= 0} {
 | |
| 	append stuff "$line\n"
 | |
|     }
 | |
|     close $f
 | |
|     $w.text insert end $stuff
 | |
|     $w.text configure -state disabled
 | |
| }
 | |
| 
 | |
| #***********************************************************************
 | |
| # %PROCEDURE: InteractiveDeleteReminder
 | |
| # %ARGUMENTS:
 | |
| #  tag -- tag of reminder to delete
 | |
| # %RETURNS:
 | |
| #  Nothing
 | |
| # %DESCRIPTION:
 | |
| #  Prompts for confirmation; then deletes reminder
 | |
| #***********************************************************************
 | |
| proc InteractiveDeleteReminder { tag } {
 | |
|     set ans [tk_dialog .error "Really Delete" "Really delete reminder?" warning 0 No Yes]
 | |
|     if {$ans == 1} {
 | |
| 	DeleteTaggedReminder $tag
 | |
|         ScheduleUpdateForChanges
 | |
|     }
 | |
| }
 | |
| 
 | |
| proc SendMail { recipient subject body } {
 | |
|     global Option
 | |
| 
 | |
|     if {"$Option(MailAddr)" == ""} {
 | |
| 	return
 | |
|     }
 | |
|     if {[catch {set token [mime::initialize -canonical text/plain -string $body]
 | |
| 	mime::setheader $token Subject $subject
 | |
| 	mime::setheader $token From "Reminder Service <>"
 | |
| 	mime::setheader $token To "<$recipient>"
 | |
| 	mime::setheader $token Auto-Submitted "auto-generated"
 | |
| 	smtp::sendmessage $token -originator "" -servers $Option(SMTPServer) -recipients $Option(MailAddr)} err]} {
 | |
| 	puts stderr "ERROR sending mail: $err"
 | |
|     }
 | |
| }
 | |
| 
 | |
| proc ClosePopup { w after_token mail_addr close_win ignore_or_kill tag reminder rem_time } {
 | |
|     global Ignore
 | |
|     if {"$after_token" != ""} {
 | |
| 	catch { after cancel $after_token }
 | |
|     }
 | |
| 
 | |
|     if {$close_win} {
 | |
| 	catch { destroy $w }
 | |
|     }
 | |
| 
 | |
|     if {"$mail_addr" != ""} {
 | |
| 	SendMail $mail_addr "Reminder for $rem_time" "Hello,\n\nThe following reminder is scheduled for $rem_time:\n\n$reminder\nRegards,\n\nTkRemind\n"
 | |
|     }
 | |
|     if {"$ignore_or_kill" == "ignore"} {
 | |
| 	set Ignore($tag) 1
 | |
|     }
 | |
|     if {"$ignore_or_kill" == "kill"} {
 | |
| 	InteractiveDeleteReminder $tag
 | |
|     }
 | |
| }
 | |
| 
 | |
| # Adjust font defaults for screen size
 | |
| proc SetFonts {} {
 | |
|     global SetFontsWorked
 | |
|     set h [winfo screenheight .]
 | |
|     if {$h <= 480} {
 | |
| 	# Small screen (maybe eeepc?)
 | |
| 	font configure TkDefaultFont -size 6
 | |
| 	font configure TkFixedFont -size 6
 | |
| 	font configure TkTextFont -size 6
 | |
|     }
 | |
|     if {$h >= 1080} {
 | |
| 	# HIDPI screen
 | |
| 	font configure TkDefaultFont -size 12
 | |
| 	font configure TkFixedFont -size 12
 | |
| 	font configure TkTextFont -size 12
 | |
|     }
 | |
|     set SetFontsWorked 1
 | |
| }
 | |
| 
 | |
| # Set up inotify to watch for changes to reminder file/directory
 | |
| proc SetupInotify {} {
 | |
|     global InotifyFP
 | |
|     global ReminderFile
 | |
|     set failed [catch {set InotifyFP [open "|inotifywait -r -q -m -e close_write -e move -e create -e delete $ReminderFile < /dev/null 2>/dev/null" "r"] } ]
 | |
|     if {$failed} {
 | |
|         # inotifywait probably not available... meh.
 | |
|         return
 | |
|     }
 | |
|     fileevent $InotifyFP readable [list InotifyReadable $InotifyFP]
 | |
| }
 | |
| 
 | |
| # Called when inotifywait reports an event.  Schedule a calendar update
 | |
| # and daemon reload.
 | |
| proc InotifyReadable { fp } {
 | |
|     catch { set num [gets $fp line] }
 | |
|     if {$num < 0} {
 | |
|         catch { exec kill [pid $fp] }
 | |
|         close $fp
 | |
|         return
 | |
|     }
 | |
|     ScheduleUpdateForChanges
 | |
| }
 | |
| 
 | |
| ### Balloon help
 | |
| set Balloon(HelpTime) 400
 | |
| set Balloon(StayTime) 3500
 | |
| set Balloon(Font) fixed
 | |
| set Balloon(MustLeave) 0
 | |
| 
 | |
| proc balloon_reset_timer { w } {
 | |
|     balloon_destroy_help_window
 | |
|     balloon_cancel_timer
 | |
|     balloon_schedule_help $w
 | |
| }
 | |
| 
 | |
| proc balloon_destroy_help_window {} {
 | |
|     catch { destroy .balloonhelp }
 | |
| }
 | |
| 
 | |
| proc balloon_cancel_timer {} {
 | |
|     global Balloon
 | |
|     catch { after cancel $Balloon(HelpId) }
 | |
| }
 | |
| 
 | |
| proc balloon_schedule_help { w } {
 | |
|     global Balloon
 | |
|     if { $Balloon(MustLeave) } {
 | |
| 	return
 | |
|     }
 | |
|     set Balloon(HelpId) [ after $Balloon(HelpTime) "balloon_popup_help $w" ]
 | |
| }
 | |
| 
 | |
| proc balloon_popup_help { w } {
 | |
|     global Balloon
 | |
|     if {![info exists Balloon(helptext$w)]} {
 | |
| 	return
 | |
|     }
 | |
| 
 | |
|     if {[string compare [winfo containing [winfo pointerx .] [winfo pointery .]] $w]} {
 | |
| 	return
 | |
|     }
 | |
|     set h .balloonhelp
 | |
|     toplevel $h -bg #000000
 | |
|     label $h.l -text $Balloon(helptext$w) -wraplength 200 -justify left -bg #FFFFC0 -bd 0
 | |
|     pack $h.l -padx 1 -pady 1 -ipadx 2 -ipady 1
 | |
|     wm overrideredirect $h 1
 | |
|     set geom [balloon_calculate_geometry $h]
 | |
|     wm geometry $h $geom
 | |
|     set Balloon(HelpId) [after $Balloon(StayTime) "catch { destroy $h }"]
 | |
|     set Balloon(MustLeave) 1
 | |
| }
 | |
| 
 | |
| bind Balloon <Leave> {
 | |
|     set Balloon(MustLeave) 0
 | |
|     balloon_destroy_help_window
 | |
|     balloon_cancel_timer
 | |
| }
 | |
| 
 | |
| bind Balloon <Enter> {
 | |
|     set Balloon(MustLeave) 0
 | |
|     balloon_reset_timer %W
 | |
| }
 | |
| 
 | |
| bind Balloon <Any-Motion> "balloon_reset_timer %W"
 | |
| bind Balloon <Any-ButtonPress> {
 | |
|     set Balloon(MustLeave) 1
 | |
|     balloon_reset_timer %W
 | |
| }
 | |
| 
 | |
| bind Balloon <Destroy> {
 | |
|     balloon_destroy_help_window
 | |
|     balloon_cancel_timer
 | |
|     catch { unset Balloon(helptext%W) }
 | |
| }
 | |
| 
 | |
| proc balloon_add_help { w txt } {
 | |
|     global Balloon
 | |
|     if {"$txt" == ""} {
 | |
| 	catch { unset Balloon(helptext$w) }
 | |
| 	return
 | |
|     }
 | |
|     set Balloon(helptext$w) $txt
 | |
|     bindtags $w "Balloon [bindtags $w]"
 | |
| }
 | |
| 
 | |
| proc balloon_calculate_geometry { w } {
 | |
|     set x [winfo pointerx $w]
 | |
|     set y [winfo pointery $w]
 | |
|     set mx [winfo screenwidth $w]
 | |
|     set my [winfo screenheight $w]
 | |
|     # Adjust for padding
 | |
|     set wid [expr [winfo reqwidth $w.l] + 6]
 | |
|     set h [expr [winfo reqheight $w.l] + 4]
 | |
| 
 | |
|     # Try above-right of pointer
 | |
|     set tx [expr $x+3]
 | |
|     set ty [expr $y-3-$h]
 | |
|     if {$ty >= 0 && ($tx+$wid) <= $mx} {
 | |
| 	return "+$tx+$ty"
 | |
|     }
 | |
| 
 | |
|     # Try above-left of pointer
 | |
|     set tx [expr $x-3-$wid]
 | |
|     set ty [expr $y-3-$h]
 | |
|     if {$ty >= 0 && $tx >= 0} {
 | |
| 	return "+$tx+$ty"
 | |
|     }
 | |
| 
 | |
|     # Try below-right of pointer
 | |
|     set tx [expr $x+3]
 | |
|     set ty [expr $y+3]
 | |
|     if {$ty+$h <= $my && ($tx+$wid) <= $mx} {
 | |
| 	return "+$tx+$ty"
 | |
|     }
 | |
| 
 | |
|     # Darn... must be below-left
 | |
|     set tx [expr $x-3-$wid]
 | |
|     set ty [expr $y+3]
 | |
|     return "+$tx+$ty"
 | |
| }
 | |
| 
 | |
| proc ChooseCalboxFont {} {
 | |
|     tk fontchooser show
 | |
|     tk fontchooser configure -font [font actual CalboxFont]
 | |
|     tk fontchooser configure -command SetCalboxFont
 | |
| }
 | |
| 
 | |
| proc SetCalboxFont {font} {
 | |
|     global tmpOpt
 | |
|     font configure CalboxFont {*}[font actual $font]
 | |
|     set tmpOpt(CalboxFont) [font actual $font]
 | |
|     raise .opt
 | |
| }
 | |
| 
 | |
| proc ChooseHeadingFont {} {
 | |
|     tk fontchooser show
 | |
|     tk fontchooser configure -font [font actual HeadingFont]
 | |
|     tk fontchooser configure -command SetHeadingFont
 | |
| }
 | |
| 
 | |
| proc SetHeadingFont {font} {
 | |
|     global tmpOpt
 | |
|     font configure HeadingFont {*}[font actual $font]
 | |
|     set tmpOpt(HeadingFont) [font actual $font]
 | |
|     raise .opt
 | |
| }
 | |
| 
 | |
| proc PickColor {index button} {
 | |
|     global tmpOpt
 | |
|     set x [tk_chooseColor -initialcolor $tmpOpt($index)]
 | |
|     if {"$x" != ""} {
 | |
|         set tmpOpt($index) $x
 | |
|         $button configure -background $x
 | |
|     }
 | |
|     raise .opt
 | |
| }
 | |
| 
 | |
| proc FindConfigFile {} {
 | |
|     global ConfigFile
 | |
| 
 | |
|     # If it was set on the command line, use that
 | |
|     if {"$ConfigFile" != ""} {
 | |
|         return
 | |
|     }
 | |
| 
 | |
|     set confighome ""
 | |
|     if {[info exists env(XDG_CONFIG_HOME)]} {
 | |
|         set confighome $env(XDG_CONFIG_HOME)
 | |
|     }
 | |
|     if {"$confighome" == ""} {
 | |
|         set confighome "~/.config"
 | |
|     }
 | |
| 
 | |
|     # If $confighome does not exist, attempt to
 | |
|     # create it
 | |
|     if {![file exists $confighome]} {
 | |
|         catch { file mkdir $confighome }
 | |
|     }
 | |
| 
 | |
|     if {[file isdirectory $confighome]} {
 | |
|         # Migrate .tkremindrc to $confighome/tkremindrc
 | |
|         if {[file exists "~/.tkremindrc"]} {
 | |
|             if {![file exists "$confighome/tkreminderc"]} {
 | |
|                 puts "Migrating ~/.tkremindrc to $confighome/tkremindrc"
 | |
|                 if {[catch { file copy "~/.tkremindrc" "$confighome/tkremindrc"}]} {
 | |
|                     puts "FAILED!\n"
 | |
|                     set ConfigFile "~/.tkremindrc"
 | |
|                     return
 | |
|                 }
 | |
|                 catch { file delete "~/.tkremindrc" }
 | |
|             }
 | |
|             set ConfigFile "$confighome/tkremindrc"
 | |
|             return
 | |
|         }
 | |
|         set ConfigFile "$confighome/tkremindrc"
 | |
|         return
 | |
|     }
 | |
|     set ConfigFile "~/.tkremindrc"
 | |
| }
 | |
| 
 | |
| proc set_default_colors { w } {
 | |
|     global tmpOpt
 | |
|     set tmpOpt(BackgroundColor) "#d9d9d9"
 | |
|     set tmpOpt(LabelColor) "#000000"
 | |
|     set tmpOpt(LineColor) "#000000"
 | |
|     set tmpOpt(TextColor) "#000000"
 | |
|     set tmpOpt(TodayColor) "#00C0C0"
 | |
|     set tmpOpt(WinBackground) "#d9d9d9"
 | |
|     update_color_buttons $w
 | |
| }
 | |
| 
 | |
| proc set_dark_colors { w } {
 | |
|     global tmpOpt
 | |
|     set tmpOpt(BackgroundColor) "#000000"
 | |
|     set tmpOpt(LabelColor) "#00ffff"
 | |
|     set tmpOpt(LineColor) "#0080fc"
 | |
|     set tmpOpt(TextColor) "#ffffff"
 | |
|     set tmpOpt(TodayColor) "#b000b6"
 | |
|     set tmpOpt(WinBackground) "#000000"
 | |
|     update_color_buttons $w
 | |
| }
 | |
| 
 | |
| proc update_color_buttons { w } {
 | |
|     global tmpOpt
 | |
|     $w.bbgcolor configure -background $tmpOpt(BackgroundColor)
 | |
|     $w.bheadcolor configure -background $tmpOpt(LabelColor)
 | |
|     $w.gridbcolor configure -background $tmpOpt(LineColor)
 | |
|     $w.btextcolor configure -background $tmpOpt(TextColor)
 | |
|     $w.tbbgcolor configure -background $tmpOpt(TodayColor)
 | |
|     $w.bwincolor configure -background $tmpOpt(WinBackground)
 | |
| }
 | |
| 
 | |
| proc set_button_to_queue {} {
 | |
|     .b.queue configure -text {Queue...} -command {DoQueue}
 | |
| }
 | |
| proc set_button_to_errors {} {
 | |
|     .b.queue configure -text {Errors...} -command {ShowErrors}
 | |
| }
 | |
| 
 | |
| proc ShowErrors {} {
 | |
|     global RemindErrors
 | |
|     set w ".errors"
 | |
|     catch { destroy $w }
 | |
|     toplevel $w
 | |
|     text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
 | |
|     scrollbar $w.sb -orient vertical -command "$w.t yview"
 | |
|     button $w.ok -text OK -command DoneShowingErrors
 | |
|     grid $w.t -row 0 -column 0 -sticky nsew
 | |
|     grid $w.sb -row 0 -column 1 -sticky ns
 | |
|     grid $w.ok -row 1 -column 0 -stick w
 | |
|     grid columnconfigure $w 0 -weight 1
 | |
|     grid columnconfigure $w 1 -weight 0
 | |
|     grid rowconfigure $w 0 -weight 1
 | |
|     grid rowconfigure $w 1 -weight 0
 | |
|     $w.t insert end $RemindErrors
 | |
|     $w.t configure -state disabled
 | |
|     CenterWindow $w .
 | |
| }
 | |
| 
 | |
| proc DoneShowingErrors {} {
 | |
|     global RemindErrors
 | |
|     set RemindErrors {}
 | |
|     set_button_to_queue
 | |
|     destroy .errors
 | |
| }
 | |
| 
 | |
| # Rem2PS program to execute -- supply full path if you want
 | |
| 
 | |
| main
 | 
