mhc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/COPYRIGHT +28 -0
  6. data/Gemfile +8 -0
  7. data/README.org +209 -0
  8. data/Rakefile +13 -0
  9. data/bin/mhc +312 -0
  10. data/emacs/Cask +25 -0
  11. data/emacs/Makefile +58 -0
  12. data/emacs/mhc-calendar.el +1723 -0
  13. data/emacs/mhc-calfw.el +135 -0
  14. data/emacs/mhc-compat.el +90 -0
  15. data/emacs/mhc-date.el +642 -0
  16. data/emacs/mhc-day.el +149 -0
  17. data/emacs/mhc-db.el +158 -0
  18. data/emacs/mhc-draft.el +211 -0
  19. data/emacs/mhc-e21.el +167 -0
  20. data/emacs/mhc-face.el +236 -0
  21. data/emacs/mhc-file.el +224 -0
  22. data/emacs/mhc-guess.el +648 -0
  23. data/emacs/mhc-header.el +176 -0
  24. data/emacs/mhc-logic.el +563 -0
  25. data/emacs/mhc-message.el +130 -0
  26. data/emacs/mhc-minibuf.el +466 -0
  27. data/emacs/mhc-misc.el +248 -0
  28. data/emacs/mhc-mua.el +260 -0
  29. data/emacs/mhc-parse.el +286 -0
  30. data/emacs/mhc-process.el +35 -0
  31. data/emacs/mhc-ps.el +1174 -0
  32. data/emacs/mhc-record.el +201 -0
  33. data/emacs/mhc-schedule.el +202 -0
  34. data/emacs/mhc-summary.el +763 -0
  35. data/emacs/mhc-sync.el +158 -0
  36. data/emacs/mhc-vars.el +149 -0
  37. data/emacs/mhc.el +1114 -0
  38. data/icons/Anniversary.xbm +6 -0
  39. data/icons/Anniversary.xpm +27 -0
  40. data/icons/Birthday.xbm +6 -0
  41. data/icons/Birthday.xpm +25 -0
  42. data/icons/Business.xbm +6 -0
  43. data/icons/Business.xpm +24 -0
  44. data/icons/CheckBox.xbm +6 -0
  45. data/icons/CheckBox.xpm +24 -0
  46. data/icons/CheckedBox.xbm +6 -0
  47. data/icons/CheckedBox.xpm +25 -0
  48. data/icons/Conflict.xbm +6 -0
  49. data/icons/Conflict.xpm +22 -0
  50. data/icons/Date.xbm +6 -0
  51. data/icons/Date.xpm +29 -0
  52. data/icons/Holiday.xbm +6 -0
  53. data/icons/Holiday.xpm +25 -0
  54. data/icons/Link.xbm +6 -0
  55. data/icons/Link.xpm +25 -0
  56. data/icons/Other.xbm +6 -0
  57. data/icons/Other.xpm +28 -0
  58. data/icons/Party.xbm +6 -0
  59. data/icons/Party.xpm +23 -0
  60. data/icons/Private.xbm +6 -0
  61. data/icons/Private.xpm +26 -0
  62. data/icons/Recurrence.xbm +6 -0
  63. data/icons/Recurrence.xpm +98 -0
  64. data/icons/Vacation.xbm +6 -0
  65. data/icons/Vacation.xpm +26 -0
  66. data/lib/mhc.rb +45 -0
  67. data/lib/mhc/builder.rb +64 -0
  68. data/lib/mhc/caldav.rb +304 -0
  69. data/lib/mhc/calendar.rb +106 -0
  70. data/lib/mhc/command.rb +13 -0
  71. data/lib/mhc/command/cache.rb +14 -0
  72. data/lib/mhc/command/completions.rb +108 -0
  73. data/lib/mhc/command/init.rb +133 -0
  74. data/lib/mhc/command/scan.rb +33 -0
  75. data/lib/mhc/command/sync.rb +22 -0
  76. data/lib/mhc/config.rb +229 -0
  77. data/lib/mhc/converter.rb +330 -0
  78. data/lib/mhc/datastore.rb +164 -0
  79. data/lib/mhc/date_enumerator.rb +274 -0
  80. data/lib/mhc/date_frame.rb +124 -0
  81. data/lib/mhc/date_helper.rb +49 -0
  82. data/lib/mhc/etag.rb +68 -0
  83. data/lib/mhc/event.rb +396 -0
  84. data/lib/mhc/formatter.rb +312 -0
  85. data/lib/mhc/logger.rb +94 -0
  86. data/lib/mhc/modifier.rb +149 -0
  87. data/lib/mhc/occurrence.rb +94 -0
  88. data/lib/mhc/occurrence_enumerator.rb +113 -0
  89. data/lib/mhc/property_value.rb +33 -0
  90. data/lib/mhc/property_value/date.rb +190 -0
  91. data/lib/mhc/property_value/integer.rb +15 -0
  92. data/lib/mhc/property_value/list.rb +41 -0
  93. data/lib/mhc/property_value/period.rb +49 -0
  94. data/lib/mhc/property_value/range.rb +100 -0
  95. data/lib/mhc/property_value/recurrence_condition.rb +272 -0
  96. data/lib/mhc/property_value/text.rb +11 -0
  97. data/lib/mhc/property_value/time.rb +45 -0
  98. data/lib/mhc/query.rb +210 -0
  99. data/lib/mhc/sync.rb +46 -0
  100. data/lib/mhc/sync/driver.rb +108 -0
  101. data/lib/mhc/sync/status.rb +70 -0
  102. data/lib/mhc/sync/status_manager.rb +142 -0
  103. data/lib/mhc/sync/strategy.rb +233 -0
  104. data/lib/mhc/sync/syncinfo.rb +98 -0
  105. data/lib/mhc/templates/config.yml.erb +142 -0
  106. data/lib/mhc/version.rb +4 -0
  107. data/lib/mhc/webdav.rb +319 -0
  108. data/mhc.gemspec +24 -0
  109. data/samples/DOT.mhc-config.yml +116 -0
  110. data/samples/japanese-holidays.mhcc +153 -0
  111. data/samples/mhc-completions.zsh +11 -0
  112. data/spec/mhc_spec.rb +682 -0
  113. data/spec/spec_helper.rb +9 -0
  114. data/xpm/close.xpm +18 -0
  115. data/xpm/delete.xpm +19 -0
  116. data/xpm/exit.xpm +18 -0
  117. data/xpm/month.xpm +18 -0
  118. data/xpm/next.xpm +18 -0
  119. data/xpm/next2.xpm +18 -0
  120. data/xpm/next_year.xpm +18 -0
  121. data/xpm/open.xpm +19 -0
  122. data/xpm/prev.xpm +18 -0
  123. data/xpm/prev2.xpm +18 -0
  124. data/xpm/prev_year.xpm +18 -0
  125. data/xpm/save.xpm +19 -0
  126. data/xpm/today.xpm +18 -0
  127. metadata +214 -0
@@ -0,0 +1,286 @@
1
+ ;;; -*- mode: Emacs-Lisp; coding: utf-8 -*-
2
+
3
+ ;; Author: Yoshinari Nomura <nom@quickhack.net>,
4
+ ;; TSUCHIYA Masatoshi <tsuchiya@namazu.org>
5
+ ;; Created: 2000/04/30
6
+ ;; Revised: $Date$
7
+
8
+
9
+ ;;; Commentary:
10
+
11
+ ;; This file is a part of MHC, and includes functions to parse
12
+ ;; schedule headers.
13
+
14
+
15
+ ;;; Code:
16
+
17
+ (require 'mhc-logic)
18
+ (require 'mhc-record)
19
+ (require 'mhc-header)
20
+
21
+ (defvar mhc-parse/strict nil)
22
+
23
+ (defun mhc-parse/continuous-lines ()
24
+ "ヘッダの継続行を処理して、内容のみを取り出す関数"
25
+ (let (list)
26
+ (skip-chars-forward " \t\n")
27
+ (while (not (eobp))
28
+ (setq list
29
+ (cons (buffer-substring-no-properties
30
+ (point)
31
+ (progn (end-of-line) (skip-chars-backward " \t") (point)))
32
+ list))
33
+ (end-of-line)
34
+ (skip-chars-forward " \t\n"))
35
+ (mapconcat 'identity (nreverse list) " ")))
36
+
37
+ (defun mhc-parse/day (record schedule)
38
+ (mhc-logic-parse-day (mhc-schedule-condition schedule))
39
+ schedule)
40
+
41
+ (defun mhc-parse/cond (record schedule)
42
+ (mhc-logic-parse-cond (mhc-schedule-condition schedule))
43
+ schedule)
44
+
45
+ (defun mhc-parse/duration (record schedule)
46
+ (mhc-logic-parse-duration (mhc-schedule-condition schedule))
47
+ schedule)
48
+
49
+ (defun mhc-parse/priority (record schedule)
50
+ (if (looking-at mhc-logic/space-regexp)
51
+ (goto-char (match-end 0)))
52
+ (let ((content (buffer-substring
53
+ (point)
54
+ (progn (skip-chars-forward "0-9") (point)))))
55
+ (if (looking-at mhc-logic/space-regexp)
56
+ (goto-char (match-end 0)))
57
+ (if (eobp)
58
+ (mhc-schedule/set-priority schedule
59
+ (if (eq (length content) 0)
60
+ nil
61
+ (string-to-number content)))
62
+ (error "Parse ERROR !!!(at X-SC-Priority:)")))
63
+ schedule)
64
+
65
+ (defun mhc-parse/subject (record schedule)
66
+ (mhc-schedule/set-subject
67
+ schedule
68
+ (mhc-eword-decode-string (mhc-parse/continuous-lines)))
69
+ schedule)
70
+
71
+ (defun mhc-parse/location (record schedule)
72
+ (mhc-schedule/set-location
73
+ schedule
74
+ (mhc-eword-decode-string (mhc-parse/continuous-lines)))
75
+ schedule)
76
+
77
+ (defconst mhc-parse/time-regexp "\\([012][0-9]\\):\\([0-5][0-9]\\)")
78
+
79
+ (defun mhc-parse/time (record schedule)
80
+ (let ((time (mhc-parse/continuous-lines))
81
+ begin end)
82
+ (cond
83
+ ((string-match (concat "^" mhc-parse/time-regexp "-" mhc-parse/time-regexp "$") time)
84
+ (setq begin (+ (* 60 (string-to-number (match-string 1 time)))
85
+ (string-to-number (match-string 2 time)))
86
+ end (+ (* 60 (string-to-number (match-string 3 time)))
87
+ (string-to-number (match-string 4 time)))))
88
+ ((string-match (concat "^" mhc-parse/time-regexp "-?$") time)
89
+ (setq begin (+ (* 60 (string-to-number (match-string 1 time)))
90
+ (string-to-number (match-string 2 time)))))
91
+ ((string-match (concat "^-" mhc-parse/time-regexp "$") time)
92
+ (setq end (+ (* 60 (string-to-number (match-string 1 time)))
93
+ (string-to-number (match-string 2 time)))))
94
+ ((and mhc-parse/strict (not (string= "" time)))
95
+ (error "Parse ERROR!!!(at X-SC-Time:)")))
96
+ (mhc-schedule/set-time schedule begin end))
97
+ schedule)
98
+
99
+ ;; For backward compatibility.
100
+ (defun mhc-parse/old-style-date (record schedule)
101
+ (mhc-logic-parse-old-style-date (mhc-schedule-condition schedule))
102
+ (mhc-parse/time record schedule))
103
+
104
+ (defconst mhc-parse/alarm-regexp "^[0-9]+ \\(minute\\|hour\\|day\\)$")
105
+
106
+ (defun mhc-parse/alarm (record schedule)
107
+ (let ((alarm (mhc-parse/continuous-lines)))
108
+ (unless (or (not mhc-parse/strict)
109
+ (string-match mhc-parse/alarm-regexp alarm)
110
+ (string= "" alarm))
111
+ (error "Parse ERROR!!! (at X-SC-Alarm:)"))
112
+ (mhc-schedule/set-alarm schedule alarm))
113
+ schedule)
114
+
115
+ (defun mhc-parse/category (record schedule)
116
+ (let ((category (mhc-parse/continuous-lines)))
117
+ (mhc-schedule/set-categories
118
+ schedule
119
+ (nconc (delq nil
120
+ (mapcar
121
+ (lambda (str)
122
+ (and (stringp str) (downcase str)))
123
+ (mhc-misc-split
124
+ (mhc-eword-decode-string category)
125
+ "[ \t]+")))
126
+ (mhc-schedule-categories schedule))))
127
+ (mhc-logic/set-todo (mhc-schedule-condition schedule)
128
+ (mhc-schedule-in-category-p schedule "todo"))
129
+ schedule)
130
+
131
+
132
+ (defun mhc-parse/recurrence-tag (record schedule)
133
+ (mhc-schedule/set-recurrence-tag
134
+ schedule
135
+ (mhc-eword-decode-string (mhc-parse/continuous-lines)))
136
+ schedule)
137
+
138
+ (defun mhc-parse/sequence (record schedule)
139
+ (if (looking-at mhc-logic/space-regexp)
140
+ (goto-char (match-end 0)))
141
+ (let ((content (buffer-substring
142
+ (point)
143
+ (progn (skip-chars-forward "0-9") (point)))))
144
+ (if (looking-at mhc-logic/space-regexp)
145
+ (goto-char (match-end 0)))
146
+ (if (eobp)
147
+ (mhc-schedule/set-sequence schedule
148
+ (if (eq (length content) 0)
149
+ nil
150
+ (string-to-number content)))
151
+ (error "Parse ERROR !!!(at X-SC-Sequence:)")))
152
+ schedule)
153
+
154
+ ;; FIXME: 要削除
155
+ (defun mhc-parse/next (record schedule)
156
+ (let ((new (mhc-schedule-new record)))
157
+ (if schedule (mhc-schedule/set-region-end schedule (point-min)))
158
+ (mhc-schedule/set-region-start new (point-min))
159
+ new))
160
+
161
+ ;; FIXME: X-SC-Schedule の入れ子構造は、(mhc-db-add-exception-rule) の
162
+ ;; 実装の都合上受け入れられないので、top level 以外の X-SC-Schedule は
163
+ ;; 安全に無視される必要がある。
164
+ (defun mhc-parse/schedule (record schedule)
165
+ (let ((buffer (current-buffer))
166
+ (start (point))
167
+ (end (point-max))
168
+ (schedule (mhc-schedule-new record)))
169
+ (mhc-schedule/set-region-start schedule start)
170
+ (mhc-schedule/set-region-start schedule end)
171
+ (with-temp-buffer
172
+ (insert-buffer-substring buffer start end)
173
+ (goto-char (point-min))
174
+ (while (not (eobp))
175
+ (let ((start (point)))
176
+ (if (skip-chars-forward " \t\n")
177
+ (delete-region start (point))))
178
+ (while (if (eobp)
179
+ nil
180
+ (eq ?\\ (progn (end-of-line) (preceding-char))))
181
+ (delete-char -1)
182
+ (forward-line))
183
+ (forward-line))
184
+ (goto-char (point-min))
185
+ (mhc-parse/internal-parser record schedule)))
186
+ schedule)
187
+
188
+ ;; FIXME: top level 以外の場所で記述された X-SC-Record-Id: は安全に無
189
+ ;; 視される必要があるが、現在の実装では何も考えずに上書きしてしまう。
190
+ (defun mhc-parse/record-id (record schedule)
191
+ (mhc-record-set-id record (mhc-parse/continuous-lines))
192
+ schedule)
193
+
194
+ ;; FIXME: top level とそれ以外の場所で許される header が異なるので、
195
+ ;; multi pass parser に組み替えるべきかも知れない。
196
+ (defun mhc-parse/internal-parser (record &optional schedule strict)
197
+ "Internal parseser of schedule headers in this narrowed buffer."
198
+ (let ((mhc-parse/strict strict)
199
+ (case-fold-search t)
200
+ func)
201
+ (while (not (eobp))
202
+ (if (looking-at "\\([^ \t:]+\\):")
203
+ (progn
204
+ (setq func (mhc-header-parse-function
205
+ (format "%s" (match-string 1))))
206
+ (mhc-header-goto-end)
207
+ (if (fboundp func)
208
+ (save-restriction
209
+ (narrow-to-region (match-beginning 0) (point))
210
+ (goto-char (match-end 0))
211
+ (setq schedule
212
+ (funcall func
213
+ record
214
+ (or schedule
215
+ (if (memq func '(mhc-parse/schedule mhc-parse/next))
216
+ nil
217
+ (mhc-parse/next record nil)))))
218
+ (goto-char (point-max)))))
219
+ ;; Always skip non-header lines.
220
+ (forward-line 1))))
221
+ schedule)
222
+
223
+ (defun mhc-parse-buffer (&optional record strict)
224
+ "Parse schedule headers in this buffer."
225
+ (unless record
226
+ (setq record (mhc-record-new (buffer-file-name))))
227
+ (mhc-header-narrowing
228
+ (let ((schedule (mhc-parse/internal-parser record nil strict)))
229
+ (if schedule (mhc-schedule/set-region-end schedule (point)))))
230
+ ;; 得られた構造を整理する
231
+ (let (schedules sexp)
232
+ ;; 現れた順序に直しておく
233
+ (mhc-record-set-schedules record (nreverse (mhc-record-schedules record)))
234
+ ;; 先頭のスケジュールをデフォルトとして参照して、欠けている要素を埋めておく
235
+ (setq schedules (cdr (mhc-record-schedules record)))
236
+ (while schedules
237
+ (mhc-schedule-append-default (car schedules) (car (mhc-record-schedules record)))
238
+ (setq schedules (cdr schedules)))
239
+ ;; 各スケジュールの条件式を生成する
240
+ (mhc-logic-compile-file record))
241
+ record)
242
+
243
+ (defun mhc-parse-file (filename)
244
+ "Parse schedules headers in the file, FILENAME."
245
+ (with-current-buffer
246
+ (mhc-get-buffer-create " *mhc-parse-file*")
247
+ (delete-region (point-min) (point-max))
248
+ (mhc-insert-file-contents-as-coding-system mhc-default-coding-system filename)
249
+ (mhc-parse-buffer (mhc-record-new filename))))
250
+
251
+
252
+
253
+ (provide 'mhc-parse)
254
+
255
+ ;;; Copyright Notice:
256
+
257
+ ;; Copyright (C) 1999, 2000 Yoshinari Nomura. All rights reserved.
258
+ ;; Copyright (C) 2000 MHC developing team. All rights reserved.
259
+
260
+ ;; Redistribution and use in source and binary forms, with or without
261
+ ;; modification, are permitted provided that the following conditions
262
+ ;; are met:
263
+ ;;
264
+ ;; 1. Redistributions of source code must retain the above copyright
265
+ ;; notice, this list of conditions and the following disclaimer.
266
+ ;; 2. Redistributions in binary form must reproduce the above copyright
267
+ ;; notice, this list of conditions and the following disclaimer in the
268
+ ;; documentation and/or other materials provided with the distribution.
269
+ ;; 3. Neither the name of the team nor the names of its contributors
270
+ ;; may be used to endorse or promote products derived from this software
271
+ ;; without specific prior written permission.
272
+ ;;
273
+ ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
274
+ ;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
275
+ ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
276
+ ;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
277
+ ;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
278
+ ;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
279
+ ;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
280
+ ;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281
+ ;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
282
+ ;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283
+ ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
284
+ ;; OF THE POSSIBILITY OF SUCH DAMAGE.
285
+
286
+ ;;; mhc-parse.el ends here.
@@ -0,0 +1,35 @@
1
+ (defvar mhc-process nil)
2
+
3
+ (add-to-list 'process-coding-system-alist '("^mhc$" . utf-8))
4
+
5
+ (defun mhc-process-send-command (command)
6
+ (unless (and (processp mhc-process)
7
+ (eq (process-status mhc-process) 'run))
8
+ (mhc-start-process))
9
+ (message "COMMAND: %s" command)
10
+ (with-current-buffer (process-buffer mhc-process)
11
+ (delete-region (point-min) (point-max))
12
+ (process-send-string mhc-process (concat command "\n"))
13
+ (let ((i 1))
14
+ (while (not (and (> (point-max) 1)
15
+ (eq (char-after (1- (point-max))) ?\n)))
16
+ (message (format "Waiting mhc process...%d" i))
17
+ (setq i (1+ i))
18
+ (accept-process-output mhc-process 0.5)))
19
+ (read (buffer-substring (point-min) (1- (point-max))))))
20
+
21
+ (defun mhc-start-process ()
22
+ (interactive)
23
+ (let ((process-connection-type nil)) ;; use PIPE not tty
24
+ (if (and (processp mhc-process)
25
+ (eq (process-status mhc-process) 'run))
26
+ (kill-process mhc-process))
27
+ (setq mhc-process (start-process
28
+ "mhc"
29
+ (get-buffer-create " *mhc-scan-process*")
30
+ "mhc"
31
+ "server"))
32
+ (set-process-query-on-exit-flag mhc-process nil)
33
+ mhc-process))
34
+
35
+ (provide 'mhc-process)
data/emacs/mhc-ps.el ADDED
@@ -0,0 +1,1174 @@
1
+ ;;; -*- mode: Emacs-Lisp; coding: utf-8 -*-
2
+
3
+ ;; Author: TSUCHIYA Masatoshi <tsuchiya@namazu.org>
4
+ ;; Hideyuki SHIRAI <shirai@quickhack.net>
5
+ ;; Created: 2000/06/18
6
+ ;; Revised: $Date: 2004/05/06 16:35:12 $
7
+
8
+
9
+ ;;; Commentary:
10
+
11
+ ;; This file is a part of MHC and includes functions to make
12
+ ;; PostScrpit calendar.
13
+
14
+
15
+ ;;; History:
16
+
17
+ ;; Original PostScript program was written
18
+ ;; by Patrick Wood <patwood@unirot.UUCP> in 1987.
19
+ ;;
20
+ ;; Shell stuff added by King Ables at Sep 3, 1987.
21
+ ;;
22
+ ;; Made pretty by tjt in 1988.
23
+ ;;
24
+ ;; Holiday and printer flag passing hacks added by
25
+ ;; smann@june.cs.washington.edu in Dec 1988.
26
+ ;;
27
+ ;; Used the better looking version with 5 rows of days rather than 6
28
+ ;; hacked together with holiday and banner/footnotes added
29
+ ;; by Joe Wood <jlw@lzga.ATT.COM> in Dec 1989.
30
+ ;;
31
+ ;; Fixed "-R" (didn't work at all; now it at least works on 8.5x11)
32
+ ;; and also fixed handling of unrecognized arguments
33
+ ;; by Jeff Mogul <mogul@decwrl.dec.com> in Jan 1990.
34
+ ;;
35
+ ;; Japanized and improved handling holidays
36
+ ;; by SUZUKI Shingo <ichimal@takopen.cs.uec.ac.jp> in Feb 2000.
37
+ ;;
38
+ ;; Stuffs rewritten with Emacs Lisp
39
+ ;; by TSUCHIYA Masatoshi <tsuchiya@namazu.org>
40
+ ;; in Jun 2000.
41
+
42
+
43
+ ;;; Bugs:
44
+
45
+ ;; This program doesn't work for months before 1753 (weird stuff
46
+ ;; happened in September, 1752).
47
+
48
+
49
+ ;;; Code:
50
+
51
+ (require 'mhc)
52
+
53
+
54
+ ;;; Customize variables:
55
+
56
+ (defcustom mhc-ps-preview-command "gv"
57
+ "*Command to preview PostScript calendar."
58
+ :group 'mhc
59
+ :type 'string)
60
+
61
+ (defcustom mhc-ps-preview-command-arguments '()
62
+ "*Argument of previewer"
63
+ :group 'mhc
64
+ :type '(repeat string))
65
+
66
+ (defcustom mhc-ps-print-command "lp"
67
+ "*Command to print PostScript calendar."
68
+ :group 'mhc
69
+ :type 'string)
70
+
71
+ (defcustom mhc-ps-print-command-arguments '()
72
+ "*Argument of print command."
73
+ :group 'mhc
74
+ :type '(repeat string))
75
+
76
+ (defcustom mhc-ps-paper-type t
77
+ "*Calendar paper type."
78
+ :group 'mhc
79
+ :type '(radio (const :tag "Landscape" t)
80
+ (const :tag "Portrait" nil)))
81
+
82
+ (defcustom mhc-ps-paper-fill-print nil
83
+ "*Fill printing just in Landscape paper size."
84
+ :group 'mhc
85
+ :type 'boolean)
86
+
87
+ (defcustom mhc-ps-truncate-lines nil
88
+ "*Truncate line."
89
+ :group 'mhc
90
+ :type 'boolean)
91
+
92
+ (defcustom mhc-ps-left-margin 2
93
+ "*Left margin of the each schedule."
94
+ :group 'mhc
95
+ :type 'integer)
96
+
97
+ (defcustom mhc-ps-string-width 20
98
+ "*Width of the each schedule."
99
+ :group 'mhc
100
+ :type 'integer)
101
+
102
+ (defcustom mhc-ps-string-column 7
103
+ "*Column of the each schedule."
104
+ :group 'mhc
105
+ :type 'integer)
106
+
107
+ (defcustom mhc-ps-title-font "Times-Bold"
108
+ "*PostScript Font used for title."
109
+ :group 'mhc
110
+ :type 'string)
111
+
112
+ (defcustom mhc-ps-day-font "Helvetica-Bold"
113
+ "*PostScript Font used for days."
114
+ :group 'mhc
115
+ :type 'string)
116
+
117
+ (defcustom mhc-ps-event-font "Times-Roman"
118
+ "*PostScript Font used for events."
119
+ :group 'mhc
120
+ :type 'string)
121
+
122
+ (defcustom mhc-ps-japanese-font "Ryumin-Light-EUC-H"
123
+ "*PostScript Font used for Japanese characters."
124
+ :group 'mhc
125
+ :type 'string)
126
+
127
+ (defcustom mhc-ps-coding-system
128
+ (if (boundp 'MULE) '*euc-japan*unix 'euc-japan-unix)
129
+ "*Coding system of PostScript data."
130
+ :group 'mhc
131
+ :type 'symbol)
132
+
133
+ (defcustom mhc-ps-save-directory "~/"
134
+ "*Directory to save PostScript file."
135
+ :group 'mhc
136
+ :type 'directory)
137
+
138
+ ;;; Internal Variables:
139
+ (defconst mhc-ps/string "\
140
+ %!
141
+ % PostScript program to draw calendar
142
+ % Copyright \(C\) 1987 by Pipeline Associates, Inc.
143
+ % Permission is granted to modify and distribute this free of charge.
144
+
145
+ % The number after /month should be set to a number from 1 to 12.
146
+ % The number after /year should be set to the year you want.
147
+ % You can change the title and date fonts, if you want.
148
+ % We figure out the rest.
149
+ % This program won't produce valid calendars before 1800 due to the switch
150
+ % from Julian to Gregorian calendars in September of 1752 wherever English
151
+ % was spoken.
152
+
153
+ %% For Japanese. Added by ichimal, 2000/2/6.
154
+ %% Original code is generated by k2ps.
155
+ /copyfont { % font-dic extra-entry-count copyfont font-dic
156
+ 1 index maxlength add dict begin
157
+ {
158
+ 1 index /FID ne 2 index /UniqueID ne and
159
+ {def}{pop pop} ifelse
160
+ } forall
161
+ currentdict
162
+ end
163
+ } bind def
164
+
165
+ %% For Japanese. Added by ichimal, 2000/2/6.
166
+ %% Original code is generated by k2ps.
167
+ /narrowfont { % ASCIIFontName EUCFontName compositefont font'
168
+ findfont dup /FontType get 0 eq {
169
+ 12 dict begin
170
+ %
171
+ % 7+8 bit EUC font
172
+ %
173
+ 12 dict begin
174
+ /EUCFont exch def
175
+ /FontInfo \(7+8 bit EUC font\) readonly def
176
+ /PaintType 0 def
177
+ /FontType 0 def
178
+ /FontMatrix matrix def
179
+ % /FontName
180
+ /Encoding \[
181
+ 16#00 1 16#20 { pop 0 } for
182
+ 16#21 1 16#28 { 16#20 sub } for
183
+ 16#29 1 16#2F { pop 0 } for
184
+ 16#30 1 16#74 { 16#27 sub } for
185
+ 16#75 1 16#FF { pop 0 } for
186
+ \] def
187
+ /FMapType 2 def
188
+ EUCFont /WMode known
189
+ { EUCFont /WMode get /WMode exch def }
190
+ { /WMode 0 def } ifelse
191
+ /FDepVector \[
192
+ EUCFont /FDepVector get 0 get
193
+ \[ 16#21 1 16#28 {} for 16#30 1 16#74 {} for \]
194
+ {
195
+ 13 dict begin
196
+ /EUCFont EUCFont def
197
+ /UpperByte exch 16#80 add def
198
+ % /FontName
199
+ /FontInfo \(EUC lower byte font\) readonly def
200
+ /PaintType 0 def
201
+ /FontType 3 def
202
+ /FontMatrix matrix def
203
+ /FontBBox {0 0 0 0} def
204
+ /Encoding \[
205
+ 16#00 1 16#A0 { pop /.notdef } for
206
+ 16#A1 1 16#FE { 16#80 sub 16 2 string cvrs
207
+ \(cXX\) dup 1 4 -1 roll
208
+ putinterval cvn } for
209
+ /.notdef
210
+ \] def
211
+ % /UniqueID
212
+ % /WMode
213
+ /BuildChar {
214
+ gsave
215
+ exch dup /EUCFont get setfont
216
+ /UpperByte get
217
+ 2 string
218
+ dup 0 4 -1 roll put
219
+ dup 1 4 -1 roll put
220
+ dup stringwidth setcharwidth
221
+ 0 0 moveto show
222
+ grestore
223
+ } bind def
224
+ currentdict
225
+ end
226
+ /lowerbytefont exch definefont
227
+ } forall
228
+ \] def
229
+ currentdict
230
+ end
231
+ /eucfont exch definefont
232
+ exch
233
+ findfont 1 copyfont dup begin
234
+ /FontMatrix FontMatrix \[.83 0 0 1 0 0.05\] matrix concatmatrix def
235
+ end
236
+ /asciifont exch definefont
237
+ exch
238
+ /FDepVector \[ 4 2 roll \] def
239
+ /FontType 0 def
240
+ /WMode 0 def
241
+ /FMapType 4 def
242
+ /FontMatrix matrix def
243
+ /Encoding \[0 1\] def
244
+ /FontBBox {0 0 0 0} def
245
+ currentdict
246
+ end
247
+ }{
248
+ pop findfont 0 copyfont
249
+ } ifelse
250
+ } def
251
+
252
+ /month @MONTH@ def
253
+ /year @YEAR@ def
254
+ /titlefont /@TFONT@ def
255
+ /dayfont /@DFONT@ def
256
+ %% For Japanese. Changed by ichimal, 2000/2/6.
257
+ %% Original code is generated by k2ps.
258
+ %% /eventfont /@EFONT@ def
259
+ /Courier-Ryumin
260
+ /@EFONT@ /@JFONT@ narrowfont definefont pop
261
+ /eventfont /Courier-Ryumin def
262
+
263
+ /holidays \[ @HOLIDAYS@ \] def
264
+ /lholidays \[ @LHOLIDAYS@ \] def
265
+ /nholidays \[ @NHOLIDAYS@ \] def
266
+ /schedules \[ @SCHEDULES@ \] def
267
+ /lschedules \[ @LSCHEDULES@ \] def
268
+ /nschedules \[ @NSCHEDULES@ \] def
269
+ /Bannerstring \(@BANNER@\) def
270
+ /Lfootstring \(@LFOOT@\) def
271
+ /Rfootstring \(@RFOOT@\) def
272
+ /Cfootstring \(@CFOOT@\) def
273
+
274
+ % calendar names - change these if you don't speak english
275
+ % \"August\", \"April\" and \"February\" could stand to be kerned even if you do
276
+
277
+ /month_names
278
+ \[ \(January\) \(February\) \(March\) \(April\) \(May\) \(June\) \(July\)
279
+ \(August\) \(September\) \(October\) \(November\) \(December\) \]
280
+ def
281
+
282
+ /day_names
283
+ \[ \(Sunday\) \(Monday\) \(Tuesday\) \(Wednesday\) \(Thursday\) \(Friday\) \(Saturday\) \]
284
+ def
285
+
286
+ % layout parameters - you can change these, but things may not look nice
287
+
288
+ /daywidth 100 def
289
+ /dayheight 95 def
290
+
291
+ /titlefontsize 48 def
292
+ /weekdayfontsize 10 def
293
+ /datefontsize 24 def
294
+ /footfontsize 20 def
295
+
296
+ /topgridmarg 35 def
297
+ /leftmarg 35 def
298
+ /daytopmarg 14 def
299
+ /dayleftmarg 5 def
300
+
301
+ % layout constants - don't change these, things probably won't work
302
+
303
+ /mainrows @WEEKS@ def
304
+ /subrows 6 def
305
+
306
+ % calendar constants - change these if you want a French revolutionary calendar
307
+
308
+ /days_week 7 def
309
+
310
+ /days_month \[ 31 28 31 30 31 30 31 31 30 31 30 31 \] def
311
+
312
+ /isleap { % is this a leap year?
313
+ year 4 mod 0 eq % multiple of 4
314
+ year 100 mod 0 ne % not century
315
+ year 1000 mod 0 eq or and % unless it's a millenia
316
+ } def
317
+
318
+ /ndays { % number of days in this month
319
+ days_month month 1 sub get
320
+ month 2 eq % February
321
+ isleap and
322
+ {
323
+ 1 add
324
+ } if
325
+ } def
326
+
327
+ /weekday { % weekday \(range 0-6\) for integer date
328
+ days_week mod
329
+ } def
330
+
331
+ /startday { % starting day-of-week for this month
332
+ /off year 2032 sub def % offset from start of \"epoch\"
333
+ off
334
+ off 4 idiv add % number of leap years
335
+ off 100 idiv sub % number of centuries
336
+ off 1000 idiv add % number of millenia
337
+ 4 add weekday days_week add % offset from Jan 1 2032
338
+ /off exch def
339
+ 1 1 month 1 sub {
340
+ /idx exch def
341
+ days_month idx 1 sub get
342
+ idx 2 eq
343
+ isleap and
344
+ {
345
+ 1 add
346
+ } if
347
+ /off exch off add def
348
+ } for
349
+ off weekday % 0--Sunday, 1--monday, etc.
350
+ } def
351
+
352
+ /prtevent { % event-string day prtevent
353
+ % print out an event
354
+ /start startday def
355
+ /day 2 1 roll def
356
+ day start add 1 sub 7 mod daywidth mul
357
+ day start add 1 sub 7 div truncate dayheight neg mul
358
+ -5
359
+ numevents day start add get -10 mul add
360
+ numevents
361
+ day start add
362
+ numevents day start add get 1 add
363
+ put
364
+ add 2 add moveto
365
+ show
366
+ } def
367
+
368
+ /drawevents { % read in a file full of events; print
369
+ % the events for this month
370
+ /numevents
371
+ \[0 0 0 0 0 0 0
372
+ 0 0 0 0 0 0 0
373
+ 0 0 0 0 0 0 0
374
+ 0 0 0 0 0 0 0
375
+ 0 0 0 0 0 0 0
376
+ 0 0 0 0 0 0 0
377
+ 0 0 0 0 0 0 0\] def
378
+ eventfont findfont 9 scalefont setfont
379
+ 0 2 holidays length 2 sub { % for the \"Holidays\"
380
+ dup
381
+ 1 add holidays 2 1 roll get
382
+ 2 1 roll holidays 2 1 roll get
383
+ prtevent
384
+ } for
385
+ 0 2 schedules length 2 sub { % for the \"Schedules\"
386
+ dup
387
+ 1 add schedules 2 1 roll get
388
+ 2 1 roll schedules 2 1 roll get
389
+ prtevent
390
+ } for
391
+ } def
392
+
393
+ % ------------------------------------------------------------------------
394
+
395
+ /prtnum { 3 string cvs show } def
396
+
397
+ /center { % center string in given width
398
+ /width exch def
399
+ /str exch def width str
400
+ stringwidth pop sub 2 div 0 rmoveto str show
401
+ } def
402
+
403
+ /centernum { exch 3 string cvs exch center } def
404
+
405
+ /drawgrid { % draw calendar boxes
406
+ titlefont findfont weekdayfontsize scalefont setfont
407
+ currentpoint /y0 exch def /x0 exch def
408
+ 0 1 days_week 1 sub {
409
+ submonth 0 eq
410
+ {
411
+ x0 y0 moveto
412
+ dup dup daywidth mul 40 rmoveto
413
+ day_names exch get
414
+ daywidth center
415
+ } if
416
+ x0 y0 moveto
417
+ daywidth mul topgridmarg rmoveto
418
+ 1.0 setlinewidth
419
+ submonth 0 eq
420
+ {
421
+ /rowsused mainrows 1 sub def
422
+ }
423
+ {
424
+ /rowsused subrows 1 sub def
425
+ }
426
+ ifelse
427
+ 0 1 rowsused {
428
+ gsave
429
+ daywidth 0 rlineto
430
+ 0 dayheight neg rlineto
431
+ daywidth neg 0 rlineto
432
+ closepath stroke
433
+ grestore
434
+ 0 dayheight neg rmoveto
435
+ } for
436
+ } for
437
+ } def
438
+
439
+ /drawnums { % place day numbers on calendar
440
+ dayfont findfont datefontsize
441
+ submonth 0 ne
442
+ {
443
+ 2.5 mul
444
+ } if scalefont setfont
445
+ /start startday def
446
+ /days ndays def
447
+ start daywidth mul dayleftmarg add daytopmarg rmoveto
448
+ submonth 0 ne
449
+ {
450
+ dayleftmarg neg dayheight -2 div rmoveto
451
+ } if
452
+ 1 1 days {
453
+ /day exch def
454
+ gsave
455
+ day start add weekday 0 eq
456
+ {
457
+ submonth 0 eq {
458
+ .7 setgray
459
+ }
460
+ {
461
+ holidaymark
462
+ } ifelse
463
+ } if
464
+ day start add weekday 1 eq
465
+ {
466
+ submonth 0 eq {
467
+ .7 setgray
468
+ }
469
+ {
470
+ holidaymark
471
+ } ifelse
472
+ } if
473
+ %% Added by ichimal, 2000.2
474
+ submonth 0 eq {
475
+ 0 2 holidays length 2 sub {
476
+ holidays 2 1 roll get day eq {
477
+ .7 setgray
478
+ exit
479
+ } if
480
+ } for
481
+ }
482
+ {
483
+ nsubmonth 0 eq {
484
+ 0 1 lholidays length 1 sub {
485
+ lholidays exch get day eq {
486
+ holidaymark
487
+ exit
488
+ } if
489
+ } for
490
+ 0 1 lschedules length 1 sub {
491
+ lschedules exch get day eq {
492
+ shedulemark
493
+ exit
494
+ } if
495
+ } for
496
+ }
497
+ {
498
+ 0 1 nholidays length 1 sub {
499
+ nholidays exch get day eq {
500
+ holidaymark
501
+ exit
502
+ } if
503
+ } for
504
+ 0 1 nschedules length 1 sub {
505
+ nschedules exch get day eq {
506
+ shedulemark
507
+ exit
508
+ } if
509
+ } for
510
+ } ifelse
511
+ } ifelse
512
+ submonth 0 eq
513
+ {
514
+ day prtnum
515
+ }
516
+ {
517
+ day daywidth centernum
518
+ } ifelse
519
+ grestore
520
+ day start add weekday 0 eq
521
+ {
522
+ currentpoint exch pop dayheight sub 0 exch moveto
523
+ submonth 0 eq
524
+ {
525
+ dayleftmarg 0 rmoveto
526
+ } if
527
+ }
528
+ {
529
+ daywidth 0 rmoveto
530
+ } ifelse
531
+ } for
532
+ } def
533
+
534
+ /holidaymark { % tiny holiday mark
535
+ gsave
536
+ 0 dayheight 2 div daytopmarg add 5 add rmoveto
537
+ daywidth 0 rlineto
538
+ 0 dayheight neg rlineto
539
+ daywidth neg 0 rlineto
540
+ .9 setgray
541
+ closepath fill
542
+ grestore
543
+ } def
544
+
545
+ /shedulemark { % tiny shedule mark
546
+ gsave
547
+ 80 60 rmoveto
548
+ 10 0 rlineto 0 -10 rlineto
549
+ -10 0 rlineto 0 10 rlineto
550
+ closepath
551
+ .0 setgray fill
552
+ grestore
553
+ } def
554
+
555
+ /drawfill { % place fill squares on calendar
556
+ /start startday def
557
+ /days ndays def
558
+ currentpoint /y0 exch def /x0 exch def
559
+ submonth 0 eq
560
+ {
561
+ usefirst
562
+ {
563
+ /fillstart 2 def
564
+ }
565
+ {
566
+ /fillstart 0 def
567
+ }
568
+ ifelse
569
+ }
570
+ {
571
+ /fillstart 0 def
572
+ }
573
+ ifelse
574
+ fillstart daywidth mul topgridmarg rmoveto
575
+ 1.0 setlinewidth
576
+ fillstart 1 start 1 sub {
577
+ gsave
578
+ .9 setgray
579
+ daywidth 0 rlineto
580
+ 0 dayheight neg rlineto
581
+ daywidth neg 0 rlineto
582
+ closepath fill
583
+ grestore
584
+ daywidth 0 rmoveto
585
+ } for
586
+ x0 y0 moveto
587
+ submonth 0 ne
588
+ {
589
+ /lastday subrows days_week mul def
590
+ days_week 1 sub daywidth mul -440 rmoveto
591
+ }
592
+ {
593
+ /lastday mainrows days_week mul 2 sub fillstart add def
594
+ days_week 3 sub fillstart add daywidth mul
595
+ @FOFFSET@ dayheight add rmoveto
596
+ } ifelse
597
+ lastday -1 ndays start 1 add add
598
+ {
599
+ /day exch def
600
+ gsave
601
+ .9 setgray
602
+ daywidth 0 rlineto
603
+ 0 dayheight neg rlineto
604
+ daywidth neg 0 rlineto
605
+ closepath fill
606
+ grestore
607
+ day weekday 1 eq
608
+ {
609
+ submonth 0 ne
610
+ {
611
+ x0 y0 moveto
612
+ days_week 1 sub daywidth mul
613
+ -440 dayheight add rmoveto
614
+ }
615
+ {
616
+ x0 y0 moveto
617
+ days_week 1 sub daywidth mul
618
+ @FOFFSET@ dayheight add rmoveto
619
+ } ifelse
620
+ }
621
+ {
622
+ daywidth neg 0 rmoveto
623
+ } ifelse
624
+ } for
625
+ } def
626
+
627
+ /usefirst { % are last two boxes used by days?
628
+ start ndays add mainrows days_week mul 3 sub gt
629
+ start 2 ge and
630
+ mainrows 6 eq or
631
+ } def
632
+
633
+ /calendar
634
+ {
635
+ titlefont findfont titlefontsize scalefont setfont
636
+ 0 60 moveto
637
+ /month_name month_names month 1 sub get def
638
+ month_name show
639
+ /yearstring year 10 string cvs def
640
+ daywidth days_week mul yearstring stringwidth pop sub 60 moveto
641
+ yearstring show
642
+
643
+ eventflag {
644
+ % Show a centered Banner if any at the Top
645
+ daywidth days_week mul 2 div
646
+ Bannerstring stringwidth pop 2 div sub
647
+ 60 moveto
648
+ Bannerstring show
649
+ % Show footnotes left-center-right
650
+ eventfont findfont footfontsize scalefont setfont
651
+ /bottomrow { dayheight mainrows mul 5 sub neg } def
652
+ 0 bottomrow moveto
653
+ Lfootstring show
654
+ daywidth days_week mul Rfootstring stringwidth pop sub
655
+ bottomrow moveto
656
+ Rfootstring show
657
+ daywidth days_week mul Cfootstring stringwidth pop sub 2 div
658
+ bottomrow moveto
659
+ Cfootstring show
660
+
661
+ } if
662
+
663
+ 0 -5 moveto
664
+ drawnums
665
+
666
+ 0 -5 moveto
667
+ drawfill
668
+
669
+ eventflag {
670
+ 0 0 moveto
671
+ drawevents
672
+ } if
673
+
674
+ 0 -5 moveto
675
+ drawgrid
676
+ } def
677
+
678
+ /eventflag true def
679
+
680
+ @SCALE@ scale
681
+ @ROTATE@ rotate
682
+ @TRANSLATE@ translate
683
+ /submonth 0 def
684
+ calendar
685
+ /eventflag false def
686
+ month 1 sub 0 eq
687
+ {
688
+ /lmonth 12 def
689
+ /lyear year 1 sub def
690
+ }
691
+ {
692
+ /lmonth month 1 sub def
693
+ /lyear year def
694
+ } ifelse
695
+ month 1 add 13 eq
696
+ {
697
+ /nmonth 1 def
698
+ /nyear year 1 add def
699
+ }
700
+ {
701
+ /nmonth month 1 add def
702
+ /nyear year def
703
+ } ifelse
704
+ usefirst
705
+ {
706
+ 0 30 translate
707
+ }
708
+ {
709
+ days_week 2 sub daywidth mul -350 translate
710
+ }
711
+ ifelse
712
+ /submonth 1 def
713
+ /nsubmonth 0 def
714
+ /year lyear def
715
+ /month lmonth def
716
+ gsave
717
+ .138 .138 scale
718
+ 12 -120 translate
719
+ calendar
720
+ grestore
721
+ /submonth 1 def
722
+ /nsubmonth 1 def
723
+ /year nyear def
724
+ /month nmonth def
725
+ daywidth 0 translate
726
+ gsave
727
+ .138 .138 scale
728
+ 12 -120 translate
729
+ calendar
730
+ grestore
731
+
732
+ showpage
733
+ ")
734
+
735
+ (defconst mhc-ps/replace-table
736
+ '(("@MONTH@" . (format "%d" month))
737
+ ("@YEAR@" . (format "%d" year))
738
+ ("@TFONT@" . mhc-ps-title-font)
739
+ ("@DFONT@" . mhc-ps-day-font)
740
+ ("@EFONT@" . mhc-ps-event-font)
741
+ ("@JFONT@" . mhc-ps-japanese-font)
742
+ ("@HOLIDAYS@" . holidays-buffer)
743
+ ("@SCHEDULES@" . schedules-buffer)
744
+ ("@LHOLIDAYS@" . last-holidays-buffer)
745
+ ("@LSCHEDULES@" . last-schedules-buffer)
746
+ ("@NHOLIDAYS@" . next-holidays-buffer)
747
+ ("@NSCHEDULES@" . next-schedules-buffer)
748
+ ("@WEEKS@" . (number-to-string weeks))
749
+ ("@FOFFSET@" . (if (eq weeks 6) "-535" "-440"))
750
+ ("@BANNER@" . (user-login-name))
751
+ ("@LFOOT@" . "")
752
+ ("@RFOOT@" . "")
753
+ ("@CFOOT@" . "")
754
+ ("@SCALE@" . (cond
755
+ ((and mhc-ps-paper-type
756
+ (or (not mhc-ps-paper-fill-print)
757
+ (eq weeks 6)))
758
+ "0.85 0.85")
759
+ (mhc-ps-paper-type "1.0 1.0")
760
+ (t "0.75 0.75")))
761
+ ("@ROTATE@" . (if mhc-ps-paper-type "90" "0"))
762
+ ("@TRANSLATE@" . (cond
763
+ ((and mhc-ps-paper-type
764
+ (or (not mhc-ps-paper-fill-print)
765
+ (eq weeks 6)))
766
+ "140 -120")
767
+ (mhc-ps-paper-type "50 -120")
768
+ (t "50 900")))))
769
+
770
+ (defun mhc-ps/weeks (date)
771
+ (if (> (+ (mhc-date-dd (mhc-date-mm-last date))
772
+ (mhc-date-ww (mhc-date-mm-first date)))
773
+ 35) 6 5))
774
+
775
+ (defun mhc-ps/substring (str width)
776
+ (let ((clist (mhc-string-to-char-list str))
777
+ cw (i 0) (w 0) (ow 0) (spc ?\ ))
778
+ (catch 'loop
779
+ (while clist
780
+ (setq w (+ w (char-width (car clist))))
781
+ (if (> w width) (throw 'loop nil))
782
+ (setq i (+ i (length (char-to-string (car clist)))))
783
+ (setq clist (cdr clist))))
784
+ (substring str 0 i)))
785
+
786
+ (defun mhc-ps/compose-subject (time subject margin)
787
+ (let ((mstr (make-string margin ?\ ))
788
+ pos str)
789
+ ;; Delete characters to emphasize subject.
790
+ (and (string-match "^\\*+[ \t\r\f\n]*" subject)
791
+ (setq pos (match-end 0))
792
+ (string-match "[ \t\r\f\n]*\\*+$" subject)
793
+ (setq subject (substring subject pos (match-beginning 0))))
794
+ (if time
795
+ (setq str (concat time " " subject))
796
+ (setq str subject))
797
+ (cond
798
+ ((<= (string-width str) mhc-ps-string-width)
799
+ (list str))
800
+ (mhc-ps-truncate-lines
801
+ (if (null time)
802
+ (list
803
+ (if (= (string-width
804
+ (setq subject (mhc-ps/substring subject mhc-ps-string-width)))
805
+ mhc-ps-string-width)
806
+ (concat subject "$")
807
+ subject))
808
+ (setq subject (concat mstr subject))
809
+ (if (= (string-width
810
+ (setq subject (mhc-ps/substring subject mhc-ps-string-width)))
811
+ mhc-ps-string-width)
812
+ (setq subject (concat subject "$")))
813
+ (list time subject)))
814
+ (t
815
+ (with-temp-buffer
816
+ (let ((fill-column mhc-ps-string-width)
817
+ (left-margin 0)
818
+ ret)
819
+ (insert str)
820
+ (fill-region (point-min) (point-max))
821
+ (goto-char (point-min))
822
+ (if (= (forward-line 1) 0)
823
+ (let ((fill-column (- mhc-ps-string-width margin)))
824
+ (fill-region (point) (point-max))))
825
+ (delete-region (goto-char (point-max))
826
+ (progn (skip-chars-backward " \t\n") (point)))
827
+ (goto-char (point-min))
828
+ (setq ret (list (buffer-substring
829
+ (point) (progn (end-of-line) (point)))))
830
+ (forward-line 1)
831
+ (while (not (eobp))
832
+ (setq ret (cons
833
+ (concat
834
+ mstr
835
+ (buffer-substring
836
+ (point) (progn (end-of-line) (point))))
837
+ ret))
838
+ (forward-line 1))
839
+ (nreverse ret)))))))
840
+
841
+ (defun mhc-ps/encode-string (string)
842
+ (let ((start 0) buf ch)
843
+ (while (string-match "[()\\\\]" string start)
844
+ (setq ch (aref string (match-beginning 0))
845
+ buf (cons (if (eq ch ?\() "\\("
846
+ (if (eq ch ?\)) "\\)"
847
+ "\\\\"))
848
+ (cons (substring string start (match-beginning 0)) buf))
849
+ start (match-end 0)))
850
+ (eval (cons 'concat (nreverse (cons (substring string start) buf))))))
851
+
852
+
853
+ (defun mhc-ps/schedule-to-string (dayinfo schedule)
854
+ (let ((begin (mhc-schedule-time-begin schedule))
855
+ (end (mhc-schedule-time-end schedule))
856
+ (day (mhc-day-day-of-month dayinfo)))
857
+ (if (or begin end)
858
+ (mapconcat (lambda (str)
859
+ (format "%d ( %s)" day (mhc-ps/encode-string str)))
860
+ (mhc-ps/compose-subject
861
+ (concat
862
+ (if begin (mhc-time-to-string begin) "")
863
+ (if end (concat "-" (mhc-time-to-string end)) ""))
864
+ (mhc-schedule-subject-as-string schedule)
865
+ mhc-ps-left-margin)
866
+ " ")
867
+ (mapconcat (lambda (str)
868
+ (format "%d ( %s)" day (mhc-ps/encode-string str)))
869
+ (mhc-ps/compose-subject
870
+ nil
871
+ (mhc-schedule-subject-as-string schedule) mhc-ps-left-margin)
872
+ " "))))
873
+
874
+
875
+ (defun mhc-ps/uniq-list (lst)
876
+ (let ((tmp lst))
877
+ (while tmp (setq tmp (setcdr tmp (delete (car tmp) (cdr tmp))))))
878
+ lst)
879
+
880
+
881
+ (defun mhc-ps/make-contents (file year month &optional category-predicate)
882
+ (let ((weeks (mhc-ps/weeks (mhc-date-new year month 1)))
883
+ (last-yymm (mhc-date-mm-- (mhc-date-new year month 1)))
884
+ (next-yymm (mhc-date-mm++ (mhc-date-new year month 1)))
885
+ schedules-buffer holidays-buffer
886
+ last-schedules-buffer last-holidays-buffer
887
+ next-schedules-buffer next-holidays-buffer)
888
+ ;; this month
889
+ (let ((dayinfo-list (mhc-db-scan-month year month)))
890
+ (while dayinfo-list
891
+ (let ((schedules (mhc-day-schedules (car dayinfo-list))))
892
+ (while schedules
893
+ (when (funcall category-predicate (car schedules))
894
+ (if (mhc-schedule-in-category-p (car schedules) "holiday")
895
+ (setq holidays-buffer
896
+ (cons (mhc-ps/schedule-to-string
897
+ (car dayinfo-list) (car schedules))
898
+ holidays-buffer))
899
+ (setq schedules-buffer
900
+ (cons (mhc-ps/schedule-to-string
901
+ (car dayinfo-list) (car schedules))
902
+ schedules-buffer))))
903
+ (setq schedules (cdr schedules))))
904
+ (setq dayinfo-list (cdr dayinfo-list))))
905
+ ;; last month
906
+ (let ((dayinfo-list (mhc-date-let last-yymm (mhc-db-scan-month yy mm))))
907
+ (while dayinfo-list
908
+ (let ((schedules (mhc-day-schedules (car dayinfo-list))))
909
+ (while schedules
910
+ (when (funcall category-predicate (car schedules))
911
+ (if (mhc-schedule-in-category-p (car schedules) "holiday")
912
+ (setq last-holidays-buffer
913
+ (cons (number-to-string
914
+ (mhc-day-day-of-month (car dayinfo-list)))
915
+ last-holidays-buffer))
916
+ (setq last-schedules-buffer
917
+ (cons (number-to-string(mhc-day-day-of-month (car dayinfo-list)))
918
+ last-schedules-buffer))))
919
+ (setq schedules (cdr schedules))))
920
+ (setq dayinfo-list (cdr dayinfo-list))))
921
+ ;; next month
922
+ (let ((dayinfo-list (mhc-date-let next-yymm (mhc-db-scan-month yy mm))))
923
+ (while dayinfo-list
924
+ (let ((schedules (mhc-day-schedules (car dayinfo-list))))
925
+ (while schedules
926
+ (when (funcall category-predicate (car schedules))
927
+ (if (mhc-schedule-in-category-p (car schedules) "holiday")
928
+ (setq next-holidays-buffer
929
+ (cons (number-to-string
930
+ (mhc-day-day-of-month (car dayinfo-list)))
931
+ next-holidays-buffer))
932
+ (setq next-schedules-buffer
933
+ (cons (number-to-string
934
+ (mhc-day-day-of-month (car dayinfo-list)))
935
+ next-schedules-buffer))))
936
+ (setq schedules (cdr schedules))))
937
+ (setq dayinfo-list (cdr dayinfo-list))))
938
+ (setq last-schedules-buffer (mhc-ps/uniq-list last-schedules-buffer)
939
+ last-holidays-buffer (mhc-ps/uniq-list last-holidays-buffer)
940
+ next-schedules-buffer (mhc-ps/uniq-list next-schedules-buffer)
941
+ next-holidays-buffer (mhc-ps/uniq-list next-holidays-buffer))
942
+ (setq schedules-buffer
943
+ (mapconcat 'identity (nreverse schedules-buffer) " ")
944
+ holidays-buffer
945
+ (mapconcat 'identity (nreverse holidays-buffer) " ")
946
+ last-schedules-buffer
947
+ (mapconcat 'identity (nreverse last-schedules-buffer) " ")
948
+ last-holidays-buffer
949
+ (mapconcat 'identity (nreverse last-holidays-buffer) " ")
950
+ next-schedules-buffer
951
+ (mapconcat 'identity (nreverse next-schedules-buffer) " ")
952
+ next-holidays-buffer
953
+ (mapconcat 'identity (nreverse next-holidays-buffer) " "))
954
+ (with-temp-buffer
955
+ (insert mhc-ps/string)
956
+ (let ((case-fold-search nil)
957
+ (alist mhc-ps/replace-table)
958
+ key value)
959
+ (while alist
960
+ (setq key (car (car alist))
961
+ value (eval (cdr (car alist)))
962
+ alist (cdr alist))
963
+ (goto-char (point-min))
964
+ (while (search-forward key nil t)
965
+ (delete-region (- (point) (length key)) (point))
966
+ (insert value))))
967
+ (and file
968
+ (mhc-write-region-as-coding-system
969
+ mhc-ps-coding-system (point-min) (point-max) (expand-file-name file)
970
+ nil 'nomsg))
971
+ (buffer-substring (point-min) (point-max)))))
972
+
973
+ (defvar mhc-ps/process-file-alist '())
974
+
975
+ (defun mhc-ps/process (command arguments file buffer year month
976
+ category-predicate)
977
+ (mhc-setup)
978
+ (message "PostScript creating...")
979
+ (let ((contents
980
+ (mhc-ps/make-contents file year month category-predicate)))
981
+ (if (null contents)
982
+ (message "No PostScript create.")
983
+ (cond
984
+ ((stringp command)
985
+ (let ((process
986
+ (apply (function start-process)
987
+ (format "mhc-ps-%s" command)
988
+ (mhc-get-buffer-create (format " *mhc-ps-%s*" command))
989
+ command (append arguments (list (expand-file-name file))))))
990
+ (set-process-coding-system
991
+ process mhc-ps-coding-system mhc-ps-coding-system)
992
+ (set-process-sentinel process 'mhc-ps/process-sentinel)
993
+ (setq mhc-ps/process-file-alist
994
+ (cons (cons process (expand-file-name file))
995
+ mhc-ps/process-file-alist))
996
+ (message "PostScript creating...done")))
997
+ ((eq command 'save)
998
+ (message "PostScript saving (%s)...done" file))
999
+ ((eq command 'buffer)
1000
+ (pop-to-buffer (get-buffer-create buffer))
1001
+ (kill-new contents)
1002
+ (let ((msg "Insert PostScript data ? (y or n) ")
1003
+ (char nil))
1004
+ (message msg)
1005
+ (while (null char)
1006
+ (setq char (read-char-exclusive))
1007
+ (if (or (eq ?y char) (eq ?\ char)
1008
+ (eq ?n char) (eq ?\177 char))
1009
+ ()
1010
+ (setq char nil)
1011
+ (message (concat "Please answer y or n. " msg))))
1012
+ (if (or (eq ?y char) (eq ?\ char))
1013
+ (save-excursion
1014
+ (insert contents)
1015
+ (message "PostScript insert to \"%s\"." buffer))
1016
+ (message "PostScript data to the latest kill in the kill ring."))))))))
1017
+
1018
+
1019
+ (defun mhc-ps/process-sentinel (process event)
1020
+ (let ((al (assoc process mhc-ps/process-file-alist)))
1021
+ (and (cdr al) (file-writable-p (cdr al)) (delete-file (cdr al)))
1022
+ (setq mhc-ps/process-file-alist
1023
+ (delete al mhc-ps/process-file-alist))))
1024
+
1025
+ ;;;###autoload
1026
+ (defun mhc-ps (&optional arg)
1027
+ "*Create PostScript calendar with selected method."
1028
+ (interactive "P")
1029
+ (let ((method 'preview)
1030
+ (date (or (mhc-current-date-month) (mhc-calendar-get-date)))
1031
+ year month char)
1032
+ (if (or arg (null date))
1033
+ (setq date (mhc-input-month "Month: " date)))
1034
+ (setq year (mhc-date-yy date))
1035
+ (setq month (mhc-date-mm date))
1036
+ (message "pre(V)iew (default), (P)rint, (S)ave, (I)nsert buffer")
1037
+ (condition-case nil
1038
+ (setq char (read-char))
1039
+ (error (setq char ?v)))
1040
+ (cond
1041
+ ((memq char '(?p ?P))
1042
+ (mhc-ps-print year month mhc-default-category-predicate-sexp))
1043
+ ((memq char '(?s ?S))
1044
+ (mhc-ps-save
1045
+ year month
1046
+ (expand-file-name
1047
+ (mhc-date-format date "mhc%04d%02d.ps" yy mm)
1048
+ mhc-ps-save-directory)
1049
+ mhc-default-category-predicate-sexp))
1050
+ ((memq char '(?i ?I))
1051
+ (mhc-ps-insert-buffer
1052
+ year month
1053
+ (read-buffer "Insert buffer: " "*mhc-postscript*")
1054
+ mhc-default-category-predicate-sexp))
1055
+ (t
1056
+ (mhc-ps-preview year month mhc-default-category-predicate-sexp)))))
1057
+
1058
+
1059
+ ;;;###autoload
1060
+ (defun mhc-ps-preview (year month &optional category-predicate)
1061
+ "*Preview PostScript calendar."
1062
+ (interactive
1063
+ (let* ((cdate (or (mhc-current-date-month) (mhc-calendar-get-date)))
1064
+ (date (mhc-input-month "Month: " cdate)))
1065
+ (list
1066
+ (mhc-date-yy date)
1067
+ (mhc-date-mm date)
1068
+ mhc-default-category-predicate-sexp)))
1069
+ (mhc-ps/process mhc-ps-preview-command mhc-ps-preview-command-arguments
1070
+ (expand-file-name
1071
+ (format "mhc%04d%02d.ps" year month)
1072
+ mhc-ps-save-directory)
1073
+ nil
1074
+ year month
1075
+ category-predicate))
1076
+
1077
+ ;;;###autoload
1078
+ (defun mhc-ps-print (year month &optional category-predicate)
1079
+ "*Print PostScript calendar."
1080
+ (interactive
1081
+ (let* ((cdate (or (mhc-current-date-month) (mhc-calendar-get-date)))
1082
+ (date (mhc-input-month "Month: " cdate)))
1083
+ (list
1084
+ (mhc-date-yy date)
1085
+ (mhc-date-mm date)
1086
+ mhc-default-category-predicate-sexp)))
1087
+ (mhc-ps/process mhc-ps-print-command mhc-ps-print-command-arguments
1088
+ (expand-file-name
1089
+ (format "mhc%04d%02d.ps" year month)
1090
+ mhc-ps-save-directory)
1091
+ nil
1092
+ year month
1093
+ category-predicate))
1094
+
1095
+ ;;;###autoload
1096
+ (defun mhc-ps-save (year month file &optional category-predicate)
1097
+ "*Save PostScript calendar."
1098
+ (interactive
1099
+ (let* ((cdate (or (mhc-current-date-month) (mhc-calendar-get-date)))
1100
+ (date (mhc-input-month "Month: " cdate))
1101
+ (default (expand-file-name
1102
+ (mhc-date-format date "mhc%04d%02d.ps" yy mm)
1103
+ mhc-ps-save-directory))
1104
+ (file (read-file-name "Save file: " default default)))
1105
+ (list
1106
+ (mhc-date-yy date)
1107
+ (mhc-date-mm date)
1108
+ file
1109
+ mhc-default-category-predicate-sexp)))
1110
+ (mhc-ps/process 'save nil
1111
+ file nil
1112
+ year month
1113
+ category-predicate))
1114
+
1115
+ ;;;###autoload
1116
+ (defun mhc-ps-insert-buffer (year month buffer &optional category-predicate)
1117
+ "*Insert PostScript calendar."
1118
+ (interactive
1119
+ (let* ((cdate (or (mhc-current-date-month) (mhc-calendar-get-date)))
1120
+ (date (mhc-input-month "Month: " cdate))
1121
+ (buffer (read-buffer "Insert buffer: " "*mhc-postscript*")))
1122
+ (list
1123
+ (mhc-date-yy date)
1124
+ (mhc-date-mm date)
1125
+ buffer
1126
+ mhc-default-category-predicate-sexp)))
1127
+ (mhc-ps/process 'buffer nil
1128
+ nil buffer
1129
+ year month
1130
+ category-predicate))
1131
+
1132
+
1133
+ (provide 'mhc-ps)
1134
+
1135
+
1136
+ ;;; Copyright Notice of the PostScript programs.
1137
+
1138
+ ;; Copyright (C) 1987 by Pipeline Associates, Inc.
1139
+ ;; Copyright (C) 2000 by SUZUKI Shingo <ichimal@takopen.cs.uec.ac.jp>.
1140
+
1141
+ ;; Permission is granted to modify and distribute this free of charge.
1142
+
1143
+
1144
+ ;;; Copyright Notice of the Emacs Lisp programs.
1145
+
1146
+ ;; Copyright (C) 2000 MHC developing team. All rights reserved.
1147
+
1148
+ ;; Redistribution and use in source and binary forms, with or without
1149
+ ;; modification, are permitted provided that the following conditions
1150
+ ;; are met:
1151
+ ;;
1152
+ ;; 1. Redistributions of source code must retain the above copyright
1153
+ ;; notice, this list of conditions and the following disclaimer.
1154
+ ;; 2. Redistributions in binary form must reproduce the above copyright
1155
+ ;; notice, this list of conditions and the following disclaimer in the
1156
+ ;; documentation and/or other materials provided with the distribution.
1157
+ ;; 3. Neither the name of the team nor the names of its contributors
1158
+ ;; may be used to endorse or promote products derived from this software
1159
+ ;; without specific prior written permission.
1160
+ ;;
1161
+ ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
1162
+ ;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1163
+ ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1164
+ ;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1165
+ ;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
1166
+ ;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1167
+ ;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1168
+ ;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1169
+ ;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1170
+ ;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1171
+ ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1172
+ ;; OF THE POSSIBILITY OF SUCH DAMAGE.
1173
+
1174
+ ;;; mhc-ps.el ends here.