diff lisp/gnus/gnus-picon.el @ 151:59463afc5666 r20-3b2

Import from CVS: tag r20-3b2
author cvs
date Mon, 13 Aug 2007 09:37:19 +0200
parents 1856695b1fa9
children 43dd3413c7c7
line wrap: on
line diff
--- a/lisp/gnus/gnus-picon.el	Mon Aug 13 09:36:20 2007 +0200
+++ b/lisp/gnus/gnus-picon.el	Mon Aug 13 09:37:19 2007 +0200
@@ -23,9 +23,6 @@
 
 ;;; Commentary:
 
-;;; TODO:
-;; See the comment in gnus-picons-remove
-
 ;;; Code:
 
 (require 'gnus)
@@ -45,17 +42,18 @@
 also add gnus-article-display-picons to gnus-article-display-hook."
   :group 'gnus-visual)
 
-(defcustom gnus-picons-buffer "*Icon Buffer*"
-  "Buffer name to display the icons in if gnus-picons-display-where is 'picons."
-  :type 'string
-  :group 'picons)
-
 (defcustom gnus-picons-display-where 'picons
   "Where to display the group and article icons.
 Legal values are `article' and `picons'."
   :type '(choice symbol string)
   :group 'picons)
 
+(defcustom gnus-picons-has-modeline-p t
+  "Wether the picons window should have a modeline.
+This is only useful if `gnus-picons-display-where' is `picons'."
+  :type 'boolean
+  :group 'picons)
+
 (defcustom gnus-picons-database "/usr/local/faces"
   "Defines the location of the faces database.
 For information on obtaining this database of pretty pictures, please
@@ -63,10 +61,12 @@
   :type 'directory
   :group 'picons)
 
-(defcustom gnus-picons-news-directory "news"
+(defcustom gnus-picons-news-directories '("news")
   "Sub-directory of the faces database containing the icons for newsgroups."
-  :type 'string
+  :type '(repeat string)
   :group 'picons)
+(define-obsolete-variable-alias 'gnus-picons-news-directory
+  'gnus-picons-news-directories)
 
 (defcustom gnus-picons-user-directories '("local" "users" "usenix" "misc")
   "List of directories to search for user faces."
@@ -152,14 +152,11 @@
 
 (defvar gnus-group-annotations nil
   "List of annotations added/removed when selecting/exiting a group")
-(defvar gnus-group-annotations-lock nil)
 (defvar gnus-article-annotations nil
   "List of annotations added/removed when selecting an article")
-(defvar gnus-article-annotations-lock nil)
 (defvar gnus-x-face-annotations nil
   "List of annotations added/removed when selecting an article with an
 X-Face.")
-(defvar gnus-x-face-annotations-lock nil)
 
 (defvar gnus-picons-jobs-alist nil
   "List of jobs that still need be done.
@@ -173,37 +170,27 @@
 
 ;;; Functions:
 
-(defsubst gnus-picons-lock (symbol)
-  (intern (concat (symbol-name symbol) "-lock")))
-
 (defun gnus-picons-remove (symbol)
   "Remove all annotations in variable named SYMBOL.
 This function is careful to set it to nil before removing anything so that
 asynchronous process don't get crazy."
-  ;; clear the lock
-  (set (gnus-picons-lock symbol) nil)
+  (setq gnus-picons-jobs-alist (remassq symbol gnus-picons-jobs-alist))
+  ;; notify running job that it may have been preempted
+  (if (eq (car gnus-picons-job-already-running) symbol)
+      (setq gnus-picons-job-already-running t))
   ;; clear all annotations
   (mapc (function (lambda (item)
 		    (if (annotationp item)
 			(delete-annotation item))))
 	(prog1 (symbol-value symbol)
-	  (set symbol nil)))
-  ;; FIXME: there's a race condition here.  If a job is already
-  ;; running, it has already removed itself from this queue...  But
-  ;; will still display its picon.
-  ;; TODO: push a request to clear an annotation.  Then
-  ;; gnus-picons-next-job will be able to clean up when it gets the
-  ;; hand
-  (setq gnus-picons-jobs-alist (remassq symbol gnus-picons-jobs-alist)))
+	  (set symbol nil))))
 
 (defun gnus-picons-remove-all ()
   "Removes all picons from the Gnus display(s)."
   (interactive)
   (gnus-picons-remove 'gnus-article-annotations)
   (gnus-picons-remove 'gnus-group-annotations)
-  (gnus-picons-remove 'gnus-x-face-annotations)
-  (when (bufferp gnus-picons-buffer)
-    (kill-buffer gnus-picons-buffer)))
+  (gnus-picons-remove 'gnus-x-face-annotations))
 
 (defun gnus-get-buffer-name (variable)
   "Returns the buffer name associated with the contents of a variable."
@@ -214,6 +201,22 @@
 				    ((stringp newvar) newvar))))
         ((stringp variable) variable)))
 
+(defun gnus-picons-set-buffer ()
+  (set-buffer
+   (get-buffer-create (gnus-get-buffer-name gnus-picons-display-where)))
+  (gnus-add-current-to-buffer-list)
+  (goto-char (point-min))
+  (if (and (eq gnus-picons-display-where 'article)
+	   gnus-picons-display-article-move-p)
+      (if (search-forward "\n\n" nil t)
+	  (forward-line -1)
+	(goto-char (point-max)))
+    (setq buffer-read-only t)
+    (unless gnus-picons-has-modeline-p
+      (set-specifier has-modeline-p
+		     (list (list (current-buffer)
+				 (cons nil gnus-picons-has-modeline-p)))))))
+
 (defun gnus-picons-prepare-for-annotations (annotations)
   "Prepare picons buffer for puting annotations memorized in ANNOTATIONS.
 ANNOTATIONS should be a symbol naming a variable wich contains a list of
@@ -221,19 +224,14 @@
   ;; let drawing catch up
   (when gnus-picons-refresh-before-display
     (sit-for 0))
-  (set-buffer (get-buffer-create
-	       (gnus-get-buffer-name gnus-picons-display-where)))
-  (gnus-add-current-to-buffer-list)
-  (goto-char (point-min))
-  (if (and (eq gnus-picons-display-where 'article)
-	   gnus-picons-display-article-move-p)
-      (when (search-forward "\n\n" nil t)
-	(forward-line -1))
-    (make-local-variable 'inhibit-read-only)
-    (setq buffer-read-only t
-	  inhibit-read-only nil))
+  (gnus-picons-set-buffer)
   (gnus-picons-remove annotations))
 
+(defsubst gnus-picons-make-annotation (&rest args)
+  (let ((annot (apply 'make-annotation args)))
+    (set-extent-property annot 'duplicable nil)
+    annot))
+
 (defun gnus-picons-article-display-x-face ()
   "Display the x-face header bitmap in the 'gnus-picons-display-where buffer."
   ;; delete any old ones.
@@ -265,7 +263,7 @@
 	(save-excursion
 	  (gnus-picons-prepare-for-annotations 'gnus-x-face-annotations)
 	  (setq gnus-x-face-annotations
-		(cons (make-annotation
+		(cons (gnus-picons-make-annotation
 		       (vector 'xface
 			       :data (concat "X-Face: "
 					     (buffer-substring beg end buf)))
@@ -276,7 +274,7 @@
 	   (annot (save-excursion
 		    (gnus-picons-prepare-for-annotations
 		     'gnus-x-face-annotations)
-		    (make-annotation nil nil 'text)))
+		    (gnus-picons-make-annotation nil nil 'text)))
 	   (process (start-process-shell-command "gnus-x-face" nil 
 						 gnus-picons-convert-x-face)))
       (push annot gnus-x-face-annotations)
@@ -306,18 +304,23 @@
 		       (message-tokenize-header (substring from (1+ at-idx))
 						"."))))
 	  (gnus-picons-prepare-for-annotations 'gnus-article-annotations)
+	  ;; if display in article buffer, the group annotations
+	  ;; wrongly placed.  Move them here
+	  (if (eq gnus-picons-display-where 'article)
+	      (dolist (ext gnus-group-annotations)
+		(set-extent-endpoints ext (point) (point))))
 	  (if (null gnus-picons-piconsearch-url)
 	      (setq gnus-article-annotations
 		    (nconc gnus-article-annotations
 			   (gnus-picons-display-pairs
 			    (gnus-picons-lookup-pairs
 			     addrs gnus-picons-domain-directories)
-			    (not (or gnus-picons-display-as-address
-				     gnus-article-annotations))
+			    gnus-picons-display-as-address
 			    "." t)
 			   (if (and gnus-picons-display-as-address addrs)
-			       (list (make-annotation [string :data "@"] nil
-						      'text nil nil nil t)))
+			       (list (gnus-picons-make-annotation
+				      [string :data "@"] nil
+				      'text nil nil nil t)))
 			   (gnus-picons-display-picon-or-name
 			    (gnus-picons-lookup-user username addrs)
 			    username t)))
@@ -340,13 +343,13 @@
 		(gnus-picons-display-pairs
 		 (gnus-picons-lookup-pairs (reverse (message-tokenize-header
 						     gnus-newsgroup-name "."))
-					   gnus-picons-news-directory)
+					   gnus-picons-news-directories)
 		 t "."))
 	(push (list 'gnus-group-annotations 'search nil
 		    (message-tokenize-header gnus-newsgroup-name ".")
-		    (if (listp gnus-picons-news-directory)
-			gnus-picons-news-directory
-		      (list gnus-picons-news-directory))
+		    (if (listp gnus-picons-news-directories)
+			gnus-picons-news-directories
+		      (list gnus-picons-news-directories))
 		    nil)
 	      gnus-picons-jobs-alist)
 	(gnus-picons-next-job))
@@ -404,40 +407,36 @@
 
 (defun gnus-picons-display-picon-or-name (picon name &optional right-p)
   (cond (picon (gnus-picons-display-glyph picon name right-p))
-	(gnus-picons-display-as-address (list (make-annotation
+	(gnus-picons-display-as-address (list (gnus-picons-make-annotation
 					       (vector 'string :data name)
 					       nil 'text
 					       nil nil nil right-p)))))
 
 (defun gnus-picons-display-pairs (pairs &optional bar-p dot-p right-p)
   "Display picons in list PAIRS."
-  (let ((bar (and bar-p (or gnus-picons-display-as-address
-			    (annotations-in-region (point)
-						   (min (point-max)
-							(1+ (point)))
-						   (current-buffer)))))
-	(domain-p (and gnus-picons-display-as-address dot-p))
+  (let ((domain-p (and gnus-picons-display-as-address dot-p))
 	pair picons)
+    (if (and bar-p domain-p right-p)
+	(setq picons (gnus-picons-display-glyph
+		      (gnus-picons-try-face gnus-xmas-glyph-directory
+					    "bar.")
+		      nil right-p)))
     (while pairs
       (setq pair (pop pairs)
-	    picons (nconc (if (and domain-p picons (not right-p))
-			      (list (make-annotation
-				     (vector 'string :data dot-p)
-				     nil 'text nil nil nil right-p)))
+	    picons (nconc picons
 			  (gnus-picons-display-picon-or-name (car pair)
 							     (cadr pair)
 							     right-p)
-			  (if (and domain-p pairs right-p)
-			      (list (make-annotation
+			  (if (and domain-p pairs)
+			      (list (gnus-picons-make-annotation
 				     (vector 'string :data dot-p)
-				     nil 'text nil nil nil right-p)))
-			  (when (and bar domain-p)
-			    (setq bar nil)
+				     nil 'text nil nil nil right-p))))))
+    (if (and bar-p domain-p (not right-p))
+	(setq picons (nconc picons
 			    (gnus-picons-display-glyph
 			     (gnus-picons-try-face gnus-xmas-glyph-directory
 						   "bar.")
-			     nil t))
-			  picons)))
+			     nil right-p))))
     picons))
 
 (defun gnus-picons-try-face (dir &optional filebase)
@@ -456,7 +455,8 @@
     glyph))
 
 (defun gnus-picons-display-glyph (glyph &optional part rightp)
-  (let ((new (make-annotation glyph (point) 'text nil nil nil rightp)))
+  (let ((new (gnus-picons-make-annotation glyph (point)
+					  'text nil nil nil rightp)))
     (when (and part gnus-picons-display-as-address)
       (set-annotation-data new (cons new
 				     (make-glyph (vector 'string :data part))))
@@ -466,8 +466,8 @@
      (if (and (eq major-mode 'gnus-article-mode)
 	      (not gnus-picons-display-as-address)
 	      (not part))
-	 (list (make-annotation [string :data " "]
-				(point) 'text nil nil nil rightp))))))
+	 (list (gnus-picons-make-annotation [string :data " "] (point)
+					    'text nil nil nil rightp))))))
 
 (defun gnus-picons-action-toggle (data)
   "Toggle annotation"
@@ -480,7 +480,8 @@
 (defun gnus-picons-clear-cache ()
   "Clear the picons cache"
   (interactive)
-  (setq gnus-picons-glyph-alist nil))
+  (setq gnus-picons-glyph-alist nil
+	gnus-picons-url-alist nil))
 
 (gnus-add-shutdown 'gnus-picons-close 'gnus)
 
@@ -497,14 +498,13 @@
 (defun gnus-picons-url-retrieve (url fn arg)
   (let ((old-asynch (default-value 'url-be-asynchronous))
 	(url-working-buffer (generate-new-buffer " *picons*"))
-	(url-request-method nil)
 	(url-package-name "Gnus")
-	(url-package-version gnus-version-number))
+	(url-package-version gnus-version-number)
+	url-request-method)
     (setq-default url-be-asynchronous t)
     (save-excursion
       (set-buffer url-working-buffer)
       (setq url-be-asynchronous t
-	    url-show-status nil
 	    url-current-callback-data arg
 	    url-current-callback-func fn)
       (url-retrieve url t))
@@ -588,8 +588,7 @@
 ;;; picon network display functions :
 
 (defun gnus-picons-network-display-internal (sym-ann glyph part right-p)
-  (set-buffer
-   (get-buffer-create (gnus-get-buffer-name gnus-picons-display-where)))
+  (gnus-picons-set-buffer)
   (set sym-ann (nconc (symbol-value sym-ann)
 		      (gnus-picons-display-picon-or-name glyph part right-p)))
   (gnus-picons-next-job-internal))
@@ -599,7 +598,11 @@
 						   w3-image-mappings)))))
     (kill-buffer (current-buffer))
     (push (cons url glyph) gnus-picons-glyph-alist)
-    (gnus-picons-network-display-internal sym-ann glyph part right-p)))
+    ;; only do the job if it has not been preempted.
+    (if (equal gnus-picons-job-already-running
+	       (list sym-ann 'picon url part right-p))
+	(gnus-picons-network-display-internal sym-ann glyph part right-p)
+      (gnus-picons-next-job-internal))))
 
 (defun gnus-picons-network-display (url part sym-ann right-p)
   (let ((cache (assoc url gnus-picons-glyph-alist)))
@@ -665,8 +668,16 @@
       (if (and gnus-picons-display-as-address new-jobs)
 	  (push (list sym-ann "@" right-p) new-jobs))
       (push (list sym-ann 'picon (cdr cache) user right-p) new-jobs))
-    (setq gnus-picons-jobs-alist (nconc (nreverse new-jobs)
-					gnus-picons-jobs-alist))
+    (if (and gnus-picons-display-as-address (not right-p))
+	(push (list sym-ann 'bar right-p) new-jobs))
+    ;; only put the jobs in the queue if this job has not been preempted.
+    (if (equal gnus-picons-job-already-running
+	       (list sym-ann 'search user addrs dbs right-p))
+	(setq gnus-picons-jobs-alist
+	      (nconc (if (and gnus-picons-display-as-address right-p)
+			 (list (list sym-ann 'bar right-p)))
+		     (nreverse new-jobs)
+		     gnus-picons-jobs-alist)))
     (gnus-picons-next-job-internal)))
 
 (defun gnus-picons-network-search-callback (user addrs dbs sym-ann right-p)
@@ -696,31 +707,33 @@
       (gnus-picons-network-search-internal user addrs dbs sym-ann right-p))))
 
 ;;; Main jobs dispatcher function
-;; Given that XEmacs is not really multi threaded, this locking should
-;; be sufficient
 
 (defun gnus-picons-next-job-internal ()
-  (if gnus-picons-jobs-alist
-      (let* ((job (pop gnus-picons-jobs-alist))
+  (if (setq gnus-picons-job-already-running (pop gnus-picons-jobs-alist))
+      (let* ((job gnus-picons-job-already-running)
 	     (sym-ann (pop job))
 	     (tag (pop job)))
 	(if tag
 	    (cond ((stringp tag);; (SYM-ANN "..." RIGHT-P)
 		   (gnus-picons-network-display-internal sym-ann nil tag
 							 (pop job)))
+		  ((eq 'bar tag)
+		   (gnus-picons-network-display-internal
+		    sym-ann (gnus-picons-try-face gnus-xmas-glyph-directory
+						  "bar.")
+		    nil (pop job)))
 		  ((eq 'search tag);; (SYM-ANN 'search USER ADDRS DBS RIGHT-P)
 		   (gnus-picons-network-search
 		    (pop job) (pop job) (pop job) sym-ann (pop job)))
 		  ((eq 'picon tag);; (SYM-ANN 'picon URL PART RIGHT-P)
 		   (gnus-picons-network-display
 		    (pop job) (pop job) sym-ann (pop job)))
-		  (t (error "Unknown picon job tag %s" tag)))))
-    (setq gnus-picons-job-already-running nil)))
+		  (t (setq gnus-picons-job-already-running nil)
+		     (error "Unknown picon job tag %s" tag)))))))
 
 (defun gnus-picons-next-job ()
-  "Start processing the job queue."
+  "Start processing the job queue if it is not in progress"
   (unless gnus-picons-job-already-running
-    (setq gnus-picons-job-already-running t)
     (gnus-picons-next-job-internal)))
 
 (provide 'gnus-picon)