From xemacs-m  Tue May 20 11:50:27 1997
Received: from jagor.srce.hr (hniksic@jagor.srce.hr [161.53.2.130])
	by xemacs.org (8.8.5/8.8.5) with ESMTP id LAA10169
	for <xemacs-beta@xemacs.org>; Tue, 20 May 1997 11:50:26 -0500 (CDT)
Received: (from hniksic@localhost)
          by jagor.srce.hr (8.8.5/8.8.4)
	  id SAA19055; Tue, 20 May 1997 18:50:09 +0200 (MET DST)
To: XEmacs Developers <xemacs-beta@xemacs.org>
Subject: [patch] Arbitrary limit to `recent-keys'
X-Save-Project-Gutenberg: <URL:http://www.promo.net/pg/nl/pgny_nov96.html>
X-Attribution: Hrv
X-Face: Mie8:rOV<\c/~z{s.X4A{!?vY7{drJ([U]0O=W/<W*SMo/Mv:58:*_y~ki>xDi&N7XG
        KV^$k0m3Oe/)'e%3=$PCR&3ITUXH,cK>]bci&<qQ>Ff%x_>1`T(+M2Gg/fgndU%k*ft
        [(7._6e0n-V%|%'[c|q:;}td$#INd+;?!-V=c8Pqf}3J
X-Drdoom-Fodder: passwd security drdoom CERT crash crypt
From: Hrvoje Niksic <hniksic@srce.hr>
Date: 20 May 1997 18:50:08 +0200
Message-ID: <kig67weozpb.fsf@jagor.srce.hr>
Lines: 290
X-Mailer: Gnus v5.4.52/XEmacs 20.2

I've always considered it deeply uncool that `recent-keys' has this
arbitrary limitation of 100 keys.  It would be much better if this
number could be configurable, and if one could specify how many
keypress events `recent-keys' should return.

So, I made a small patch to remedy the situation:

recent-keys (&optional NUMBER)

recent-keys-ring-size ()

set-recent-keys-ring-size (SIZE)

The following statements removes the need to ever use the last
function in your Lisp programs:

(defsetf recent-keys-ring-size set-recent-keys-ring-size)

The Lisp changes are minimal.  Patch follows:

--- src/event-stream.c.orig	Tue May 20 15:14:01 1997
+++ src/event-stream.c	Tue May 20 18:36:22 1997
@@ -188,6 +188,11 @@
 /* File in which we write all commands we read; an lstream */
 static Lisp_Object Vdribble_file;
 
+/* Recent keys ring location; a vector of events or nil-s */
+Lisp_Object Vrecent_keys_ring;
+int recent_keys_ring_size;
+int recent_keys_ring_index;
+
 #ifdef DEBUG_XEMACS
 int debug_emacs_events;
 #endif
@@ -3227,24 +3232,39 @@
    data structure.)
  */
 
-#define RECENT_KEYS_SIZE 100
-Lisp_Object recent_keys_ring;
-int recent_keys_ring_index;
+DEFUN ("recent-keys", Frecent_keys, 0, 1, 0, /*
+Return a vector of recent keyboard or mouse button events read.
+If NUMBER is non-nil, not more than NUMBER events will be returned.
+Change number of events stored using `set-recent-keys-size'.
 
-DEFUN ("recent-keys", Frecent_keys, 0, 0, 0, /*
-Return vector of last 100 or so keyboard or mouse button events read.
 This copies the event objects into a new vector; it is safe to keep and
 modify them.
 */
-       ())
+       (number))
 {
   struct gcpro gcpro1;
   Lisp_Object val = Qnil;
-  int size = XVECTOR (recent_keys_ring)->size;
+  int nwanted;
   int start, nkeys, i, j;
   GCPRO1 (val);
 
-  if (NILP (vector_data (XVECTOR (recent_keys_ring))[recent_keys_ring_index]))
+  if (NILP (number))
+    nwanted = recent_keys_ring_size;
+  else
+    {
+      CHECK_NATNUM (number);
+      nwanted = XINT (number);
+    }
+
+  /* Create the keys ring vector, if none present. */
+  if (NILP (Vrecent_keys_ring))
+    {
+      Vrecent_keys_ring = make_vector (recent_keys_ring_size, Qnil);
+      /* And return nothing in particular. */
+      return make_vector (0, Qnil);
+    }
+
+  if (NILP (vector_data (XVECTOR (Vrecent_keys_ring))[recent_keys_ring_index]))
     /* This means the vector has not yet wrapped */
     {
       nkeys = recent_keys_ring_index;
@@ -3252,26 +3272,102 @@
     }
   else
     {
-      nkeys = size;
-      start = ((recent_keys_ring_index == size) ? 0 : recent_keys_ring_index);
+      nkeys = recent_keys_ring_size;
+      start = ((recent_keys_ring_index == nkeys) ? 0 : recent_keys_ring_index);
+    }
+
+  if (nwanted < nkeys)
+    {
+      start += nkeys - nwanted;
+      if (start >= recent_keys_ring_size)
+	start -= recent_keys_ring_size;
+      nkeys = nwanted;
     }
+  else
+    nwanted = nkeys;
 
-  val = make_vector (nkeys, Qnil);
+  val = make_vector (nwanted, Qnil);
 
   for (i = 0, j = start; i < nkeys; i++)
   {
-    Lisp_Object e = vector_data (XVECTOR (recent_keys_ring))[j];
+    Lisp_Object e = vector_data (XVECTOR (Vrecent_keys_ring))[j];
 
     if (NILP (e))
       abort ();
     vector_data (XVECTOR (val))[i] = Fcopy_event (e, Qnil);
-    if (++j >= size)
+    if (++j >= recent_keys_ring_size)
       j = 0;
   }
   UNGCPRO;
   return (val);
 }
 
+
+DEFUN ("recent-keys-ring-size", Frecent_keys_ring_size, 0, 0, 0, /*
+The maximum number of events `recent-keys' can return.
+*/
+       ())
+{
+  return make_int (recent_keys_ring_size);
+}
+
+DEFUN ("set-recent-keys-ring-size", Fset_recent_keys_ring_size, 1, 1, 0, /*
+Set the maximum number of events to be stored internally.
+*/
+       (size))
+{
+  Lisp_Object new_vector = Qnil;
+  int i, j, nkeys, start, min;
+  struct gcpro gcpro1;
+  GCPRO1 (new_vector);
+
+  CHECK_INT (size);
+  if (XINT (size) <= 0)
+    error ("Recent keys ring size must be positive");
+  if (XINT (size) == recent_keys_ring_size)
+    return size;
+
+  new_vector = make_vector (XINT (size), Qnil);
+
+  if (NILP (Vrecent_keys_ring))
+    {
+      Vrecent_keys_ring = new_vector;
+      return size;
+    }
+
+  if (NILP (vector_data (XVECTOR (Vrecent_keys_ring))[recent_keys_ring_index]))
+    /* This means the vector has not yet wrapped */
+    {
+      nkeys = recent_keys_ring_index;
+      start = 0;
+    }
+  else
+    {
+      nkeys = recent_keys_ring_size;
+      start = ((recent_keys_ring_index == nkeys) ? 0 : recent_keys_ring_index);
+    }
+
+  if (XINT (size) > nkeys)
+    min = nkeys;
+  else
+    min = XINT (size);
+
+  for (i = 0, j = start; i < min; i++)
+    {
+      vector_data (XVECTOR (new_vector))[i]
+	= vector_data (XVECTOR (Vrecent_keys_ring))[j];
+      if (++j >= recent_keys_ring_size)
+	j = 0;
+    }
+  recent_keys_ring_size = XINT (size);
+  recent_keys_ring_index = (i < recent_keys_ring_size) ? i : 0;
+
+  Vrecent_keys_ring = new_vector;
+
+  UNGCPRO;
+  return size;
+}
+
 /* Vthis_command_keys having value Qnil means that the next time
    push_this_command_keys is called, it should start over.
    The times at which the command-keys are reset
@@ -3372,16 +3468,20 @@
 static void
 push_recent_keys (Lisp_Object event)
 {
-  Lisp_Object e
-    = vector_data (XVECTOR (recent_keys_ring)) [recent_keys_ring_index];
+  Lisp_Object e;
+
+  if (NILP (Vrecent_keys_ring))
+    Vrecent_keys_ring = make_vector (recent_keys_ring_size, Qnil);
+
+  e = vector_data (XVECTOR (Vrecent_keys_ring)) [recent_keys_ring_index];
 
   if (NILP (e))
     {
       e = Fmake_event ();
-      vector_data (XVECTOR (recent_keys_ring)) [recent_keys_ring_index] = e;
+      vector_data (XVECTOR (Vrecent_keys_ring)) [recent_keys_ring_index] = e;
     }
   Fcopy_event (event, e);
-  if (++recent_keys_ring_index == XVECTOR (recent_keys_ring)->size)
+  if (++recent_keys_ring_index == recent_keys_ring_size)
     recent_keys_ring_index = 0;
 }
 
@@ -4160,6 +4260,8 @@
   defsymbol (&Qcommand_execute, "command-execute");
 
   DEFSUBR (Frecent_keys);
+  DEFSUBR (Frecent_keys_ring_size);
+  DEFSUBR (Fset_recent_keys_ring_size);
   DEFSUBR (Finput_pending_p);
   DEFSUBR (Fenqueue_eval_event);
   DEFSUBR (Fnext_event);
@@ -4207,8 +4309,9 @@
 
 
   recent_keys_ring_index = 0;
-  recent_keys_ring = make_vector (RECENT_KEYS_SIZE, Qnil);
-  staticpro (&recent_keys_ring);
+  recent_keys_ring_size = 100;
+  Vrecent_keys_ring = Qnil;
+  staticpro (&Vrecent_keys_ring);
 
   Vthis_command_keys = Qnil;
   staticpro (&Vthis_command_keys);
@@ -4471,7 +4574,6 @@
 
   Vdribble_file = Qnil;
   staticpro (&Vdribble_file);
-
 
 #ifdef DEBUG_XEMACS
   DEFVAR_INT ("debug-emacs-events", &debug_emacs_events /*
--- src/events.c.orig	Tue May 20 15:41:11 1997
+++ src/events.c	Tue May 20 15:41:38 1997
@@ -421,9 +421,12 @@
     for (i = 0; i < XVECTOR (Vthis_command_keys)->size; i++)
       if (EQ (event, vector_data (XVECTOR (Vthis_command_keys)) [i]))
 	abort ();
-    for (i = 0; i < XVECTOR (Vrecent_keys_ring)->size; i++)
-      if (EQ (event, vector_data (XVECTOR (Vrecent_keys_ring)) [i]))
-	abort ();
+    if (!NILP (Vrecent_keys_ring))
+      {
+	for (i = 0; i < XVECTOR (Vrecent_keys_ring)->size; i++)
+	  if (EQ (event, vector_data (XVECTOR (Vrecent_keys_ring)) [i]))
+	    abort ();
+      }
   }
 #endif /* 0 */
 
--- lisp/cl/cl-macs.el.orig	Tue May 20 18:12:55 1997
+++ lisp/cl/cl-macs.el	Tue May 20 18:13:39 1997
@@ -1643,6 +1643,7 @@
 (defsetf annotation-data set-annotation-data)
 (defsetf annotation-action set-annotation-action)
 (defsetf annotation-menu set-annotation-menu)
+(defsetf recent-keys-ring-size set-recent-keys-ring-size)
 
 (defsetf getenv setenv t)
 (defsetf get-register set-register)
--- lisp/prim/help.el.orig	Tue May 20 18:40:28 1997
+++ lisp/prim/help.el	Tue May 20 18:40:30 1997
@@ -607,7 +607,7 @@
   (interactive)
   (with-displaying-help-buffer
    (lambda ()
-     (princ (key-description (recent-keys)))
+     (princ (key-description (recent-keys 100)))
      (save-excursion
        (set-buffer standard-output)
        (goto-char (point-min))


-- 
Hrvoje Niksic <hniksic@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
Contrary to popular belief, Unix is user friendly.  
It just happens to be selective about who it makes friends with.

