~ubuntu-branches/ubuntu/karmic/mew-beta/karmic

« back to all changes in this revision

Viewing changes to mew-thread.el

  • Committer: Bazaar Package Importer
  • Author(s): Tatsuya Kinoshita
  • Date: 2008-04-24 00:28:17 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080424002817-68vgq5lfqr8z0795
Tags: 6.0.51~0.20080421-1
New upstream release. (CVS trunk on 2008-04-21)

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
              node list.
41
41
 
42
42
If you have bogus messages and the second pass is carried out, thread
43
 
structure MAY loop. This results in an infinite loop of visualizing 
44
 
threads (not making threads). 
 
43
structure MAY loop. This results in an infinite loop of visualizing
 
44
threads (not making threads).
45
45
 
46
46
Mew does not provide any loop detection/avoidance mechanism. So, you
47
47
should understand this risk."
52
52
  "*Vector of strings to be used for indentation of thread.
53
53
 
54
54
This consists of four members; 1st member for prefixing to a child
55
 
message that is not the last one, 2nd member is for prefixing to the 
56
 
last child, 3rd and 4th members are for prefixing to grand-child thread trees, 
 
55
message that is not the last one, 2nd member is for prefixing to the
 
56
last child, 3rd and 4th members are for prefixing to grand-child thread trees,
57
57
4th member is for the child tree of the last child message.
58
58
 
59
59
Example1: [\" +\" \" +\" \" |\" \"  \"] makes thread view below.
85
85
  "*If non-nil, the specified string is inserted between threads.")
86
86
(defvar mew-thread-separator "--")
87
87
 
88
 
(defsubst mew-thread-insert-separator ()
 
88
(defun mew-thread-insert-separator ()
89
89
  (if (and mew-use-thread-separator
90
90
           (/= (save-excursion (beginning-of-line) (point)) 1))
91
91
      (insert mew-thread-separator "\n")))
98
98
(defun mew-thread-make-entry ()
99
99
  (make-vector 5 nil))
100
100
 
101
 
(defsubst mew-thread-get-myid (entry)
 
101
(defun mew-thread-get-myid (entry)
102
102
  (aref entry 0))
103
103
 
104
 
(defsubst mew-thread-get-prntid (entry)
 
104
(defun mew-thread-get-prntid (entry)
105
105
  (aref entry 1))
106
106
 
107
 
(defsubst mew-thread-get-child (entry)
 
107
(defun mew-thread-get-child (entry)
108
108
  (aref entry 2))
109
109
 
110
 
(defsubst mew-thread-get-msg (entry)
 
110
(defun mew-thread-get-msg (entry)
111
111
  (aref entry 3))
112
112
 
113
 
(defsubst mew-thread-get-line (entry)
 
113
(defun mew-thread-get-line (entry)
114
114
  (aref entry 4))
115
115
 
116
 
(defsubst mew-thread-set-myid (entry myid)
 
116
(defun mew-thread-set-myid (entry myid)
117
117
  (aset entry 0 myid))
118
118
 
119
 
(defsubst mew-thread-set-prntid (entry prntid)
 
119
(defun mew-thread-set-prntid (entry prntid)
120
120
  (aset entry 1 prntid))
121
121
 
122
 
(defsubst mew-thread-set-child (entry child)
 
122
(defun mew-thread-set-child (entry child)
123
123
  (aset entry 2 child))
124
124
 
125
 
(defsubst mew-thread-set-msg (entry msg)
 
125
(defun mew-thread-set-msg (entry msg)
126
126
  (aset entry 3 msg))
127
127
 
128
 
(defsubst mew-thread-set-line (entry line)
 
128
(defun mew-thread-set-line (entry line)
129
129
  (aset entry 4 line))
130
130
 
131
131
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
151
151
 
152
152
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
153
153
;;;
154
 
;;; Making thread
 
154
;;; Commands
155
155
;;;
156
156
 
157
157
(defun mew-summary-mark-thread ()
159
159
  (interactive)
160
160
  (mew-summary-thread-region (point-min) (point-max) 'mark))
161
161
 
162
 
(defsubst mew-thread-cache-valid-p (vfolder)
 
162
(defun mew-thread-cache-valid-p (vfolder)
163
163
  (let ((cfolder (mew-summary-folder-name 'ext))
164
164
        ofld)
165
165
    (save-excursion
166
166
      (when (get-buffer vfolder)
167
167
        (set-buffer vfolder)
168
 
        (setq ofld (mew-vinfo-get-parent-folder))
 
168
        (setq ofld (mew-vinfo-get-original-folder))
169
169
        (and (equal ofld cfolder)
170
170
             (get-buffer ofld)
171
171
             (equal (mew-sinfo-get-cache-time)
172
172
                    (progn (set-buffer ofld) (mew-sinfo-get-cache-time))))))))
173
173
 
174
174
(defun mew-summary-make-thread (&optional arg)
175
 
  "If called in Summary mode or in Virtual mode made of a single
176
 
physical folder, this command makes threads for the Summary mode
177
 
as Virtual mode, then the cursor jump onto the current message in
178
 
the Virtual mode. If a corresponding Virtual mode exists, this
179
 
command just visits the Virtual mode.
180
 
 
181
 
If called with '\\[universal-argument]' in Summary mode, make
182
 
threads for messages in the region.
183
 
 
184
 
If called in Thread (Virtual) mode, switch back to the
185
 
corresponding Summary mode and move to the current message."
 
175
  "If called in Summary mode or Selection, make threads for
 
176
all messages.
 
177
 
 
178
If called with '\\[universal-argument]', make threads for
 
179
messages in the region.
 
180
 
 
181
If called in Thread, switch back to the corresponding Summary
 
182
mode or Selection."
186
183
  (interactive "P")
187
184
  (if (mew-mark-active-p) (setq arg t))
188
185
  (if arg
195
192
           (folder (mew-summary-folder-name 'ext)) ;; xxx
196
193
           fld vfolder)
197
194
      (cond
198
 
       ((mew-virtual-p)
199
 
        (cond
200
 
         ((mew-thread-p)
201
 
          (setq fld (mew-vinfo-get-parent-folder))
202
 
          (if (not (and fld (get-buffer fld)))
203
 
              (message "No original folder")
204
 
            (mew-summary-visit-folder fld nil 'no-ls)
205
 
            (mew-summary-toggle-disp-msg (if disp 'on 'off))
206
 
            (if (not msg)
207
 
                (goto-char (point-max))
208
 
              (mew-summary-move-and-display msg))))
209
 
         ((mew-pickable-p)
210
 
          (mew-summary-thread-region (point-min) (point-max) nil msg))
211
 
         (t
212
 
          (message "No physical folder"))))
 
195
       ((mew-thread-p)
 
196
        (setq fld (mew-vinfo-get-original-folder))
 
197
        (if (not (and fld (get-buffer fld)))
 
198
            (message "No original folder")
 
199
          (mew-summary-visit-folder fld nil 'no-ls)
 
200
          (mew-summary-toggle-disp-msg (if disp 'on 'off))
 
201
          (if (not msg)
 
202
              (goto-char (point-max))
 
203
            (mew-summary-move-and-display msg))))
213
204
       ((and (setq vfolder (mew-folder-to-thread folder))
214
205
             (mew-thread-cache-valid-p vfolder))
215
206
        (mew-summary-visit-folder vfolder)
217
208
        (when msg
218
209
          (mew-summary-move-and-display msg)
219
210
          (mew-thread-move-cursor)))
 
211
       ((mew-selection-p)
 
212
        (mew-summary-thread-region (point-min) (point-max) nil msg))
220
213
       (t
221
214
        (mew-summary-thread-region (point-min) (point-max) nil msg))))))
222
215
 
232
225
      (setq iter (lambda () (mew-summary-search-regexp-visible regex))))
233
226
    (mew-summary-thread-region (point-min) (point-max) nil nil iter)))
234
227
 
 
228
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
229
;;;
 
230
;;; Making thread
 
231
;;;
 
232
 
 
233
(defun mew-thread-get-iter (mark iter)
 
234
  (cond
 
235
   (iter iter)
 
236
   (mark (lambda () (re-search-forward mew-regex-msg-review nil t)))
 
237
   (t    (lambda () (not (eobp))))))
 
238
 
 
239
(defun mew-thread-create-db (size)
 
240
  (let ((dbsize
 
241
         (cond
 
242
          ((<= size 211) 211)
 
243
          ((<= size 1511) 1511)
 
244
          ((<= size 7211) 7211)
 
245
          (t 18211))))
 
246
    (make-vector dbsize 0))) ;; hash
 
247
 
 
248
(defun mew-thread-pass-1 (db func)
 
249
  (let (start msg my-id prnt-id prnt-cld me top line prnt)
 
250
    (save-excursion
 
251
      (goto-char (point-min))
 
252
      (while (funcall func)
 
253
        (beginning-of-line)
 
254
        (setq start (point))
 
255
        (if (not (mew-sumsyn-match mew-regex-sumsyn-long))
 
256
            (forward-line)
 
257
          (setq msg     (mew-sumsyn-message-number))
 
258
          (setq my-id   (mew-sumsyn-my-id))
 
259
          (setq prnt-id (mew-sumsyn-parent-id))
 
260
          (forward-line)
 
261
          ;; Throw away properties here and give properties later.
 
262
          ;; This is faster than inheriting properties.
 
263
          (setq line (mew-buffer-substring start (point)))
 
264
          (setq me (mew-thread-make-entry))
 
265
          (mew-thread-set-msg me msg)
 
266
          (mew-thread-set-line me line)
 
267
          (if (string= my-id "")
 
268
              (setq top (cons me top))
 
269
            ;; some broken messages refer themselves
 
270
            ;; don't register me here so that his parent
 
271
            ;; will not be found.
 
272
            (if (or (string= prnt-id "") (string= my-id prnt-id))
 
273
                (setq top (cons me top))
 
274
              (mew-thread-set-prntid me prnt-id)
 
275
              (setq prnt (symbol-value (intern-soft prnt-id db)))
 
276
              (if (null prnt)
 
277
                  (setq top (cons me top))
 
278
                (setq prnt-cld (mew-thread-get-child prnt))
 
279
                (if prnt-cld
 
280
                    (nconc prnt-cld (list me))
 
281
                  (mew-thread-set-child prnt (list me)))))
 
282
            (mew-thread-set-myid me my-id)
 
283
            (set (intern my-id db) me)))))
 
284
    top))
 
285
 
 
286
(defun mew-summary-setup-vfolder (db top column)
 
287
  (let* ((ofolder (mew-summary-folder-name 'ext))
 
288
         (vfolder (mew-folder-to-thread ofolder))
 
289
         (pfolder (mew-summary-physical-folder))
 
290
         (disp (mew-sinfo-get-disp-msg))
 
291
         (ctime (mew-sinfo-get-cache-time))
 
292
         (case (mew-sinfo-get-case)))
 
293
    (mew-summary-switch-to-folder vfolder)
 
294
    (mew-vinfo-set-mode 'thread)
 
295
    (mew-vinfo-set-physical-folder pfolder)
 
296
    (mew-vinfo-set-original-folder ofolder)
 
297
    (mew-erase-buffer)
 
298
    (mew-hscroll)
 
299
    (mew-summary-toggle-disp-msg (if disp 'on 'off))
 
300
    (mew-sinfo-set-cache-time ctime)
 
301
    (mew-sinfo-set-case case)
 
302
    (setq mew-summary-buffer-raw t)
 
303
    (mew-vinfo-set-db db)
 
304
    (mew-vinfo-set-top top)
 
305
    (mew-vinfo-set-column column)))
 
306
 
 
307
(defun mew-thread-pass-2 (db top)
 
308
  (if (null mew-use-complete-thread)
 
309
      (nreverse top)
 
310
    ;; This may create looped thread.
 
311
    ;; See mew-use-complete-thread for more information.
 
312
    (let (prnt prnt-id prnt-cld ret)
 
313
      (dolist (me top)
 
314
        (if (not (and (mew-thread-get-myid me)
 
315
                      (setq prnt-id (mew-thread-get-prntid me))))
 
316
            (setq ret (cons me ret))
 
317
          (setq prnt (symbol-value (intern-soft prnt-id db)))
 
318
          (if (null prnt)
 
319
              (setq ret (cons me ret))
 
320
            (setq prnt-cld (mew-thread-get-child prnt))
 
321
            (if prnt-cld
 
322
                (setq prnt-cld (nconc prnt-cld (list me)))
 
323
              (mew-thread-set-child prnt (list me))))))
 
324
      ret)))
 
325
 
 
326
(defun mew-thread-postscript (mark disp-msg)
 
327
  (when mark (mew-mark-undo-mark mew-mark-review))
 
328
  (jit-lock-register 'mew-summary-cook-region)
 
329
  (mew-summary-set-count-line)
 
330
  (set-buffer-modified-p nil)
 
331
  (if disp-msg
 
332
      (mew-summary-move-and-display disp-msg)
 
333
    (goto-char (point-max)))
 
334
  (mew-thread-move-cursor))
 
335
 
 
336
(defun mew-thread-debug-info (tm1 tm2 tm3 tm4 tm5 tm6)
 
337
  (when (mew-debug 'thread)
 
338
    (let* ((t1 (mew-time-calc tm2 tm1))
 
339
           (t2 (mew-time-calc tm4 tm3))
 
340
           (t3 (mew-time-calc tm6 tm5)))
 
341
      (message "pass1 %f, pass2 %f, visual %f" t1 t2 t3))))
 
342
 
235
343
(defun mew-summary-thread-region (beg end &optional mark disp-msg iter)
236
344
  "Make threads for messages in a region.  If you want to know how
237
345
threads are created, see 'mew-use-complete-thread'."
238
346
  (interactive "r")
239
 
  (mew-pickable
240
 
   (when (mew-summary-exclusive-p)
241
 
     (let* ((ofolder (mew-summary-folder-name 'ext))
242
 
            (vfolder (mew-folder-to-thread (mew-physical-folder ofolder)))
243
 
            (folder (mew-summary-physical-folder))
244
 
            (disp (mew-sinfo-get-disp-msg))
245
 
            (ctime (mew-sinfo-get-cache-time))
246
 
            (case (mew-sinfo-get-case))
247
 
            (column (mew-get-summary-form folder 'column))
248
 
            db size top start me prnt prnt-cld my-id prnt-id func msg line
249
 
            tm1 tm2 tm3 tm4 tm5 tm6)
250
 
       (message "Making thread (first pass)...")
251
 
       (save-restriction
252
 
         (narrow-to-region beg end)
253
 
         (setq size (count-lines beg end))
254
 
         (cond
255
 
          ((<= size 211)
256
 
           (setq size 211))
257
 
          ((<= size 1511)
258
 
           (setq size 1511))
259
 
          ((<= size 7211)
260
 
           (setq size 7211))
261
 
          (t
262
 
           (setq size 18211)))
263
 
         (setq db (make-vector size 0)) ;; hash
264
 
         (save-excursion
265
 
           (goto-char (point-min))
266
 
           (if mark
267
 
               (setq func (lambda ()
268
 
                            (re-search-forward mew-regex-msg-review nil t)))
269
 
             (setq func (lambda () (not (eobp)))))
270
 
           (if iter
271
 
               (setq func iter))
272
 
           (setq tm1 (current-time))
273
 
           (while (funcall func)
274
 
             (beginning-of-line)
275
 
             (setq start (point))
276
 
             (if (not (mew-sumsyn-match mew-regex-sumsyn-long))
277
 
                 (forward-line)
278
 
               (setq msg     (mew-sumsyn-message-number))
279
 
               (setq my-id   (mew-sumsyn-my-id))
280
 
               (setq prnt-id (mew-sumsyn-parent-id))
281
 
               (forward-line)
282
 
               ;; Throw away properties here and give properties later.
283
 
               ;; This is faster than inheriting properties.
284
 
               (setq line (mew-buffer-substring start (point)))
285
 
               (setq me (mew-thread-make-entry))
286
 
               (mew-thread-set-msg me msg)
287
 
               (mew-thread-set-line me line)
288
 
               (if (string= my-id "")
289
 
                   (setq top (cons me top))
290
 
                 ;; some broken messages refer themselves
291
 
                 ;; don't register me here so that his parent
292
 
                 ;; will not be found.
293
 
                 (if (or (string= prnt-id "") (string= my-id prnt-id))
294
 
                     (setq top (cons me top))
295
 
                   (mew-thread-set-prntid me prnt-id)
296
 
                   (setq prnt (symbol-value (intern-soft prnt-id db)))
297
 
                   (if (null prnt)
298
 
                       (setq top (cons me top))
299
 
                     (setq prnt-cld (mew-thread-get-child prnt))
300
 
                     (if prnt-cld
301
 
                         (nconc prnt-cld (list me))
302
 
                       (mew-thread-set-child prnt (list me)))))
303
 
                 (mew-thread-set-myid me my-id)
304
 
                 (set (intern my-id db) me))))))
305
 
       ;;
306
 
       (if (null me)
307
 
           (message "No target messages")
308
 
         (setq tm2 (current-time))
309
 
         (mew-summary-switch-to-folder vfolder ofolder)
310
 
         (mew-erase-buffer)
311
 
         (mew-hscroll)
312
 
         (mew-summary-toggle-disp-msg (if disp 'on 'off))
313
 
         (mew-sinfo-set-cache-time ctime)
314
 
         (mew-sinfo-set-case case)
315
 
         (setq mew-summary-buffer-raw t)
316
 
         (mew-vinfo-set-top nil)
317
 
         (mew-vinfo-set-db db)
318
 
         (mew-vinfo-set-column column)
319
 
         ;;
320
 
         (message "Making thread (second pass)...")
321
 
         (setq tm3 (current-time))
322
 
         (if (null mew-use-complete-thread)
323
 
             (mew-vinfo-set-top (nreverse top))
324
 
           ;; This may create looped thread.
325
 
           ;; See mew-use-complete-thread for more information.
326
 
           (while top
327
 
             (setq me (car top))
328
 
             (if (not (and (mew-thread-get-myid me)
329
 
                           (setq prnt-id (mew-thread-get-prntid me))))
330
 
                 (mew-vinfo-set-top (cons me (mew-vinfo-get-top)))
331
 
               (setq prnt (symbol-value (intern-soft prnt-id db)))
332
 
               (if (null prnt)
333
 
                   (mew-vinfo-set-top (cons me (mew-vinfo-get-top)))
334
 
                 (setq prnt-cld (mew-thread-get-child prnt))
335
 
                 (if prnt-cld
336
 
                     (nconc prnt-cld (list me))
337
 
                   (mew-thread-set-child prnt (list me)))))
338
 
             (setq top (cdr top))))
339
 
         ;;
340
 
         (setq tm4 (current-time))
341
 
         (message "Displaying thread...")
342
 
         (setq tm5 (current-time))
343
 
         (mew-summary-thread-print-top
344
 
          (mew-vinfo-get-top) folder column)
345
 
         ;;
346
 
         ;; Unmarking in both Summary and Thread
347
 
         (when mark (mew-mark-undo-mark mew-mark-review))
348
 
         (setq tm6 (current-time))
349
 
         (when mew-gemacs-p
350
 
           (jit-lock-register 'mew-summary-cook-region))
351
 
         (mew-summary-set-count-line)
352
 
         (set-buffer-modified-p nil)
353
 
         (if disp-msg
354
 
             (mew-summary-move-and-display disp-msg)
355
 
           (goto-char (point-max)))
356
 
         (mew-thread-move-cursor)
357
 
         (message "Displaying thread...done")
358
 
         (run-hooks 'mew-thread-display-hook)
359
 
         (when (mew-debug 'thread)
360
 
           (let* ((t1 (mew-time-calc tm2 tm1))
361
 
                  (t2 (mew-time-calc tm4 tm3))
362
 
                  (t3 (mew-time-calc tm6 tm5)))
363
 
             (message "pass1 %f, pass2 %f, visual %f" t1 t2 t3))))))))
 
347
  (when (mew-summary-exclusive-p)
 
348
    (let* ((column (or (mew-sinfo-get-summary-column) ;; scanned
 
349
                       ;; Summary only
 
350
                       (mew-get-summary-column (mew-summary-folder-name 'ext))))
 
351
           db top tm1 tm2 tm3 tm4 tm5 tm6)
 
352
      (save-restriction
 
353
        (narrow-to-region beg end)
 
354
        (setq db (mew-thread-create-db (count-lines beg end)))
 
355
        ;;
 
356
        (message "Making thread (first pass)...")
 
357
        (setq tm1 (current-time))
 
358
        (setq top (mew-thread-pass-1 db (mew-thread-get-iter mark iter)))
 
359
        (setq tm2 (current-time)))
 
360
      ;;
 
361
      (if (null top)
 
362
          (message "No target messages")
 
363
        (message "Making thread (second pass)...")
 
364
        (setq tm3 (current-time))
 
365
        (setq top (mew-thread-pass-2 db top))
 
366
        (setq tm4 (current-time))
 
367
        ;;
 
368
        (mew-summary-setup-vfolder db top column)
 
369
        ;;
 
370
        (message "Displaying thread...")
 
371
        (setq tm5 (current-time))
 
372
        (mew-summary-thread-print-top (mew-vinfo-get-top) column)
 
373
        (setq tm6 (current-time))
 
374
        ;;
 
375
        (mew-thread-postscript mark disp-msg)   
 
376
        ;;
 
377
        (message "Displaying thread...done")
 
378
        (run-hooks 'mew-thread-display-hook)
 
379
        (mew-thread-debug-info tm1 tm2 tm3 tm4 tm5 tm6)))))
364
380
 
365
381
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
366
382
;;;
400
416
;;; Visualizing thread
401
417
;;;
402
418
 
403
 
(defun mew-summary-thread-print-top (top folder column)
404
 
  (while top
405
 
    (let* ((me (car top))
406
 
           (cld (mew-thread-get-child me)))
 
419
(defun mew-summary-thread-print-top (top column)
 
420
  (let (cld)
 
421
    (dolist (me top)
 
422
      (setq cld (mew-thread-get-child me))
407
423
      (mew-elet
408
424
       (mew-thread-insert-separator)
409
425
       (insert (mew-thread-get-line me))
411
427
       (move-to-column column)
412
428
       (mew-thread-put-property (point) (1+ (point)) 0)
413
429
       (forward-line))
414
 
      (if cld (mew-summary-thread-print-tree cld folder column))
415
 
      (setq top (cdr top)))))
 
430
      (if cld (mew-summary-thread-print-tree cld column)))))
416
431
 
417
 
(defun mew-summary-thread-print-tree (tree folder column)
 
432
(defun mew-summary-thread-print-tree (tree column)
418
433
  (let ((tree-stack nil)
419
434
        (prefix "")
420
435
        (level 1) pos)
482
497
  "Put the 'o' mark on all messages of the current sub-thread."
483
498
  (interactive)
484
499
  (mew-thread-only
485
 
   (let* ((fld (mew-physical-folder (mew-summary-folder-name 'ext)))
486
 
          ;; mew-vinfo-get-parent-folder cannot be used here
 
500
   (let* ((fld (mew-folder-basename (mew-summary-folder-name 'ext)))
487
501
          (folders (mew-summary-refile-body nil nil nil 'no-mark))
488
502
          (folders-str (mew-join "," folders))
489
503
          (func (lambda ()
510
524
       (mew-refile-set-from-alist alist folders)))))
511
525
 
512
526
(defun mew-refile-set-from-alist (alist folders)
513
 
  (let (ent fld msg msgs)
514
 
    (while alist
515
 
      (setq ent (car alist))
516
 
      (setq alist (cdr alist))
 
527
  (let (fld)
 
528
    (dolist (ent alist)
517
529
      (setq fld (car ent))
518
 
      (setq msgs (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect
519
 
      (while msgs
520
 
        (setq msg (number-to-string (car msgs)))
521
 
        (setq msgs (cdr msgs))
 
530
      (dolist (msg (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect
 
531
        (setq msg (number-to-string msg))
522
532
        (when (get-buffer fld)
523
533
          (save-excursion
524
534
            (set-buffer fld)
619
629
        (mew-thread-unmark-physical-from-alist alist))))))
620
630
 
621
631
(defun mew-thread-unmark-physical-from-alist (alist)
622
 
  (let (ent fld msg msgs)
623
 
    (while alist
624
 
      (setq ent (car alist))
625
 
      (setq alist (cdr alist))
 
632
  (let (fld msgs)
 
633
    (dolist (ent alist)
626
634
      (setq fld (car ent))
627
635
      (setq msgs (sort (copy-sequence (cdr ent)) '<)) ;; sort has side effect
628
636
      (when (get-buffer fld)
629
637
        (set-buffer fld)
630
638
        (save-excursion
631
639
          (goto-char (point-min))
632
 
          (while msgs
633
 
            (setq msg (number-to-string (car msgs)))
634
 
            (setq msgs (cdr msgs))
 
640
          (dolist (msg msgs)
 
641
            (setq msg (number-to-string msg))
635
642
            (when (re-search-forward (mew-regex-sumsyn-msg msg) nil t)
636
643
              (mew-thread-undo fld msg)
637
644
              (mew-mark-unmark))))))))
680
687
       (mew-thread-move-cursor)
681
688
       (mew-summary-display)))))
682
689
 
683
 
(defun mew-summary-thread-parent ()
 
690
(defun mew-summary-parent ()
684
691
  "Move onto the parent message of the current message."
685
692
  (interactive)
686
693
  (mew-summary-goto-message)
687
694
  (mew-decode-syntax-delete)
 
695
  (let ((par-id (mew-summary-parent-id)) result)
 
696
    (cond
 
697
     ((or (null par-id) (string= par-id ""))
 
698
      (message "No parent"))
 
699
     ((mew-summary-parent-local par-id)
 
700
      (message "Parent found"))
 
701
     ((and (y-or-n-p "No parent in this folder. Find in others? ")
 
702
           (setq result (mew-summary-parent-global par-id)))
 
703
      (if (eq result t)
 
704
          (message "Parent found")
 
705
        (message "%s" result)))
 
706
     (t
 
707
      (message "Parent not found")))))
 
708
 
 
709
(defun mew-summary-parent-local (par-id)
688
710
  (let ((pos (point))
689
 
        (par-id (mew-summary-parent-id))
690
 
        key)
691
 
    (if (or (null par-id) (string= par-id ""))
692
 
        (message "No required info")
693
 
      (setq key (mew-regex-sumsyn-my-id par-id))
694
 
      (if (or (re-search-backward key nil t)
695
 
              (progn
696
 
                (goto-char (point-max))
697
 
                (re-search-backward key nil t)))
698
 
          (progn
699
 
            (mew-thread-move-cursor)
700
 
            (mew-summary-display)
701
 
            (message "Parent found"))
702
 
        (goto-char pos)
703
 
        (message "No parent")))))
 
711
        (key (mew-regex-sumsyn-my-id par-id)))
 
712
    (if (or (re-search-backward key nil t)
 
713
            (re-search-forward  key nil t))
 
714
        (progn
 
715
          (mew-thread-move-cursor)
 
716
          (mew-summary-display)
 
717
          t)
 
718
      (goto-char pos)
 
719
      nil)))
 
720
 
 
721
(defun mew-summary-parent-global (par-id)
 
722
  (mew-msgid-check
 
723
   (let ((db (mew-expand-file "+" mew-id-db-file))
 
724
         (regex (format "\\(.*\\)/\\([0-9]+\\)\\(%s\\)?$" (regexp-quote mew-suffix)))
 
725
         path msg folder)
 
726
     (with-temp-buffer
 
727
       (mew-piolet mew-cs-text-for-read mew-cs-text-for-write
 
728
         (call-process mew-prog-smew nil t nil "-p" db par-id "")
 
729
         (goto-char (point-min))
 
730
         (when (looking-at regex)
 
731
           (setq path (mew-match-string 1))
 
732
           (setq msg (mew-match-string 2)))))
 
733
     (if (not msg)
 
734
         nil
 
735
       (setq folder (mew-folder-path-to-folder path))
 
736
       (when folder
 
737
         (mew-summary-visit-folder folder nil 'no-ls)
 
738
         (if (mew-summary-search-msg msg)
 
739
             (progn
 
740
               (mew-summary-display)
 
741
               t)
 
742
           "Parent not found. Scan 'update would be necessary"))))))
704
743
 
705
744
(defun mew-summary-thread-child ()
706
 
  "Move onto the child message of the current message."
 
745
  "Move onto the first child message of the current message."
707
746
  (interactive)
708
747
  (mew-summary-goto-message)
709
748
  (mew-decode-syntax-delete)
711
750
        (my-id (mew-summary-my-id))
712
751
        key)
713
752
    (if (or (null my-id) (string= my-id ""))
714
 
        (message "No required info")
 
753
        (message "No child")
715
754
      (setq key (mew-regex-sumsyn-par-id my-id))
716
 
      (if (or (re-search-forward key nil t)
717
 
              (progn
718
 
                (goto-char (point-min))
719
 
                (re-search-forward key nil t)))
 
755
      (if (or (re-search-forward  key nil t)
 
756
              (re-search-backward key nil t))
720
757
          (progn
721
758
            (mew-thread-move-cursor)
722
759
            (mew-summary-display)
723
760
            (message "Child found"))
724
761
        (goto-char pos)
725
 
        (message "No child")))))
 
762
        (message "Child not found")))))
726
763
 
727
764
(defun mew-summary-thread-sibling-up ()
728
765
  "Search backward by one sibling message of the current message."
729
766
  (interactive)
730
 
  (let ((pos (point)) 
 
767
  (let ((pos (point))
731
768
        (par-id (mew-summary-parent-id))
732
769
        key)
733
770
    (if (or (null par-id) (string= par-id ""))
734
 
        (message "No required info")
 
771
        (message "No sibling")
735
772
      (setq key (mew-regex-sumsyn-par-id par-id))
736
773
      (if (re-search-backward key nil t)
737
774
          (progn
739
776
            (mew-summary-display)
740
777
            (message "Sibling found"))
741
778
        (goto-char pos)
742
 
        (message "No sibling")))))
 
779
        (message "Sibling not found")))))
743
780
 
744
781
(defun mew-summary-thread-sibling-down ()
745
782
  "Search forward by one sibling message of the current message."
748
785
        (par-id (mew-summary-parent-id))
749
786
        key)
750
787
    (if (or (null par-id) (string= par-id ""))
751
 
        (message "No required info")
 
788
        (message "No sibling")
752
789
      (setq key (mew-regex-sumsyn-par-id par-id))
753
790
      (forward-line)
754
791
      (if (re-search-forward key nil t)
757
794
            (mew-summary-display)
758
795
            (message "Sibling found"))
759
796
        (goto-char pos)
760
 
        (message "No sibling")))))
 
797
        (message "Sibling not found")))))
761
798
 
762
799
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
763
800
;;;
809
846
 
810
847
(defun mew-thread-toggle ()
811
848
  "If children of a message are displayed, they will hide and
812
 
\"+\" is displayed on the parent. 
 
849
\"+\" is displayed on the parent.
813
850
If the children are hidden, they will appear."
814
851
  (interactive)
815
852
  (mew-thread-only
948
985
  (save-excursion
949
986
    (mew-summary-goto-message)
950
987
    (beginning-of-line)
951
 
    ;; parent    
 
988
    ;; parent
952
989
    (let ((id (mew-summary-my-id))
953
990
          fld msg)
954
991
      (goto-char (mark-marker));; user's mark
1079
1116
 
1080
1117
;;; Copyright Notice:
1081
1118
 
1082
 
;; Copyright (C) 2000-2007 Mew developing team.
 
1119
;; Copyright (C) 2000-2008 Mew developing team.
1083
1120
;; All rights reserved.
1084
1121
 
1085
1122
;; Redistribution and use in source and binary forms, with or without
1086
1123
;; modification, are permitted provided that the following conditions
1087
1124
;; are met:
1088
 
;; 
 
1125
;;
1089
1126
;; 1. Redistributions of source code must retain the above copyright
1090
1127
;;    notice, this list of conditions and the following disclaimer.
1091
1128
;; 2. Redistributions in binary form must reproduce the above copyright
1094
1131
;; 3. Neither the name of the team nor the names of its contributors
1095
1132
;;    may be used to endorse or promote products derived from this software
1096
1133
;;    without specific prior written permission.
1097
 
;; 
 
1134
;;
1098
1135
;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
1099
1136
;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1100
1137
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR