Subject: Suggestion for a "transient-mark-map" in Emacs (repost)

From: "Kim F. Storm" <[email-masked]>
Date: Thu, 12 Dec 1996 09:47:45 +0100 (MET)

It seems that the following message was lost is transit.

>From: "Kim F. Storm" <[email-masked]>
>To: [email-masked], [email-masked], [email-masked]
>Date: Mon Dec 09 12:13:07 +0000 1996
>Subject: Suggestion for a "transient-mark-map" in Emacs

I have recently started using the pc-select.el style of marking and
selecting text in NT-emacs (on Windows 95), and I actually find it
very convenient.  However, since I switch between emacs and other
Windows 95 applications, I frequently made the mistake of using C-x
and C-c for cut and copy when I'm in emacs.

I tried to find a way to map C-x and C-c to kill-region and
copy-region-as-kill when the region mark was active and keep their
normal prefix functionality otherwise.  However, I couldn't find an
easy way to do it, so instead I came up with the idea of having a
special keymap which was only used when the mark was active and the
transient-mark-mode is selected; I called this the transient-mark-map.

Now, with this new map, it is straightforward to map C-x and C-c as
kill and copy when the region is active.

My experience with this temporary remapping of C-x and C-c is quite
positive;  I do make the mistake of deleting a random region with C-x
from time to time, but it is easy to undo (I also remapped C-z to undo
and C-v to paste).  In any case, this happens much less frequently than
before when I often pressed C-x (in vain) to kill the region.

Below, I supply my diffs to keyboard.c and keymap.c (relative to the
19.34 release).

Mon Dec 09 11:55:00 1996  Kim Storm  <[email-masked]>

	* keymap.c (Vtransient_mark_map): new variable.
	(key-binding): Lookup key in Vtransient_mark_map.
	(syms_of_keymap): Defvar transient-mark-map.

	* keyboard.c (read_key_sequence): Allow more dynamic construction
	of the list of active submaps.	Added Vtransient_mark_map to
	submaps when buffer's mark is active in transient-mark-mode.

*** keymap.org	Tue Jun 11 02:58:18 1996
--- keymap.c	Fri Nov 29 11:01:34 1996
***************
*** 78,83 ****
--- 78,86 ----
  /* Keymap mapping ASCII function key sequences onto their preferred forms.  */
  Lisp_Object Vkey_translation_map;
  
+ /* The keymap used before any other map if transient mark is active */
+ Lisp_Object Vtransient_mark_map;
+ 
  /* A list of all commands given new bindings since a certain time
     when nil was stored here.
     This is used to speed up recomputation of menu key equivalents
***************
*** 1086,1091 ****
--- 1089,1102 ----
      { 
        Lisp_Object local;
  
+       if (! NILP (Vtransient_mark_map)
+ 	  && ! NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
+ 	{
+ 	  value = Flookup_key (Vtransient_mark_map, key, accept_default);
+ 	  if (! NILP (value) && !INTEGERP (value))
+ 	    RETURN_UNGCPRO (value);
+ 	}
+ 	  
        nmaps = current_minor_maps (0, &maps);
        /* Note that all these maps are GCPRO'd
  	 in the places where we found them.  */
***************
*** 2749,2754 ****
--- 2760,2769 ----
    DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map,
      "Local keymap for minibuffer input with completion, for exact match.");
    Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil);
+ 
+   DEFVAR_LISP ("transient-mark-map", &Vtransient_mark_map,
+     "Keymap to use when transient-mark mode is active in the current buffer.");
+   Vtransient_mark_map = Fmake_sparse_keymap (Qnil);
  
    current_global_map = global_map;
  
*** keyboard.org	Fri Aug 23 09:56:00 1996
--- keyboard.c	Fri Nov 29 11:41:14 1996
***************
*** 333,338 ****
--- 333,341 ----
     This one takes precedence over ordinary definitions.  */
  extern Lisp_Object Vkey_translation_map;
  
+ /* The keymap used before any other map if transient mark is active */
+ extern Lisp_Object Vtransient_mark_map;
+ 
  /* Non-nil means deactivate the mark at end of this command.  */
  Lisp_Object Vdeactivate_mark;
  
***************
*** 5770,5775 ****
--- 5773,5779 ----
       keymaps we have allocated space for.  */
    int nmaps;
    int nmaps_allocated = 0;
+   int ndefs_allocated = 0;
  
    /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in
       the current keymaps.  */
***************
*** 5914,5931 ****
       click and we need to switch buffers, we jump back here to rebuild
       the initial keymaps from the current buffer.  */
    {
!     Lisp_Object *maps;
  
      if (!NILP (current_kboard->Voverriding_terminal_local_map)
  	|| !NILP (Voverriding_local_map))
        {
- 	if (3 > nmaps_allocated)
- 	  {
- 	    submaps = (Lisp_Object *) alloca (3 * sizeof (submaps[0]));
- 	    defs    = (Lisp_Object *) alloca (3 * sizeof (defs[0]));
- 	    nmaps_allocated = 3;
- 	  }
- 	nmaps = 0;
  	if (!NILP (current_kboard->Voverriding_terminal_local_map))
  	  submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
  	if (!NILP (Voverriding_local_map))
--- 5918,5939 ----
       click and we need to switch buffers, we jump back here to rebuild
       the initial keymaps from the current buffer.  */
    {
!     if (10 > nmaps_allocated)
!       {
! 	submaps = (Lisp_Object *) alloca (10 * sizeof (submaps[0]));
! 	nmaps_allocated = 10;
!       }
!     nmaps = 0;
! 
!     if (!NILP (Vtransient_mark_map)
! 	&& !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
!       {
! 	submaps[nmaps++] = Vtransient_mark_map;
!       }
  
      if (!NILP (current_kboard->Voverriding_terminal_local_map)
  	|| !NILP (Voverriding_local_map))
        {
  	if (!NILP (current_kboard->Voverriding_terminal_local_map))
  	  submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
  	if (!NILP (Voverriding_local_map))
***************
*** 5933,5946 ****
        }
      else
        {
! 	nmaps = current_minor_maps (0, &maps);
! 	if (nmaps + 2 > nmaps_allocated)
  	  {
! 	    submaps = (Lisp_Object *) alloca ((nmaps+2) * sizeof (submaps[0]));
! 	    defs    = (Lisp_Object *) alloca ((nmaps+2) * sizeof (defs[0]));
! 	    nmaps_allocated = nmaps + 2;
  	  }
! 	bcopy (maps, submaps, nmaps * sizeof (submaps[0]));
  #ifdef USE_TEXT_PROPERTIES
  	submaps[nmaps++] = orig_local_map;
  #else
--- 5941,5959 ----
        }
      else
        {
! 	Lisp_Object *maps;
! 	int mi_maps;
! 	
! 	mi_maps = current_minor_maps (0, &maps);
! 	if (mi_maps + nmaps + 2 > nmaps_allocated)
  	  {
! 	    Lisp_Object *omaps = submaps;
! 	    nmaps_allocated = mi_maps + nmaps + 2;
! 	    submaps = (Lisp_Object *) alloca (nmaps_allocated * sizeof (submaps[0]));
! 	    bcopy (omaps, submaps, nmaps * sizeof (submaps[0]));
  	  }
! 	bcopy (maps, submaps + nmaps, mi_maps * sizeof (submaps[0]));
! 	nmaps += mi_maps;
  #ifdef USE_TEXT_PROPERTIES
  	submaps[nmaps++] = orig_local_map;
  #else
***************
*** 5949,5954 ****
--- 5962,5973 ----
        }
      submaps[nmaps++] = current_global_map;
    }
+ 
+   if (ndefs_allocated < nmaps_allocated)
+     {
+       ndefs_allocated = nmaps_allocated;
+       defs    = (Lisp_Object *) alloca (ndefs_allocated * sizeof (defs[0]));
+     }
  
    /* Find an accurate initial value for first_binding.  */
    for (first_binding = 0; first_binding < nmaps; first_binding++)

--
Kim F. Storm, Olicom A/S <[email-masked]>

---

From: Andrew Innes <[email-masked]>
Date: Thu, 12 Dec 1996 10:58:14 GMT

>It seems that the following message was lost is transit.

I received the first copy, but didn't have any real comment to make.

>transient-mark-mode is selected; I called this the transient-mark-map.

This sounds okay to me, but then I don't use transient-mark-mode.  I
gather your change wouldn't affect me in that case, so that's okay.

Are you proposing to alter pc-select.el as well to define C-x, C-v, C-c
and C-z as standard in transient-mark-map, perhaps as a configurable
option?

AndrewI

---

From: "Kim F. Storm" <[email-masked]>
Date: Thu, 12 Dec 1996 16:12:43 +0100 (MET)

Date: Thu, 12 Dec 1996 10:58:14 GMT
   From: Andrew Innes <[email-masked]>

And since the transient-mark-map is empty by default, it shouldn't
affect anybody else for that matter.

Yes, although C-z and C-v must be generally remapped in global-map
since they are not linked to the active region as such.

I have made some steps to improve on pc-selection-mode and
delete-selection-mode, but I haven't had the time to stream-line the
code. In any case, my changes to pc-select.el are not mandatory to
take advantage of the transient-mark-map, provided you remap the keys
yourself.

---

From: "Kim F. Storm" <[email-masked]>
Date: Fri, 13 Dec 1996 10:59:01 +0100 (MET)

Date: Thu, 12 Dec 1996 20:29:55 -0500
   From: Richard Stallman <[email-masked]>
   Cc: [email-masked], [email-masked]

   I do not mind if you remap C-x, C-v, C-c and C-z,
   but I do not want to install such a change in Emacs.
   Sorry.

Maybe I didn't make myself clear, but I didn't ask you to remap
anything, I just asked you to make it possible for me to do it. As it
is now, I just cannot see any simple way to have C-x and C-c work on
the region the way it does in all other applications I use on this
system (Windows95).

I cannot imagine how the proposed change (transient-mark-map) can
harm anyone if they don't use it.  The changes are small and in my
opinion trivial.  I honestly fail to see the reason why you object to
include these changes.

For the record, I've been maintaining emacs at this company for the
last 5 years, and before that at other sites for another 5 years, and
have always advocated its use (over the official company standard
which is the "brief" editor, its successor "crisp", or the various MS
editors). The main reason of course because it is a superb editor,
but also because it has two major features none of the other editors
have: 
- you have access to the source code, and if something doesn't work
  (the way you want it to), you fix it, and
- you share the work you do to improve emacs - and the work a lot of
  other users have done - to achieve an even more superior product.

Of course, I can understand that you cannot simply put each and every
proposal into the official code, but given the amount and varity of
features that is already in there, I find it hard to distinguish what
is acceptable and what is not, and why my proposal fall into the last
category.

So I'm sorry too.

---

From: Richard Stallman <[email-masked]>
Date: Thu, 12 Dec 1996 20:29:55 -0500