[comp.emacs] Is there a cleaner way to check for a narrowed buffer?

allbery@axcess.UUCP (Brandon S. Allbery) (01/16/88)

I have a function which wants to narrow the current buffer to a region only if
it is not already narrowed.  (The narrowing separates parts of a buffer which
are edited with different major modes.)  If the buffer is already narrowed, I
want the function to signal an error.

The only way I have figured out so far to do this is the following piece of
ugliness:

	(let ((old-min (point-min))
	      (old-max (point-max)))
	  (unwind-protect
	      (progn
		(widen)
		(if (not (and (= old-min (point-min))
			      (= old-max (point-max))))
		    (error "You already have a C section in this file.")))
		  (narrow-to-region old-min old-max)))

I personally consider stuff like "unwind-protect" to be for use in special
situations -- and checking for narrowing isn't one of them, or shouldn't be.
I guess it's done in the C code rather than Lisp (since the format %n is used
in the modeline rather than checking for a variable's value), but why isn't
some special function provided ( (narrowp) or something ) to do this?
-- 
 ___  ________________,	Brandon S. Allbery	       cbosgd \
'   \/  __   __,  __,	aXcess Company		       mandrill|
 __  | /__> <__  <__	6615 Center St. #A1-105		       !ncoast!
/  ` | \__. .__> .__>	Mentor, OH 44060-4101	       necntc  | axcess!allbery
\___/\________________.	Moderator, comp.sources.misc   hoptoad/

wolfgang@mgm.mit.edu (Wolfgang Rupprecht) (01/18/88)

In article <138@axcess.UUCP> allbery@axcess.UUCP (Brandon S. Allbery) writes:
>I have a function which wants to narrow the current buffer to a region only if
>it is not already narrowed. [...] but why isn't
>some special function provided ( (narrowp) or something ) to do this?

(defun narowp () 
"Return t if buffer is narrowed."
  (/= 1 (point-min)))

---

Wolfgang Rupprecht 	ARPA: wolfgang@mgm.mit.edu (IP 18.82.0.114)
Independent Consultant  UUCP: {mit-eddie!mgm.mit.edu,mirror!mit-mgm}!wolfgang 
			VOICE: Hey_Wolfgang!_(617)_267-4365

quiroz@cs.rochester.edu (Cesar Quiroz) (01/18/88)

Brandon Allbery wants a function defined to check if the current
buffer is under narrowing.  I take he was thinking of a C primitive
or such, to complement the other narrowing functions.  Wolfgang
Rupprecht suggests this function:
:(defun narowp () 
:"Return t if buffer is narrowed."
:  (/= 1 (point-min)))

This doesn't work, as a little reflection shows.  The narrowing
might permit (= 1 (point-min))!  Think of narrowing to the first
page, for instance.  The original idea (to check if either point-min
or point-max changed) is better.  A possible implementation,
although I suspect Brandon doesn't need this code:

      (defun narrowp ()
        "True if the current buffer is narrowed.
      The value actually returned is a list of the end points of the
      restriction."
        (let ((min (point-min))
              (max (point-max)))
          (if (and (= min 1) (= max (1+ (buffer-size))))
              nil
            (list min max))))

This still fails if the restriction coincides with the whole
buffer... 
-- 
Cesar Augusto  Quiroz Gonzalez
Department of Computer Science     ...allegra!rochester!quiroz
University of Rochester            or
Rochester,  NY 14627               quiroz@cs.rochester.edu

wolfgang@mgm.mit.edu (Wolfgang Rupprecht) (01/18/88)

%$#* news software wouldn't let me cancel my article.  

No checking for point-min + point-max isn't enough to tell if a buffer
is narrowed.  The only real way is probably to add some C code.

This might just do the trick. To editfns.c add:

DEFUN ("narrowp", Fnarrowp, Snarrowp, 0, 0, "",
  "Returns t if buffer is narrowed, else returns nil.")
  ()
{
     return (bf_head_clip > 1 || bf_tail_clip > 0) ? Qt: Qnil;
}

Towards the end of the file, add this extra line to syms_of_editfns:

void
syms_of_editfns ()
{
     [...]
     defsubr (&SNarrowp);		/* add this line only ! */
}

Now recompile + dump. 

(Now to see why nntp-rn screws up and refuses to let me cancel my
previous article.)
---
Wolfgang Rupprecht 	ARPA: wolfgang@mgm.mit.edu (IP 18.82.0.114)
Independent Consultant  UUCP: {mit-eddie!mgm.mit.edu,mirror!mit-mgm}!wolfgang 
			VOICE: Hey_Wolfgang!_(617)_267-4365

wesommer@athena.mit.edu (William E. Sommerfeld) (01/18/88)

In article <138@axcess.UUCP> allbery@axcess.UUCP (Brandon S. Allbery) writes:
>I have a function which wants to narrow the current buffer to a region only if
>it is not already narrowed.  ...  If the buffer is already narrowed, I
>want the function to signal an error.
>
>The only way I have figured out so far to do this is the following piece of
>ugliness:
> (gross use of unwind-protect deleted in the interest of )

Rob Krawitz will probably also respond to this, but...

The other suggestions on how to detect a current restriction makes
sense, but there is there is a special form, save-restriction, which
could be used to cleanly implement constructs similar to what you have
above (which you're probably want to use in the yacc/bison mode):

(save-restriction 
  form1 
  form2 
  ...)

is sort of equivalent to

(let ((old-min (point-min))
      (old-max (point-max)))
  (unwind-protect
      (progn
        form1
        form2
        ...)
    (widen) 
    (narrow-to-region old-min old-max)))

(the difference being that old-min and old-max won't be visible inside
the execution of the internal forms).

Another form related to this which is real useful is save-excursion,
which saves `point' and `mark' on entry, and _always_ restores them
when the form is exited.  The two are sort of like gsave and grestore
in postscript, except that they also interact well with exception
handling.

Look in rmail.el and info.el to see a lot of use of both of these
forms.

					- Bill

allbery@axcess.UUCP (Brandon S. Allbery) (01/24/88)

In article <2336@bloom-beacon.MIT.EDU>, wolfgang@mgm.mit.edu (Wolfgang Rupprecht) writes:
+---------------
| In article <138@axcess.UUCP> allbery@axcess.UUCP (Brandon S. Allbery) writes:
| >I have a function which wants to narrow the current buffer to a region if
| >it is not already narrowed. [...] but why isn't
| >some special function provided ( (narrowp) or something ) to do this?
| 
| (defun narowp () 
| "Return t if buffer is narrowed."
|   (/= 1 (point-min)))
+---------------

Nice try, but if you've seen my Yacc/Bison mode for Emacs, you might notice
that the first thing it does is narrow to the first two sections of a file
(i.e. make the pure C code at the end of the file invisible).  So (point-min)
will return 1 regardless.
-- 
 ___  ________________,	Brandon S. Allbery	       cbosgd \
'   \/  __   __,  __,	aXcess Company		       mandrill|
 __  | /__> <__  <__	6615 Center St. #A1-105		       !ncoast!
/  ` | \__. .__> .__>	Mentor, OH 44060-4101	       necntc  | axcess!allbery
\___/\________________.	Moderator, comp.sources.misc   hoptoad/

allbery@axcess.UUCP (Brandon S. Allbery) (01/24/88)

In article <5959@sol.ARPA>, quiroz@cs.rochester.edu (Cesar Quiroz) writes:
+---------------
| page, for instance.  The original idea (to check if either point-min
| or point-max changed) is better.  A possible implementation,
| although I suspect Brandon doesn't need this code:
> ...
|           (if (and (= min 1) (= max (1+ (buffer-size))))
> ...
| This still fails if the restriction coincides with the whole
| buffer... 
+---------------

As far as I can see, if the narrowed region is the whole buffer the C code
doesn't consider it narrowed.  (At least, the mode line doesn't.)  In any
case, I just want to know if the whole buffer is visible or not, and narrowing
isn't pushed/popped in the C code, so everything works for my purposes.  (I'm
not upset about narrowing not being pushed/popped; looks like a Lisp wrapper
around narrow-to-region and widen would provide that easily if I wanted it.)

Yes, I was thinking of a C primitive.  However, (buffer-size) looks like it
will do the job.  Tell me, is there any more complete way to find out all
these little functions (the partially complete gnu functions manual isn't
really useful and the help stuff virtually requires you to know what you're
looking for beforehand) than to sit down and start reading ALL the Emacs code?

Anyway, thanks for the help.  Someone might want to replace my gross hack to
do this if they saved a copy of the yacc-mode I sent out.
-- 
 ___  ________________,	Brandon S. Allbery	       cbosgd \
'   \/  __   __,  __,	aXcess Company		       mandrill|
 __  | /__> <__  <__	6615 Center St. #A1-105		       !ncoast!
/  ` | \__. .__> .__>	Mentor, OH 44060-4101	       necntc  | axcess!allbery
\___/\________________.	Moderator, comp.sources.misc   hoptoad/