Index: lisp/gutter-items.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/Attic/gutter-items.el,v retrieving revision 1.1.2.31 diff -u -r1.1.2.31 gutter-items.el --- lisp/gutter-items.el 2000/02/26 21:28:32 1.1.2.31 +++ lisp/gutter-items.el 2000/02/27 21:10:52 @@ -30,26 +30,13 @@ "Input from the gutters." :group 'environment) -(defvar gutter-buffers-tab nil - "A tab widget in the gutter for displaying buffers. -Do not set this. Use `glyph-image-instance' and -`set-image-instance-property' to change the properties of the tab.") - -(defcustom gutter-visible-p - (specifier-instance default-gutter-visible-p) - "Whether the default gutter is globally visible. This option can be -customized through the options menu." - :group 'gutter - :type 'boolean - :set #'(lambda (var val) - (set-specifier default-gutter-visible-p val) - (setq gutter-visible-p val) - (when gutter-buffers-tab (update-tab-in-gutter)))) - +;; Although these customizations appear bogus, they are neccessary in +;; order to be able to save options through the options menu. (defcustom default-gutter-position (default-gutter-position) "The location of the default gutter. It can be 'top, 'bottom, 'left or -'right. This option can be customized through the options menu." +'right. This option should be customized through the options menu. +To set the gutter position explicitly use `set-default-gutter-position'" :group 'gutter :type '(choice (const :tag "top" top) (const :tag "bottom" bottom) @@ -57,59 +44,68 @@ (const :tag "right" right)) :set #'(lambda (var val) (set-default-gutter-position val) - (setq default-gutter-position val) - (when gutter-buffers-tab (update-tab-in-gutter)))) + (setq default-gutter-position val))) ;;; Gutter helper functions +;; called by Fset_default_gutter_position() +(defvar default-gutter-position-changed-hook nil + "Function or functions to be called when the gutter position is changed. +The value of this variable may be buffer-local.") + +;; called by set-gutter-element-visible-p +(defvar gutter-element-visibility-changed-hook nil + "Function or functions to be called when the visibility of an +element in the gutter changes. The value of this variable may be +buffer-local. The gutter element symbol is passed as an argument to +the hook, as is the visibility flag.") + (defun set-gutter-element (gutter-specifier prop val &optional locale tag-set) "Set GUTTER-SPECIFIER gutter element PROP to VAL in optional LOCALE. This is a convenience function for setting gutter elements." - (let ((spec-list (specifier-spec-list gutter-specifier locale tag-set))) - (if spec-list - (add-spec-list-to-specifier - gutter-specifier - (mapcar #'(lambda (spec) - (setcdr (car (cdr spec)) - (plist-put (cdr (car (cdr spec))) - prop val)) - spec) spec-list) - 'remove-all) - (set-specifier gutter-specifier (list prop val) locale tag-set)))) + (map-extents #'(lambda (extent arg) + (set-extent-property extent 'duplicable t)) val) + (modify-specifier-instances gutter-specifier #'plist-put (list prop val) + 'force nil locale tag-set)) (defun remove-gutter-element (gutter-specifier prop &optional locale tag-set) "Remove gutter element PROP from GUTTER-SPECIFIER in optional LOCALE. This is a convenience function for removing gutter elements." - (let ((spec-list (specifier-spec-list gutter-specifier locale tag-set))) - (when spec-list - (add-spec-list-to-specifier - gutter-specifier - (mapcar #'(lambda (spec) - (setcdr (car (cdr spec)) - (plist-remprop (cdr (car (cdr spec))) - prop)) - spec) spec-list) - 'remove-all)))) + (modify-specifier-instances gutter-specifier #'plist-remprop (list prop) + 'force nil locale tag-set)) -(defun set-gutter-element-visible-p (gutter-specifier +(defun set-gutter-element-visible-p (gutter-visible-specifier-p prop &optional visible-p locale tag-set) - "Make gutter element PROP VISIBLE-P for GUTTER-SPECIFIER in optional LOCALE. + "Change the visibility of gutter elements. +Set the visibility of element PROP to VISIBLE-P for +GUTTER-SPECIFIER-VISIBLE-P in optional LOCALE. This is a convenience function for hiding and showing gutter elements." - (let ((spec-list (specifier-spec-list gutter-specifier locale tag-set))) - (cond (spec-list - (add-spec-list-to-specifier - gutter-specifier - (mapcar #'(lambda (spec) - (setcdr (car (cdr spec)) - (if visible-p - (cons prop (cdr (car (cdr spec)))) - (delq prop (cdr (car (cdr spec)))))) - spec) spec-list) - 'remove-all)) - (visible-p - (set-specifier gutter-specifier (list prop) locale tag-set)) - (t nil)))) + (modify-specifier-instances + gutter-visible-specifier-p #'(lambda (spec prop visible-p) + (if (consp spec) + (if visible-p + (if (memq prop spec) spec + (cons prop spec)) + (delq prop spec)) + (if visible-p (list prop)))) + (list prop visible-p) + 'force nil locale tag-set) + (run-hook-with-args 'gutter-element-visibility-changed-hook prop visible-p)) + +(defun gutter-element-visible-p (gutter-visible-specifier-p + prop &optional domain) + "Determine whether a gutter element is visible. +Given GUTTER-VISIBLE-SPECIFIER-P and gutter element PROP, return +non-nil if it is visible in optional DOMAIN." + (let ((spec (specifier-instance gutter-visible-specifier-p domain))) + (or (and (listp spec) (memq 'buffers-tab spec)) + spec))) + +(defun init-gutter () + "Initialize the gutter." + ;; do nothing as yet. + ) ;;; The Buffers tab @@ -117,6 +113,21 @@ "Customization of `Buffers' tab." :group 'gutter) +(defvar gutter-buffers-tab nil + "A tab widget in the gutter for displaying buffers. +Do not set this. Use `glyph-image-instance' and +`set-image-instance-property' to change the properties of the tab.") + +(defcustom gutter-buffers-tab-visible-p + (gutter-element-visible-p default-gutter-visible-p 'buffers-tab) + "Whether the buffers tab is globally visible. +This option should be set through the options menu." + :group 'buffers-tab + :type 'boolean + :set #'(lambda (var val) + (set-gutter-element-visible-p default-gutter-visible-p 'buffers-tab val) + (setq gutter-buffers-tab-visible-p val))) + (defvar gutter-buffers-tab-orientation 'top "Where the buffers tab currently is. Do not set this.") @@ -293,9 +304,9 @@ (defun add-tab-to-gutter () "Put a tab control in the gutter area to hold the most recent buffers." (setq gutter-buffers-tab-orientation (default-gutter-position)) - (let ((gutter-string "")) + (let ((gutter-string "\n")) (unless gutter-buffers-tab-extent - (setq gutter-buffers-tab-extent (make-extent 0 0 gutter-string))) + (setq gutter-buffers-tab-extent (make-extent 0 1 gutter-string))) (set-extent-begin-glyph gutter-buffers-tab-extent (setq gutter-buffers-tab @@ -309,28 +320,32 @@ (eq gutter-buffers-tab-orientation 'bottom)) '(gutter-pixel-width) '(gutter-pixel-height)) :properties (list :items (buffers-tab-items)))))) - ;; This looks better than a 3d border + + ;; Nuke all existing tabs + (remove-gutter-element top-gutter 'buffers-tab) + (remove-gutter-element bottom-gutter 'buffers-tab) + (remove-gutter-element left-gutter 'buffers-tab) + (remove-gutter-element right-gutter 'buffers-tab) + ;; Put tabs into all devices that will be able to display them (mapcar #'(lambda (x) (when (valid-image-instantiator-format-p 'tab-control x) - (set-specifier default-gutter-border-width 0 'global x) - (set-specifier top-gutter nil 'global x) - (set-specifier bottom-gutter nil 'global x) - (set-specifier left-gutter nil 'global x) - (set-specifier right-gutter nil 'global x) - (set-specifier left-gutter-width 0 'global x) - (set-specifier right-gutter-width 0 'global x) (cond ((eq gutter-buffers-tab-orientation 'top) - (set-specifier top-gutter gutter-string 'global x)) + ;; This looks better than a 3d border + (set-specifier top-gutter-border-width 0 'global x) + (set-gutter-element top-gutter 'buffers-tab gutter-string 'global x)) ((eq gutter-buffers-tab-orientation 'bottom) - (set-specifier bottom-gutter gutter-string 'global x)) + (set-specifier bottom-gutter-border-width 0 'global x) + (set-gutter-element bottom-gutter 'buffers-tab gutter-string 'global x)) ((eq gutter-buffers-tab-orientation 'left) - (set-specifier left-gutter gutter-string 'global x) + (set-specifier left-gutter-border-width 0 'global x) + (set-gutter-element left-gutter 'buffers-tab gutter-string 'global x) (set-specifier left-gutter-width (glyph-width gutter-buffers-tab) 'global x)) ((eq gutter-buffers-tab-orientation 'right) - (set-specifier right-gutter gutter-string 'global x) + (set-specifier right-gutter-border-width 0 'global x) + (set-gutter-element right-gutter 'buffers-tab gutter-string 'global x) (set-specifier right-gutter-width (glyph-width gutter-buffers-tab) 'global x)) @@ -366,9 +381,18 @@ (get-buffer-create "*scratch*"))))) (set-image-instance-property inst :items buffers)))) +(defun update-tab-hook (&optional arg) + (when gutter-buffers-tab (update-tab-in-gutter arg))) + (add-hook 'kill-buffer-hook 'remove-buffer-from-gutter-tab) -(add-hook 'create-frame-hook 'update-tab-in-gutter) +(add-hook 'create-frame-hook 'update-tab-hook) (add-hook 'record-buffer-hook 'update-tab-in-gutter) +(add-hook 'default-gutter-position-changed 'update-tab-hook) +(add-hook 'gutter-element-visibility-changed-hook + #'(lambda (prop visible-p) + (when (and (eq prop 'buffers-tab) + visible-p) + (update-tab-in-gutter)))) ;; ;; progress display @@ -430,7 +454,7 @@ :pixel-height progress-glyph-height :orientation 'horizontal)))))) -(defvar progress-extent-text "") +(defvar progress-extent-text "\n") (defvar progress-extent nil) (defun progress-displayed-p (&optional return-string frame) @@ -469,7 +493,7 @@ oldmsg) ;; nothing to display so get rid of the gauge (set-specifier bottom-gutter-border-width 0 frame) - (set-specifier bottom-gutter-visible-p nil frame)))) + (set-gutter-element-visible-p bottom-gutter-visible-p 'progress nil frame)))) (defun remove-progress (&optional label frame) ;; If label is nil, we want to remove all matching progress gauges. @@ -526,16 +550,16 @@ (redisplay-echo-area))) ;; do some funky display here. (unless progress-extent - (setq progress-extent (make-extent 0 0 progress-extent-text))) + (setq progress-extent (make-extent 0 1 progress-extent-text))) (let ((bglyph (extent-begin-glyph progress-extent))) (set-extent-begin-glyph progress-extent progress-abort-glyph) ;; fixup the gutter specifiers - (set-specifier bottom-gutter progress-extent-text frame) + (set-gutter-element bottom-gutter 'progress progress-extent-text frame) (set-specifier bottom-gutter-border-width 2 frame) (set-image-instance-property (glyph-image-instance progress-text-glyph) :data message) (set-specifier bottom-gutter-height 'autodetect frame) - (set-specifier bottom-gutter-visible-p t frame) + (set-gutter-element-visible-p bottom-gutter-visible-p 'progress t frame) ;; we have to do this so redisplay is up-to-date and so ;; redisplay-gutter-area performs optimally. (redisplay-gutter-area) @@ -561,10 +585,10 @@ (redisplay-echo-area))) ;; do some funky display here. (unless progress-extent - (setq progress-extent (make-extent 0 0 progress-extent-text)) + (setq progress-extent (make-extent 0 1 progress-extent-text)) (set-extent-begin-glyph progress-extent progress-layout-glyph)) ;; fixup the gutter specifiers - (set-specifier bottom-gutter progress-extent-text frame) + (set-gutter-element bottom-gutter 'progress progress-extent-text frame) (set-specifier bottom-gutter-border-width 2 frame) (set-image-instance-property (glyph-image-instance progress-gauge-glyph) :percent val) @@ -572,7 +596,7 @@ (glyph-image-instance progress-text-glyph) :data message) (if (and (eq (specifier-instance bottom-gutter-height frame) 'autodetect) - (specifier-instance bottom-gutter-visible-p frame)) + (gutter-element-visible-p bottom-gutter-visible-p 'progress frame)) (progn ;; if the gauge is already visible then just draw the gutter ;; checking for user events @@ -581,7 +605,7 @@ (dispatch-event (next-command-event)))) ;; otherwise make the gutter visible and redraw the frame (set-specifier bottom-gutter-height 'autodetect frame) - (set-specifier bottom-gutter-visible-p t frame) + (set-gutter-element-visible-p bottom-gutter-visible-p 'progress t frame) ;; we have to do this so redisplay is up-to-date and so ;; redisplay-gutter-area performs optimally. (redisplay-frame) Index: lisp/menubar-items.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/menubar-items.el,v retrieving revision 1.6.2.18 diff -u -r1.6.2.18 menubar-items.el --- lisp/menubar-items.el 2000/01/26 12:33:55 1.6.2.18 +++ lisp/menubar-items.el 2000/02/27 21:10:57 @@ -739,11 +739,11 @@ ))) ,@(if (featurep 'gutter) '(("Gutter Appearance" - ["Visible" - (customize-set-variable 'gutter-visible-p - (not gutter-visible-p)) + ["Buffers Tab Visible" + (customize-set-variable 'gutter-buffers-tab-visible-p + (not gutter-buffers-tab-visible-p)) :style toggle - :selected gutter-visible-p] + :selected gutter-buffers-tab-visible-p] ("Default Location" ["Top" (customize-set-variable 'default-gutter-position 'top) Index: lisp/msw-init.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/msw-init.el,v retrieving revision 1.7 diff -u -r1.7 msw-init.el --- lisp/msw-init.el 1998/06/02 03:50:19 1.7 +++ lisp/msw-init.el 2000/02/27 21:10:57 @@ -47,6 +47,7 @@ (if (featurep 'infodock) (require 'id-x-toolbar) (init-x-toolbar))) + (if (featurep 'gutter) (init-gutter)) (add-hook 'zmacs-deactivate-region-hook (lambda () (if (console-on-window-system-p) Index: lisp/specifier.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/specifier.el,v retrieving revision 1.8 diff -u -r1.8 specifier.el --- lisp/specifier.el 1998/06/30 06:35:26 1.8 +++ lisp/specifier.el 2000/02/27 21:11:00 @@ -403,6 +403,40 @@ how-to-add)))) value) +(defun modify-specifier-instances (specifier func &optional args force default + locale tag-set) + "Modify all specifications that match LOCALE and TAG-SET by FUNC. + +For each specification that exists for SPECIFIER, in locale LOCALE +that matches TAG-SET, call the function FUNC with the instance as its +first argument and with optional arguments ARGS. The result is then +used as the new value of the instantiator. + +If there is no specification in the domain LOCALE matching TAG-SET and +FORCE is non-nil, an explicit one is created from the matching +specifier instance if that exists or DEFAULT otherwise. If LOCALE is +not a domain (i.e. a buffer), DEFAULT is always used. FUNC is then +applied like above and the resulting specification is added." + + (let ((spec-list (specifier-spec-list specifier locale tag-set))) + (cond + (spec-list + ;; Destructively edit the spec-list + (mapc #'(lambda (spec) + (mapc #'(lambda (inst-pair) + (setcdr inst-pair + (apply func (cdr inst-pair) args))) + (cdr spec))) + spec-list) + (add-spec-list-to-specifier specifier spec-list)) + (force + (set-specifier specifier + (apply func + (or (and (valid-specifier-domain-p locale) + (specifier-instance specifier)) + default) args) + locale tag-set))))) + (defmacro let-specifier (specifier-list &rest body) "Add specifier specs, evaluate forms in BODY and restore the specifiers. \(let-specifier SPECIFIER-LIST BODY...) Index: lisp/x-init.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/x-init.el,v retrieving revision 1.8.2.2 diff -u -r1.8.2.2 x-init.el --- lisp/x-init.el 1998/12/05 16:54:55 1.8.2.2 +++ lisp/x-init.el 2000/02/27 21:11:02 @@ -305,8 +305,8 @@ (init-x-toolbar)) (if (and (featurep 'infodock) (featurep 'toolbar)) (require 'id-x-toolbar)) - (if (featurep 'mule) - (init-mule-x-win)) + (if (featurep 'gutter) (init-gutter)) + (if (featurep 'mule) (init-mule-x-win)) ;; these are only ever called if zmacs-regions is true. (add-hook 'zmacs-deactivate-region-hook (lambda () Index: src/gutter.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/gutter.c,v retrieving revision 1.1.2.20 diff -u -r1.1.2.20 gutter.c --- src/gutter.c 2000/02/26 21:26:11 1.1.2.20 +++ src/gutter.c 2000/02/27 21:11:14 @@ -48,6 +48,7 @@ Lisp_Object Qgutter_size; Lisp_Object Qgutter_visible; +Lisp_Object Qdefault_gutter_position_changed_hook; #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ do { \ @@ -514,14 +515,21 @@ list1 (Fcons (Qnil, Qzero))); set_specifier_fallback (Vgutter_border_width[new], Vdefault_gutter_border_width); + /* We don't realy want the left and right gutters to default to + visible. */ set_specifier_fallback (Vgutter_visible_p[cur], - list1 (Fcons (Qnil, Qt))); + cur == TOP_GUTTER || cur == BOTTOM_GUTTER ? + list1 (Fcons (Qnil, Qt)) + : list1 (Fcons (Qnil, Qnil))); set_specifier_fallback (Vgutter_visible_p[new], Vdefault_gutter_visible_p); + Vdefault_gutter_position = position; unhold_frame_size_changes (); } + run_hook (Qdefault_gutter_position_changed_hook); + return position; } @@ -858,6 +866,8 @@ defsymbol (&Qgutter_size, "gutter-size"); defsymbol (&Qgutter_visible, "gutter-visible"); + defsymbol (&Qdefault_gutter_position_changed_hook, + "default-gutter-position-changed"); } void