changeset 18016:22cbed2e6098

(hs-special-modes-alist): Include also the comment regexp in the alist. This is needed for modes like c++ where the comment beginning regexp is not easy to determine from the syntax table. Include ADJUST-BLOCK-BEGINNING in the alist. (hs-hide-comments-when-hiding-all): Add autoload cookie. (hs-show-hidden-short-form): (hs-adjust-block-beginning): New variables. Comment out `hs-menu-bar' as XEmacs support was removed. (hs-c-end-regexp): Remove variable, obsoleted by the rewrite of `hs-inside-comment-p'. (hs-discard-overlays): No need to test if we are inside the overlay, we surely are since we got the overlay using `overlays-at'. (hs-hide-block-at-point): Rewritten to use the new variables. Use only one parameter to specify the comment. (hs-show-block-at-point): No need for the COMMENT-REG parameter. (hs-safety-is-job-n): Correct typo. (hs-hide-initial-comment-block): Add ^L to the chars to skip. Take into account `hs-show-hidden-short-form' when testing. (hs-inside-single-line-comment-p): Function deleted, obsoleted by the rewrite of `hs-inside-comment-p'. (hs-inside-comment-p): Rewritten from scratch. Semantics changed when returning non-nil. We can be inside a comment, but that comment might not be hidable (the car of the return value should be non-nil to be hidable). (hs-grok-mode-type): Rewrite to be more understandable. `hs-c-end-regexp' does not exist any more. Initialize `hs-c-start-regexp' from the alist if specified there. Initialize `hs-adjust-block-beginning'. (hs-find-block-beginning): Rewritten to be able to deal with the situation when a block beginning spans multiple lines and the point is on one of those lines. (hs-already-hidden-p): Look first if we are inside a comment or a block, go to their end and look there for the overlays. (java-hs-adjust-block-beginning): New function. (hs-hide-all): Hide a comment block only if `hs-inside-comment-p' says is hidable. (hs-hide-block): Simplify. Handle properly the result of `hs-inside-comment-p'. (hs-show-block): Likewise. (hs-minor-mode): Doc string fixes. Make `hs-adjust-block-beginning' buffer local. Delete making `hs-c-end-regexp' buffer local as it was deleted.
author Richard M. Stallman <rms@gnu.org>
date Thu, 29 May 1997 05:23:39 +0000
parents 934a44a3b34f
children 4c3a2b58fd72
files lisp/progmodes/hideshow.el
diffstat 1 files changed, 334 insertions(+), 163 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/progmodes/hideshow.el	Thu May 29 03:32:17 1997 +0000
+++ b/lisp/progmodes/hideshow.el	Thu May 29 05:23:39 1997 +0000
@@ -87,9 +87,50 @@
 ;;;#autoload
 (defvar hs-special-modes-alist 
   '((c-mode "{" "}")
-    (c++-mode "{" "}")
-    (java-mode "\\(\\(public\\|private\\|protected\\|static\\|\\s-\\)+\\([a-zA-Z0-9_:]+[ \t]+\\)\\([a-zA-Z0-9_:]+\\)[ \t]*([^)]*)[ \t\n]*\\([ \t\n]throws[ \t]+[^{]+\\)*[ \t]*\\){" "}" java-hs-forward-sexp))
-  "*Alist of the form (MODE START-RE END-RE FORWARD-SEXP-FUNC).
+    (c++-mode "{" "}" "/[*/]")
+    (java-mode   "\\(\\(\\([ \t]*\\(\\(public\\|private\\|protected\\|abstract\\|static\\|\\final\\)[ \t\n]+\\)+\\(synchronized[ \t\n]*\\)?[a-zA-Z0-9_:]+[ \t\n]*\\(\\[[ \t\n]*\\][ \t\n]*\\)?\\([a-zA-Z0-9_:]+[ \t\n]*\\)([^)]*)\\([ \n\t]+throws[ \t\n][^{]+\\)?\\)\\|\\([ \t]*static[^{]*\\)\\)[ \t\n]*{\\)"  "}"  "/[*/]" java-hs-forward-sexp java-hs-adjust-block-beginning))
+; I tested the java regexp using the following:
+;(defvar hsj-public)
+;(defvar hsj-syncronised)
+;(defvar hsj-type)
+;(defvar hsj-fname)
+;(defvar hsj-par)
+;(defvar hsj-throws)
+;(defvar hsj-static)
+
+;(setq hsj-public "[ \t]*\\(\\(public\\|private\\|protected\\|abstract\\|static\\|\\final\\)[ \t\n]+\\)+")
+;(setq hsj-syncronised "\\(synchronized[ \t\n]*\\)?")
+;(setq hsj-type "[a-zA-Z0-9_:]+[ \t\n]*\\(\\[[ \t\n]*\\][ \t\n]*\\)?")
+;(setq hsj-fname "\\([a-zA-Z0-9_:]+[ \t\n]*\\)")
+;(setq hsj-par "([^)]*)")
+;(setq hsj-throws "\\([ \n\t]+throws[ \t\n][^{]+\\)?")
+
+;(setq hsj-static "[ \t]*static[^{]*")
+
+
+;(setq hs-block-start-regexp (concat
+;			     "\\("
+;			         "\\("
+;				      "\\("
+;				         hsj-public
+;				         hsj-syncronised
+;					 hsj-type
+;					 hsj-fname
+;					 hsj-par
+;					 hsj-throws
+;				      "\\)"
+;				      "\\|"
+;				      "\\("
+;				         hsj-static
+;				      "\\)"
+;				 "\\)"
+;				    "[ \t\n]*{"
+;			      "\\)"  
+;				    ))
+
+  "*Alist for initializing the hideshow variables for different modes.
+It has the form 
+(MODE START-RE END-RE COMMENT-START-RE FORWARD-SEXP-FUNC ADJUST-BEG-FUNC).
 If present, hideshow will use these values for the start and end regexps,
 respectively.  Since Algol-ish languages do not have single-character
 block delimiters, the function `forward-sexp' which is used by hideshow
@@ -102,9 +143,15 @@
 
 For example:
 
-\t(pushnew '(simula-mode \"begin\" \"end\" simula-next-statement)
+\t(pushnew '(simula-mode \"begin\" \"end\" \"!\" simula-next-statement)
 \t	hs-special-modes-alist :test 'equal)
 
+See the documentation for `hs-adjust-block-beginning' to see what
+is the use of ADJUST-BEG-FUNC.
+
+If any of those is left nil, hideshow will try to guess some values, see
+`hs-grok-mode-type' for this.
+
 Note that the regexps should not contain leading or trailing whitespace.")
 
 (defvar hs-minor-mode-hook 'hs-hide-initial-comment-block
@@ -122,6 +169,49 @@
 (defvar hs-minor-mode-prefix "\C-c"
   "*Prefix key to use for hideshow commands in hideshow minor mode.")
 
+;;;#autoload
+(defvar hs-hide-comments-when-hiding-all t 
+  "Hide the comments too when you do an `hs-hide-all'." )
+
+;;;#autoload
+(defvar hs-show-hidden-short-form t
+  "Leave only the first line visible in a hidden block.
+If t only the first line is visible when a block is in the hidden state, 
+else both the first line and the last line are showed. Also if t and 
+`hs-adjust-block-beginning' is set, it is used also.
+
+An example of how this works: (in c-mode)
+original:
+                      
+/* My function main
+   some more stuff about main
+*/
+int
+main(void)
+{
+  int x=0;
+  return 0;
+}
+
+
+hidden and hs-show-hidden-short-form is nil
+/* My function main...
+*/                        
+int
+main(void)
+{...
+}
+
+hidden and hs-show-hidden-short-form is t
+/* My function main...
+int                   
+main(void)                  
+{ ...
+
+
+The latest has the disadvantage of not being symetrical, but it saves
+screen lines ...
+")
 
 ;;;----------------------------------------------------------------------------
 ;;; internal variables
@@ -133,18 +223,14 @@
 (defvar hs-minor-mode-map nil
   "Mode map for hideshow minor mode.")
 
-(defvar hs-menu-bar nil
-  "Menu bar for hideshow minor mode (Xemacs only).")
+;(defvar hs-menu-bar nil
+;  "Menu bar for hideshow minor mode (Xemacs only).")
 
 (defvar hs-c-start-regexp nil
   "Regexp for beginning of comments.  
 Differs from mode-specific comment regexps in that 
 surrounding whitespace is stripped.")
 
-(defvar hs-c-end-regexp nil
-  "Regexp for end of comments.
-See `hs-c-start-regexp'.")
-
 (defvar hs-block-start-regexp nil
   "Regexp for beginning of block.")
 
@@ -159,8 +245,24 @@
 For other modes such as simula, a more specialized function
 is necessary.")
 
-(defvar hs-hide-comments-when-hiding-all t 
-  "Hide the comments too when you do an `hs-hide-all'." )
+(defvar hs-adjust-block-beginning nil
+  "Function used to tweak the block beginning.
+It has effect only if `hs-show-hidden-short-form' is t. The block it
+is hidden from the point returned by this function, as opposed to
+hiding it from the point returned when searching
+`hs-block-start-regexp'.  In c-like modes, if we wish to also hide the
+curly braces (if you think they occupy too much space on the screen),
+this function should return the starting point (at the end of line) of
+the hidden region.  
+
+It is called with a single argument ARG which is the the position in
+buffer after the block beginning.
+
+It should return the position from where we should start hiding.
+
+It should not move the point.  
+
+See `java-hs-adjust-block-beginning' for an example of using this.")
 
 ;(defvar hs-emacs-type 'fsf
 ;  "Used to support both Emacs and Xemacs.")
@@ -175,7 +277,7 @@
 ;;;----------------------------------------------------------------------------
 ;;; support funcs
 
-;; snarfed from noutline.el;
+;; snarfed from outline.el;
 (defun hs-flag-region (from to flag)
   "Hides or shows lines from FROM to TO, according to FLAG.
 If FLAG is nil then text is shown, while if FLAG is t the text is hidden."
@@ -203,67 +305,79 @@
 	(while overlays
 	  (let ((o (car overlays)))
 	    (if (eq (overlay-get o prop) value)
-		(if (or 
-		     (and (> (overlay-end o) beg) (< (overlay-end o) end))
-		     (and (< (overlay-start o) beg) (< (overlay-start o) end)))
-		    (delete-overlay o))))
+		    (delete-overlay o)))
 	  (setq overlays (cdr overlays))))
       (goto-char (next-overlay-change (point))))))
 
-(defun hs-hide-block-at-point (&optional end comment c-reg)
+(defun hs-hide-block-at-point (&optional end comment-reg)
   "Hide block iff on block beginning, optional END means reposition at end.
-COMMENT true means that it should hide a comment block, C-REG is a list
-of the form (BEGIN . END) and specifies the limits of the comment." 
-  (if comment
-      (let ((reg (if c-reg  c-reg (hs-inside-comment-p))))
-	(goto-char (nth 1 reg))
-	(forward-line -1)
+COMMENT-REG is a list of the form (BEGIN . END) and specifies the limits 
+of the comment, or nil if the block is not a comment." 
+  (if comment-reg
+      (progn 
+	;; goto the end of line at the end of the comment
+	(goto-char (nth 1 comment-reg))
+	(unless hs-show-hidden-short-form (forward-line -1))
 	(end-of-line)
-	(hs-flag-region (car reg)  (point) t)
-	(goto-char (if end (nth 1 reg) (car reg)))
-	)
+	(hs-flag-region (car comment-reg)  (point) t) 
+	(goto-char (if end (nth 1 comment-reg) (car comment-reg))))
       (if (looking-at hs-block-start-regexp)
-	  (let* ((p (point))
+	  (let* ((p ;; p is the point at the end of the block beginning
+		  (if (and  hs-show-hidden-short-form 
+			    hs-adjust-block-beginning)
+		      ;; we need to adjust the block beginning
+		      (funcall hs-adjust-block-beginning (match-end 0)) 
+		    (match-end 0)))
+		 ;; q is the point at the end of the block
 		 (q (progn (funcall hs-forward-sexp-func 1) (point))))
-	    (forward-line -1) (end-of-line)
-	    (if (and (< p (point)) (> (count-lines p q) 1))
-	    (hs-flag-region p (point) t))
-	(goto-char (if end q p))))))
+	    ;; position the point so we can call `hs-flag-region'
+	    (unless hs-show-hidden-short-form (forward-line -1))
+	    (end-of-line)
+	    (if (and (< p (point)) (> (count-lines p q) 
+				      (if hs-show-hidden-short-form 1 2)))
+		(hs-flag-region p (point) t))
+	    (goto-char (if end q p))))))
 
-(defun hs-show-block-at-point (&optional end)
-  "Show block iff on block beginning.  Optional END means reposition at end."
-  (if (looking-at hs-block-start-regexp)
-      (let* ((p (point))
-	     (q
-	      (condition-case error	; probably unbalanced paren
-		  (progn
-		    (funcall hs-forward-sexp-func 1)
-		    (point))
-		(error
-		 (cond
-		  ((eq hs-unbalance-handler-method 'ignore)
-		   ;; just ignore this block
-		   (point))
-		  ((eq hs-unbalance-handler-method 'top-level)
-		   ;; try to get out of rat's nest and expose the whole func
-		   (if (/= (current-column) 0) (beginning-of-defun))
-		   (setq p (point))
-		   (re-search-forward (concat "^" hs-block-start-regexp)
-				      (point-max) t 2)
-		   (point))
-		  ((eq hs-unbalance-handler-method 'next-line)
-		   ;; assumption is that user knows what s/he's doing
-		   (beginning-of-line) (setq p (point))
-		   (end-of-line 2) (point))
-		  (t
-		   ;; pass error through -- this applies to `signal', too
-		   (signal (car error) (cdr error))))))))
-	(hs-flag-region p q nil)
-	(goto-char (if end (1+ (point)) p)))))
+(defun hs-show-block-at-point (&optional end comment-reg)
+  "Show block iff on block beginning.  Optional END means reposition at end.
+COMMENT-REG is a list of the forme (BEGIN . END) and specifies the limits 
+of the comment. It should be nil when hiding a block." 
+  (if comment-reg
+      (when (car comment-reg)
+	(hs-flag-region (car comment-reg) (nth 1 comment-reg) nil)
+	(goto-char (if end (nth 1 comment-reg) (car comment-reg))))
+    (if (looking-at hs-block-start-regexp)
+	(let* ((p (point))
+	       (q
+		(condition-case error	; probably unbalanced paren
+		    (progn
+		      (funcall hs-forward-sexp-func 1)
+		      (point))
+		  (error
+		   (cond
+		    ((eq hs-unbalance-handler-method 'ignore)
+		     ;; just ignore this block
+		     (point))
+		    ((eq hs-unbalance-handler-method 'top-level)
+		     ;; try to get out of rat's nest and expose the whole func
+		     (if (/= (current-column) 0) (beginning-of-defun))
+		     (setq p (point))
+		     (re-search-forward (concat "^" hs-block-start-regexp)
+					(point-max) t 2)
+		     (point))
+		    ((eq hs-unbalance-handler-method 'next-line)
+		     ;; assumption is that user knows what s/he's doing
+		     (beginning-of-line) (setq p (point))
+		     (end-of-line 2) (point))
+		    (t
+		     ;; pass error through -- this applies to `signal', too
+		     (signal (car error) (cdr error))))))))
+	  (hs-flag-region p q nil)
+	  (goto-char (if end (1+ (point)) p))))))
 
 (defun hs-safety-is-job-n ()
   "Warn `buffer-invisibility-spec' does not contain hs."
-    (if (or buffer-invisibility-spec (assq hs buffer-invisibility-spec) )
+    (if (or buffer-invisibility-spec (assq 'hs buffer-invisibility-spec) )
 	nil
       (message "Warning: `buffer-invisibility-spec' does not contain hs!!")
       (sit-for 2)))
@@ -276,82 +390,122 @@
       (let ((p (point))
 	    c-reg)
 	(goto-char (point-min))
-	(skip-chars-forward " \t\n")
+	(skip-chars-forward " \t\n^L")
 	(setq c-reg (hs-inside-comment-p))
-	(if (and c-reg (> (count-lines (car c-reg) (nth 1 c-reg)) 2))
+	;; see if we have enough comment lines to hide
+	(if (and c-reg (> (count-lines (car c-reg) (nth 1 c-reg)) 
+			  (if hs-show-hidden-short-form 1 2)))
 	    (hs-hide-block)
 	  (goto-char p))))
 
-(defun hs-inside-single-line-comment-p ()
-  "Look to see if we are on a single line comment."
-  (save-excursion
-    (beginning-of-line)
-    (looking-at (concat "^[ \t]*" hs-c-start-regexp))))
-
 (defun hs-inside-comment-p ()
   "Returns non-nil if point is inside a comment, otherwise nil.
 Actually, returns a list containing the buffer position of the start 
-and the end of the comment."
-  (save-excursion
-    (let ((p (point))
-	  q
-	  p-aux)
-      (if (string= comment-end "")	; single line
-	    (if (not (hs-inside-single-line-comment-p))
-		nil
-	      ;;find-beginning-of-the-chained-single-line-comments
-	      (beginning-of-line)
-	      (forward-comment (- (buffer-size)))
-	      (skip-chars-forward " \t\n")
-	      (beginning-of-line)
-	      (setq q (point))
-	      (goto-char p)
-	      ;;find-end-of-the-chained-single-line-comments
-	      (forward-comment (buffer-size))
-	      (skip-chars-backward " \t\n")
-	      (list q   (point)))
-	(re-search-forward hs-c-end-regexp (point-max) 1)
-	(forward-comment (buffer-size))
-	(skip-chars-backward " \t\n")
-	(end-of-line)
-	(setq q (point))
-	(forward-comment (- 0 (buffer-size)))
-	(re-search-forward hs-c-start-regexp (point-max) 1)
-	(setq p-aux (- (point) (length comment-start)))
-	(if (and (>= p-aux 0) (< p-aux p))
-	    (list (match-beginning 0) q))))))
+and the end of the comment. A comment block can be hided only if on its 
+starting line there are only white spaces preceding the actual comment 
+beginning, if we are inside of a comment but this condition is not 
+we return a list having a nil as its car and the end of comment position
+as cdr."
+  (save-excursion 
+    ;; the idea is to look backwards for a comment start regexp, do a
+    ;; forward comment, and see if we are inside, then extend extend
+    ;; forward and backward as long as we have comments
+    (let ((q (point)))
+      (when (or (looking-at hs-c-start-regexp)
+	      (re-search-backward hs-c-start-regexp (point-min) t))
+	(forward-comment (- (buffer-size)))
+	(skip-chars-forward " \t\n")
+	(let ((p (point))
+	      (not-hidable nil))
+	  (beginning-of-line)
+	  (unless (looking-at (concat "[ \t]*" hs-c-start-regexp))
+	    ;; we are in this situation: (example)
+	    ;; (defun bar ()
+	    ;;      (foo)
+	    ;;                ) ; comment
+	    ;;                 ^
+	    ;;   the point was here before doing (beginning-of-line)
+	    ;; here we should advance till the next comment which 
+	    ;; eventually has only white spaces preceding it on the same
+	    ;; line 
+	    (goto-char p)
+	    (forward-comment 1)
+	    (skip-chars-forward " \t\n")
+	    (setq p (point))
+	    (while (and (< (point) q) 
+			(> (point) p) 
+			(not (looking-at hs-c-start-regexp)))
+	      (setq p (point))  ;; use this to avoid an infinit cycle.
+	      (forward-comment 1)
+	      (skip-chars-forward " \t\n"))
+	    (if (or (not (looking-at hs-c-start-regexp)) 
+		    (> (point) q))
+		;; we cannot hide this comment block
+		(setq not-hidable t)))
+	  ;; goto the end of the comment
+	  (forward-comment (buffer-size))
+	  (skip-chars-backward " \t\n")
+	  (end-of-line)
+	  (if (>= (point) q)
+	      (list (if not-hidable nil p) (point))))))))
 
 (defun hs-grok-mode-type ()
   "Setup variables for new buffers where applicable."
-  (if (and (boundp 'comment-start)
-	   (boundp 'comment-end))
-      (progn
-	(setq hs-c-start-regexp (regexp-quote comment-start))
-	(if (string-match " +$" hs-c-start-regexp)
-	    (setq hs-c-start-regexp
-		  (substring hs-c-start-regexp 0 (1- (match-end 0)))))
-	(setq hs-c-end-regexp (if (string= "" comment-end) "\n"
-				(regexp-quote comment-end)))
-	(if (string-match "^ +" hs-c-end-regexp)
-	    (setq hs-c-end-regexp
-		  (substring hs-c-end-regexp (match-end 0))))
-	(let ((lookup (assoc major-mode hs-special-modes-alist)))
-	  (setq hs-block-start-regexp (or (nth 1 lookup) "\\s\(")
-		hs-block-end-regexp (or (nth 2 lookup) "\\s\)")
-		hs-forward-sexp-func (or (nth 3 lookup) 'forward-sexp))))))
+  (when (and (boundp 'comment-start)
+	     (boundp 'comment-end))
+    (let ((lookup (assoc major-mode hs-special-modes-alist)))
+      (setq hs-block-start-regexp (or (nth 1 lookup) "\\s\(")
+	    hs-block-end-regexp (or (nth 2 lookup) "\\s\)")
+	    hs-c-start-regexp (or (nth 3 lookup)
+				  (let ((c-start-regexp 
+					 (regexp-quote comment-start)))
+				    (if (string-match " +$" c-start-regexp)
+					 (substring c-start-regexp 0 (1- (match-end 0)))
+				      c-start-regexp)))
+	    hs-forward-sexp-func (or (nth 4 lookup) 'forward-sexp)
+	    hs-adjust-block-beginning (nth 5 lookup)))))
 
 (defun hs-find-block-beginning ()
-  "Repositions point at block-start.  
-Return point, or nil if top-level." 
+  "Repositions point at block-start.
+Return point, or nil if top-level."
   (let (done
+	(try-again t)
 	(here (point))
 	(both-regexps (concat "\\(" hs-block-start-regexp "\\)\\|\\("
 			      hs-block-end-regexp "\\)")))
+    (beginning-of-line)
+    ;; A block beginning can span on multiple lines, if the point
+    ;; is on one of those lines, trying a regexp search from
+    ;; that point would fail to find the block beginning, so we look
+    ;; backwards for the block beginning, or a block end.
+    (while try-again
+      (setq try-again nil)
+      (when (re-search-backward both-regexps (point-min) t)
+	(if (match-beginning 1) ; found a block beginning
+	    (if (save-match-data (hs-inside-comment-p)) 
+		;;but it was inside a comment, so we have to look for
+		;;it again
+		(setq try-again t)
+	      ;; that's what we were looking for
+	      (setq done (match-beginning 0)))
+	  ;; we found a block end, look to see if we were on a block
+	  ;; beginning when we started
+	  (if (and 
+	       (re-search-forward hs-block-start-regexp (point-max) t)
+	       (>= here (match-beginning 0)) (< here (match-end 0)))
+	      (setq done (match-beginning 0))))))
+    (goto-char here)
     (while (and (not done)
+		;; This had problems because the regexp can match something
+		;; inside of a comment!
+		;; Since inside a comment we can have incomplete sexps
+		;; this would have signaled an error.
+		(or (forward-comment (-(buffer-size))) t); `or' is a hack to
+							 ; make it return t
 		(re-search-backward both-regexps (point-min) t))
       (if (match-beginning 1)		; start of start-regexp
-	  (setq done (match-beginning 1))
-	(goto-char (match-end 2))	; end of end-regexp
+	  (setq done (match-beginning 0))
+	(goto-char (match-end 0))	; end of end-regexp
 	(funcall hs-forward-sexp-func -1)))
     (goto-char (or done here))
     done))
@@ -361,8 +515,16 @@
   (list 'if 'hs-minor-mode (cons 'progn body)))
 
 (defun hs-already-hidden-p ()
-  "Return non-nil if point is in an already-hidden block otherwise nil."
+  "Return non-nil if point is in an already-hidden block, otherwise nil."
   (save-excursion
+    (let ((c-reg (hs-inside-comment-p)))
+      (if (and c-reg (nth 0 c-reg))
+	  ;; point is inside a comment, and that comment is hidable
+	  (goto-char (nth 0 c-reg))
+	(if (and (not c-reg) (hs-find-block-beginning)
+		 (looking-at hs-block-start-regexp))
+	    ;; point is inside a block
+	    (goto-char (match-end 0)))))
     (end-of-line)
     (let ((overlays (overlays-at (point)))
 	  (found nil))
@@ -382,6 +544,17 @@
 	  (forward-sexp 1))
       (forward-sexp 1))))
 
+(defun java-hs-adjust-block-beginning (arg)
+  "Function to be assigned to `hs-adjust-block-beginning'.
+Arg is a position in buffer just after {. This goes back to the end of
+the function header. The purpose is to save some space on the screen
+when displaying hidden blocks."
+  (save-excursion
+    (goto-char arg)
+    (forward-char -1)
+    (forward-comment (- (buffer-size)))
+    (point)))
+
 ;;;----------------------------------------------------------------------------
 ;;; commands
 
@@ -398,7 +571,8 @@
      (hs-flag-region (point-min) (point-max) nil) ; eliminate weirdness
      (goto-char (point-min))
      (if hs-hide-comments-when-hiding-all 
-	 (let ((count 0)
+	 (let (c-reg
+	       (count 0)
 	       (block-and-comment-re  ;; this should match 
 		(concat "\\(^"        ;; the block beginning and comment start
 			hs-block-start-regexp  
@@ -411,14 +585,13 @@
 		   (message "Hiding ... %d" (setq count (1+ count))))
 	       ;;found a comment
 	       (setq c-reg (hs-inside-comment-p))
-	       (if c-reg 
-		   (progn 
-		     (goto-char (nth 1 c-reg))
-		     (if (> (count-lines (car c-reg) (nth 1 c-reg)) 2)
-			 (progn
-			   (hs-hide-block-at-point t t c-reg)
-			   (message "Hiding ... %d" 
-				    (setq count (1+ count))))))))))
+	       (if (and c-reg (car c-reg))
+		   (if (> (count-lines (car c-reg) (nth 1 c-reg)) 
+			  (if hs-show-hidden-short-form 1 2))
+		       (progn
+			 (hs-hide-block-at-point t c-reg)
+			 (message "Hiding ... %d" (setq count (1+ count))))
+		     (goto-char (nth 1 c-reg)))))))
        (let ((count 0)
 	     (top-level-re (concat "^" hs-block-start-regexp)))
 	 (while 
@@ -446,48 +619,39 @@
 
 (defun hs-hide-block (&optional end)
   "Selects a block and hides it.  
-With prefix arg, reposition at end.  Block is defined as a sexp for
-lispish modes, mode-specific otherwise.  Comments are blocks, too.  
-Upon completion, point is at repositioned and the normal hook 
+With prefix arg, reposition at end. Block is defined as a sexp for
+lispish modes, mode-specific otherwise. Comments are blocks, too.
+Upon completion, point is at repositioned and the normal hook
 `hs-hide-hook' is run.  See documentation for `run-hooks'."
   (interactive "P")
   (hs-life-goes-on
    (let ((c-reg (hs-inside-comment-p)))
-     (if c-reg
-	 (cond 
-	  ((<= (count-lines (car c-reg) (nth 1 c-reg)) 2)
+     (cond
+      ((and c-reg (or (null (nth 0 c-reg)) 
+		      (<= (count-lines (car c-reg) (nth 1 c-reg)) 
+			  (if hs-show-hidden-short-form 1 2))))
 	   (message "Not enough comment lines to hide!"))
-	  (t
-	   (goto-char (nth 1 c-reg))
-	   (hs-hide-block-at-point end t c-reg)
-	   (hs-safety-is-job-n)
-	   (run-hooks 'hs-hide-hook)))
-       (if (or (looking-at hs-block-start-regexp)
+      ((or c-reg (looking-at hs-block-start-regexp)
 	       (hs-find-block-beginning))
-	   (progn
-	     (hs-hide-block-at-point end)
-	     (hs-safety-is-job-n)
-	     (run-hooks 'hs-hide-hook)))))))
+       (hs-hide-block-at-point end c-reg)
+       (hs-safety-is-job-n)
+       (run-hooks 'hs-hide-hook))))))
 
 (defun hs-show-block (&optional end)
   "Selects a block and shows it.
-With prefix arg, reposition at end.  Upon completion, point is 
+With prefix arg, reposition at end. Upon completion, point is
 repositioned and the normal hook `hs-show-hook' is run.  
 See documentation for `hs-hide-block' and `run-hooks'."
   (interactive "P")
   (hs-life-goes-on
    (let ((c-reg (hs-inside-comment-p)))
-     (if c-reg
-	 (progn
-	   (hs-flag-region (car c-reg) (nth 1 c-reg) nil)
-	   (hs-safety-is-job-n)
-	   (goto-char (if end (nth 1 c-reg) (car c-reg))))
-       (if (or (looking-at hs-block-start-regexp)
-	       (hs-find-block-beginning))
+     (if (or c-reg
+	     (looking-at hs-block-start-regexp)
+	     (hs-find-block-beginning))
 	   (progn
-	     (hs-show-block-at-point end)
+	     (hs-show-block-at-point end c-reg)
 	     (hs-safety-is-job-n)
-	     (run-hooks 'hs-show-hook)))))))
+	     (run-hooks 'hs-show-hook))))))
 
 (defun hs-show-region (beg end)
   "Shows all lines from BEG to END, without doing any block analysis.
@@ -515,13 +679,21 @@
   "Toggle hideshow minor mode.
 With ARG, turn hideshow minor mode on if ARG is positive, off otherwise.
 When hideshow minor mode is on, the menu bar is augmented with hideshow
-commands and the hideshow commands are enabled.  The variables
-`selective-display' and `selective-display-ellipses' are set to t.
+commands and the hideshow commands are enabled.  
+The value '(hs . t) is added to `buffer-invisibility-spec'.
 Last, the normal hook `hs-minor-mode-hook' is run; see the doc 
 for `run-hooks'.
 
+The main commands are: `hs-hide-all', `hs-show-all', `hs-hide-block'
+and `hs-show-block'. 
+Also see the documentation for the variable `hs-show-hidden-short-form'.
+
 Turning hideshow minor mode off reverts the menu bar and the
-variables to default values and disables the hideshow commands."
+variables to default values and disables the hideshow commands.
+
+Key bindings:
+\\{hs-minor-mode-map}"
+
   (interactive "P")
   (setq hs-minor-mode
         (if (null arg)
@@ -577,8 +749,7 @@
   (define-key hs-minor-mode-map [menu-bar Hide/Show hs-show-block]
     '("Show Block" . hs-show-block))
   (define-key hs-minor-mode-map [menu-bar Hide/Show hs-hide-block]
-    '("Hide Block" . hs-hide-block))
-  )
+    '("Hide Block" . hs-hide-block)))
 
 ;; some housekeeping
 (or (assq 'hs-minor-mode minor-mode-map-alist)
@@ -592,16 +763,16 @@
 ;; make some variables buffer-local
 (make-variable-buffer-local 'hs-minor-mode)
 (make-variable-buffer-local 'hs-c-start-regexp)
-(make-variable-buffer-local 'hs-c-end-regexp)
 (make-variable-buffer-local 'hs-block-start-regexp)
 (make-variable-buffer-local 'hs-block-end-regexp)
 (make-variable-buffer-local 'hs-forward-sexp-func)
+(make-variable-buffer-local 'hs-adjust-block-beginning)
 (put 'hs-minor-mode 'permanent-local t)
 (put 'hs-c-start-regexp 'permanent-local t)
-(put 'hs-c-end-regexp 'permanent-local t)
 (put 'hs-block-start-regexp 'permanent-local t)
 (put 'hs-block-end-regexp 'permanent-local t)
 (put 'hs-forward-sexp-func 'permanent-local t)
+(put 'hs-adjust-block-beginning 'permanent-local t)
 
 
 ;;;----------------------------------------------------------------------------