Subject: lib/14067: libedit suggestion - new el_set() operation
To: None <gnats-bugs@gnats.netbsd.org>
From: None <anthony.mallet@ficus.yi.org>
List: netbsd-bugs
Date: 09/26/2001 02:08:26
>Number:         14067
>Category:       lib
>Synopsis:       libedit suggestion - new el_set() operation
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 25 17:09:02 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Anthony Mallet
>Release:        1.5Y
>Organization:

>Environment:
	
System: NetBSD ficus 1.5Y NetBSD 1.5Y (FICUS) #7: Sun Sep 23 01:15:49 CEST 2001 toto@ficus:/home/src/netbsd-current/sys/arch/i386/compile/FICUS i386
Architecture: i386
Machine: i386
>Description:
I need to add a new feature in libedit because:
i) I have to write an interactive program with line editing
   functionalities that must also process events in the background (when
   no input is available).
ii) The builtin "read_char()" function (in read.c) is declared "private"
    and cannot be replaced easly. Furthermore this function insist on
    reconfiguring the tty in blocking mode which is not what I want.

>How-To-Repeat:
Write some code which calls el_gets() or el_getc() to get user input.
Try to process events when no input is available, without relying on some
polling method (SIGALARM or so...).

>Fix:
The enclosed patch (see below) match my needs. It's of course only a
suggestion; I'm open to the discussion :)
This patch adds a new command for el_set() and el_get():
	el_set(EditLine *el, EL_GETCFN, int (*f)(EditLine *, char *));
	el_get(EditLine *el, EL_GETCFN, int (**f)(EditLine *, char *));
The first line sets a new read_char function to be used by the two
functions el_gets and el_getc. A predefined constant EL_BUILTIN_GETCFN
refers the default builtin function.
The second line returns the current read_char function (or
EL_BUILTIN_GETCFN if the default function is used).

Index: editline.3
===================================================================
RCS file: /usr/local/cvs_hilare/lib/libedit/dist/editline.3,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 editline.3
--- editline.3	25 Sep 2001 16:03:16 -0000	1.1.1.1
+++ editline.3	25 Sep 2001 23:46:38 -0000
@@ -368,6 +368,17 @@
 (using
 .Fn el_get )
 to determine if editing should be enabled or not.
+.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)"
+Define the character reading function as
+.Fa f ,
+which is to return the number of characters read and store them in
+.Fa c .
+This function is called internally by
+.Fn el_gets
+and
+.Fn el_getc .
+The builtin function can be set or restored with the special function
+name ``EL_BUILTIN_GETCFN''.
 .El
 .It Fn el_get
 Get
@@ -399,6 +410,9 @@
 above).
 .It Dv EL_EDITMODE, Fa "int *"
 Return non-zero if editing is enabled.
+.It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)"
+Return a pointer to the function that read characters, which is equal to
+``EL_BUILTIN_GETCFN'' in the case of the default builtin function.
 .El
 .It Fn el_source
 Initialise
Index: el.c
===================================================================
RCS file: /usr/local/cvs_hilare/lib/libedit/dist/el.c,v
retrieving revision 1.2
diff -u -r1.2 el.c
--- el.c	25 Sep 2001 16:08:09 -0000	1.2
+++ el.c	25 Sep 2001 23:46:39 -0000
@@ -92,6 +92,7 @@
 	(void) hist_init(el);
 	(void) prompt_init(el);
 	(void) sig_init(el);
+	(void) read_init(el);
 
 	return (el);
 }
@@ -244,6 +245,13 @@
 		rv = 0;
 		break;
 
+	case EL_GETCFN:
+	{
+		el_rfunc_t rc = va_arg(va, el_rfunc_t);
+		rv = el_read_setfn(el, rc);
+		break;
+	}
+
 	default:
 		rv = -1;
 	}
@@ -353,6 +361,11 @@
 		}
 		break;
 #endif /* XXX */
+
+	case EL_GETCFN:
+		*((el_rfunc_t *)ret) = el_read_getfn(el);
+		rv = 0;
+		break;
 
 	default:
 		rv = -1;
Index: el.h
===================================================================
RCS file: /usr/local/cvs_hilare/lib/libedit/dist/el.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 el.h
--- el.h	25 Sep 2001 16:03:17 -0000	1.1.1.1
+++ el.h	25 Sep 2001 23:46:39 -0000
@@ -106,6 +106,7 @@
 #include "parse.h"
 #include "sig.h"
 #include "help.h"
+#include "read.h"
 
 struct editline {
 	char		 *el_prog;	/* the program name		*/
@@ -129,6 +130,7 @@
 	el_history_t	  el_history;	/* History stuff		*/
 	el_search_t	  el_search;	/* Search stuff			*/
 	el_signal_t	  el_signal;	/* Signal handling stuff	*/
+	el_read_t	  el_read;	/* Character reading stuff	*/
 };
 
 protected int	el_editmode(EditLine *, int, char **);
Index: histedit.h
===================================================================
RCS file: /usr/local/cvs_hilare/lib/libedit/dist/histedit.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 histedit.h
--- histedit.h	25 Sep 2001 16:03:17 -0000	1.1.1.1
+++ histedit.h	25 Sep 2001 23:46:39 -0000
@@ -126,6 +126,9 @@
 #define	EL_HIST		10	/* , hist_fun_t, const char *);	*/
 #define	EL_EDITMODE	11	/* , int);			*/
 #define	EL_RPROMPT	12	/* , el_pfunc_t);		*/
+#define	EL_GETCFN	13	/* , el_rfunc_t);		*/
+
+#define EL_BUILTIN_GETCFN	(NULL)
 
 /*
  * Source named file or $PWD/.editrc or $HOME/.editrc
Index: read.c
===================================================================
RCS file: /usr/local/cvs_hilare/lib/libedit/dist/read.c,v
retrieving revision 1.2
diff -u -r1.2 read.c
--- read.c	25 Sep 2001 16:08:11 -0000	1.2
+++ read.c	25 Sep 2001 23:46:40 -0000
@@ -58,8 +58,38 @@
 
 private int	read__fixio(int, int);
 private int	read_preread(EditLine *);
-private int	read_getcmd(EditLine *, el_action_t *, char *);
 private int	read_char(EditLine *, char *);
+private int	read_getcmd(EditLine *, el_action_t *, char *);
+
+/* read_init():
+ *	Initialize the read stuff
+ */
+protected int
+read_init(EditLine *el)
+{
+   /* builtin read_char */
+   el->el_read.read_char = read_char;
+
+   return 0;
+}
+
+protected int
+el_read_setfn(EditLine *el, el_rfunc_t rc)
+{
+   if (rc == EL_BUILTIN_GETCFN)
+      el->el_read.read_char = read_char;
+   else
+      el->el_read.read_char = rc;
+
+   return 0;
+}
+
+protected el_rfunc_t
+el_read_getfn(EditLine *el)
+{
+   return (el->el_read.read_char == read_char)?
+	EL_BUILTIN_GETCFN : el->el_read.read_char;
+}
 
 #ifdef DEBUG_EDIT
 private void
@@ -79,7 +109,6 @@
 }
 #endif /* DEBUG_EDIT */
 
-
 /* read__fixio():
  *	Try to recover from a read error
  */
@@ -309,7 +338,7 @@
 #ifdef DEBUG_READ
 	(void) fprintf(el->el_errfile, "Reading a character\n");
 #endif /* DEBUG_READ */
-	num_read = read_char(el, cp);
+	num_read = (el->el_read.read_char)(el, cp);
 #ifdef DEBUG_READ
 	(void) fprintf(el->el_errfile, "Got it %c\n", *cp);
 #endif /* DEBUG_READ */
@@ -335,7 +364,7 @@
 		char *cp = el->el_line.buffer;
 		size_t idx;
 
-		while (read_char(el, cp) == 1) {
+		while ((el->el_read.read_char)(el, cp) == 1) {
 			/* make sure there is space for next character */
 			if (cp + 1 >= el->el_line.limit) {
 				idx = (cp - el->el_line.buffer);
@@ -380,7 +409,7 @@
 
 		term__flush();
 
-		while (read_char(el, cp) == 1) {
+		while ((el->el_read.read_char)(el, cp) == 1) {
 			/* make sure there is space next character */
 			if (cp + 1 >= el->el_line.limit) {
 				idx = (cp - el->el_line.buffer);
Index: read.h
===================================================================
RCS file: read.h
diff -N read.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ read.h	25 Sep 2001 23:46:40 -0000
@@ -0,0 +1,23 @@
+/*	$NetBSD: $	*/
+
+/*-
+ * Some copyright information...
+ */
+
+/*
+ * el.read.h: Character reading functions
+ */
+#ifndef _h_el_read
+#define	_h_el_read
+
+typedef int (*el_rfunc_t)(EditLine *, char *);
+
+typedef struct el_read_t {
+   el_rfunc_t	read_char;	/* Function to read a character */
+} el_read_t;
+ 
+protected int		read_init(EditLine *);
+protected int		el_read_setfn(EditLine *, el_rfunc_t);
+protected el_rfunc_t	el_read_getfn(EditLine *);
+
+#endif /* _h_el_read */
>Release-Note:
>Audit-Trail:
>Unformatted: