git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@2170 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
		
			
				
	
	
		
			742 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			742 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*  $Id: edit.c,v 1.1 2008-03-27 00:41:33 vsc Exp $
 | |
| 
 | |
|     Part of SWI-Prolog
 | |
| 
 | |
|     Author:        Jan Wielemaker
 | |
|     E-mail:        jan@swi.psy.uva.nl
 | |
|     WWW:           http://www.swi-prolog.org
 | |
|     Copyright (C): 1985-2002, University of Amsterdam
 | |
| 
 | |
|     This library is free software; you can redistribute it and/or
 | |
|     modify it under the terms of the GNU Lesser General Public
 | |
|     License as published by the Free Software Foundation; either
 | |
|     version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|     This library is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|     Lesser General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU Lesser General Public
 | |
|     License along with this library; if not, write to the Free Software
 | |
|     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| */
 | |
| 
 | |
| #define _MAKE_DLL 1
 | |
| #undef _export
 | |
| #include <windows.h>
 | |
| #include <tchar.h>
 | |
| #include "console.h"
 | |
| #include "console_i.h"
 | |
| #include "common.h"
 | |
| #include <memory.h>
 | |
| #include <string.h>
 | |
| #include <ctype.h>
 | |
| 
 | |
| #ifndef EOF
 | |
| #define EOF -1
 | |
| #endif
 | |
| 
 | |
| typedef void (*function)(Line ln, int chr);	/* edit-function */
 | |
| 
 | |
| static function dispatch_table[256];	/* general dispatch-table */
 | |
| static function dispatch_meta[256];	/* ESC-char dispatch */
 | |
| static RlcCompleteFunc _rlc_complete_function = rlc_complete_file_function;
 | |
| 
 | |
| static void	init_line_package(RlcData b);
 | |
| static void	bind_actions(void);
 | |
| 
 | |
| #ifndef min
 | |
| #define min(a, b) ((a) < (b) ? (a) : (b))
 | |
| #define max(a, b) ((a) > (b) ? (a) : (b))
 | |
| #endif
 | |
| 
 | |
| #ifndef TRUE
 | |
| #define TRUE 1
 | |
| #define FALSE 0
 | |
| #endif
 | |
| 
 | |
| #ifndef EOS
 | |
| #define EOS 0
 | |
| #endif
 | |
| 
 | |
| #ifndef ESC
 | |
| #define ESC 27
 | |
| #endif
 | |
| 
 | |
| #define COMPLETE_NEWLINE 1
 | |
| #define COMPLETE_EOF	 2
 | |
| 
 | |
| #define ctrl(c)	((c) - '@')
 | |
| #define META_OFFSET 128
 | |
| #define meta(c) ((c) + META_OFFSET)
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	       BUFFER		*
 | |
| 		 *******************************/
 | |
| 
 | |
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | |
| make_room(Line, int room)
 | |
| 	Make n-characters space after the point.
 | |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 | |
| 
 | |
| static void
 | |
| make_room(Line ln, size_t room)
 | |
| { while ( ln->size + room + 1 > ln->allocated )
 | |
|   { if ( !ln->data )
 | |
|     { ln->data = rlc_malloc(256 * sizeof(TCHAR));
 | |
|       ln->allocated = 256;
 | |
|     } else
 | |
|     { ln->allocated *= 2;
 | |
|       ln->data = rlc_realloc(ln->data, ln->allocated * sizeof(TCHAR));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   memmove(&ln->data[ln->point + room], &ln->data[ln->point],
 | |
| 	  (ln->size - ln->point)*sizeof(TCHAR));
 | |
|   ln->size += room;
 | |
|   if ( room > 0 )
 | |
|     ln->change_start = min(ln->change_start, ln->point);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| set_line(Line ln, const TCHAR *s)
 | |
| { size_t len = _tcslen(s);
 | |
| 
 | |
|   ln->size = ln->point = 0;
 | |
|   make_room(ln, len);
 | |
|   _tcsncpy(ln->data, s, len);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| terminate(Line ln)
 | |
| { if ( !ln->data )
 | |
|   { ln->data = rlc_malloc(sizeof(TCHAR));
 | |
|     ln->allocated = 1;
 | |
|   }
 | |
|   ln->data[ln->size] = EOS;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| delete(Line ln, size_t from, size_t len)
 | |
| { if ( from < 0 || from > ln->size || len < 0 || from + len > ln->size )
 | |
|     return;
 | |
| 
 | |
|   _tcsncpy(&ln->data[from], &ln->data[from+len], ln->size - (from+len));
 | |
|   ln->size -= len;
 | |
| } 
 | |
| 
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	     POSITIONING	*
 | |
| 		 *******************************/
 | |
| 
 | |
| static size_t
 | |
| back_word(Line ln, size_t from)
 | |
| { from = min(from, ln->size);
 | |
|   from = max(0, from);
 | |
| 
 | |
|   if ( ln->data )
 | |
|   { while(!rlc_is_word_char(ln->data[from-1]) && from > 0 )
 | |
|       from--;
 | |
|     while(rlc_is_word_char(ln->data[from-1]) && from > 0 )
 | |
|       from--;
 | |
|   }
 | |
| 
 | |
|   return from;
 | |
| }
 | |
| 
 | |
| static size_t
 | |
| forw_word(Line ln, size_t from)
 | |
| { from = min(from, ln->size);
 | |
|   from = max(0, from);
 | |
| 
 | |
|   if ( ln->data )
 | |
|   { while(!rlc_is_word_char(ln->data[from]) && from < ln->size )
 | |
|       from++;
 | |
|     while(rlc_is_word_char(ln->data[from]) && from < ln->size )
 | |
|       from++;
 | |
|   }
 | |
| 
 | |
|   return from;
 | |
| }
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *       EDITING FUNCTIONS	*
 | |
| 		 *******************************/
 | |
| 
 | |
| static __inline void
 | |
| changed(Line ln, size_t from)
 | |
| { ln->change_start = min(ln->change_start, from);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| insert_self(Line ln, int chr)
 | |
| { make_room(ln, 1);
 | |
|   ln->data[ln->point++] = chr;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| backward_delete_character(Line ln, int chr)
 | |
| { if ( ln->point > 0 )
 | |
|   { memmove(&ln->data[ln->point-1], &ln->data[ln->point],
 | |
| 	    (ln->size - ln->point)*sizeof(TCHAR));
 | |
|     ln->size--;
 | |
|     ln->point--;
 | |
|   }
 | |
| 
 | |
|   changed(ln, ln->point);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| delete_character(Line ln, int chr)
 | |
| { if ( ln->point < ln->size )
 | |
|   { ln->point++;
 | |
|     backward_delete_character(ln, chr);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| backward_character(Line ln, int chr)
 | |
| { if ( ln->point > 0 )
 | |
|     ln->point--;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| forward_character(Line ln, int chr)
 | |
| { if ( ln->point < ln->size )
 | |
|     ln->point++;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| backward_word(Line ln, int chr)
 | |
| { ln->point = back_word(ln, ln->point);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| forward_word(Line ln, int chr)
 | |
| { ln->point = forw_word(ln, ln->point);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| backward_delete_word(Line ln, int chr)
 | |
| { size_t from = back_word(ln, ln->point);
 | |
|   
 | |
|   memmove(&ln->data[from], &ln->data[ln->point],
 | |
| 	  (ln->size - ln->point)*sizeof(TCHAR));
 | |
|   ln->size -= ln->point - from;
 | |
|   ln->point = from;
 | |
|   changed(ln, from);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| forward_delete_word(Line ln, int chr)
 | |
| { size_t to = forw_word(ln, ln->point);
 | |
|   
 | |
|   memmove(&ln->data[ln->point], &ln->data[to], (ln->size - to)*sizeof(TCHAR));
 | |
|   ln->size -= to - ln->point;
 | |
|   changed(ln, ln->point);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| transpose_chars(Line ln, int chr)
 | |
| { if ( ln->point > 0 && ln->point < ln->size )
 | |
|   { int c0 = ln->data[ln->point-1];
 | |
|     ln->data[ln->point-1] = ln->data[ln->point];
 | |
|     ln->data[ln->point] = c0;
 | |
|     changed(ln, ln->point-1);
 | |
|   } 
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| start_of_line(Line ln, int chr)
 | |
| { ln->point = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| end_of_line(Line ln, int chr)
 | |
| { ln->point = ln->size;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| kill_line(Line ln, int chr)
 | |
| { ln->size = ln->point;
 | |
|   changed(ln, ln->size);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| empty_line(Line ln, int chr)
 | |
| { ln->size = ln->point = 0;
 | |
|   changed(ln, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| enter(Line ln, int chr)
 | |
| { ln->point = ln->size;
 | |
| #ifdef DOS_CRNL  
 | |
|   make_room(ln, 2);
 | |
|   ln->data[ln->point++] = '\r';
 | |
|   ln->data[ln->point++] = '\n';
 | |
| #else
 | |
|   make_room(ln, 1);
 | |
|   ln->data[ln->point++] = '\n';
 | |
| #endif
 | |
|   terminate(ln);
 | |
|   ln->complete = COMPLETE_NEWLINE;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| eof(Line ln, int chr)
 | |
| { ln->point = ln->size;
 | |
|   terminate(ln);
 | |
|   ln->complete = COMPLETE_EOF;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| delete_character_or_eof(Line ln, int chr)
 | |
| { if ( ln->size == 0 )
 | |
|   { ln->point = ln->size;
 | |
|     terminate(ln);
 | |
|     ln->complete = COMPLETE_EOF;
 | |
|   } else
 | |
|     delete_character(ln, chr);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| undefined(Line ln, int chr)
 | |
| { 
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| interrupt(Line ln, int chr)
 | |
| { raise(SIGINT);
 | |
| }
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *		HISTORY		*
 | |
| 		 *******************************/
 | |
| 
 | |
| static void
 | |
| add_history(rlc_console c, const TCHAR *data)
 | |
| { const TCHAR *s = data;
 | |
| 
 | |
|   while(*s && *s <= ' ')
 | |
|     s++;
 | |
| 
 | |
|   if ( *s )
 | |
|     rlc_add_history(c, s);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| backward_history(Line ln, int chr)
 | |
| { const TCHAR *h;
 | |
| 
 | |
|   if ( rlc_at_head_history(ln->console) && ln->size > 0 )
 | |
|   { terminate(ln);
 | |
|     add_history(ln->console, ln->data);
 | |
|   }
 | |
| 
 | |
|   if ( (h = rlc_bwd_history(ln->console)) )
 | |
|   { set_line(ln, h);
 | |
|     ln->point = ln->size;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| forward_history(Line ln, int chr)
 | |
| { if ( !rlc_at_head_history(ln->console) )
 | |
|   { const TCHAR *h = rlc_fwd_history(ln->console);
 | |
| 
 | |
|     if ( h )
 | |
|     { set_line(ln, h);
 | |
|       ln->point = ln->size;
 | |
|     }
 | |
|   } else
 | |
|     empty_line(ln, chr);
 | |
| }
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	      COMPLETE		*
 | |
| 		 *******************************/
 | |
| 
 | |
| RlcCompleteFunc
 | |
| rlc_complete_hook(RlcCompleteFunc new)
 | |
| { RlcCompleteFunc old = _rlc_complete_function;
 | |
| 
 | |
|   _rlc_complete_function = new;
 | |
| 
 | |
|   return old;
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| common(const TCHAR *s1, const TCHAR *s2, int insensitive)
 | |
| { int n = 0;
 | |
| 
 | |
|   if ( !insensitive )
 | |
|   { while(*s1 && *s1 == *s2)
 | |
|     { s1++, s2++;
 | |
|       n++;
 | |
|     }
 | |
|     return n;
 | |
|   } else
 | |
|   { while(*s1)
 | |
|     { if ( _totlower(*s1) == _totlower(*s2) )
 | |
|       { s1++, s2++;
 | |
| 	n++;
 | |
|       } else
 | |
| 	break;
 | |
|     }
 | |
|     return n;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| complete(Line ln, int chr)
 | |
| { if ( _rlc_complete_function )
 | |
|   { rlc_complete_data dbuf;
 | |
|     RlcCompleteData data = &dbuf;
 | |
| 
 | |
|     memset(data, 0, sizeof(dbuf));
 | |
|     data->line      = ln;
 | |
|     data->call_type = COMPLETE_INIT;
 | |
| 
 | |
|     if ( (*_rlc_complete_function)(data) )
 | |
|     { TCHAR match[COMPLETE_MAX_WORD_LEN];
 | |
|       int nmatches = 1;
 | |
|       size_t ncommon = _tcslen(data->candidate);
 | |
|       size_t patlen = ln->point - data->replace_from;
 | |
| 
 | |
|       _tcscpy(match, data->candidate);
 | |
| 
 | |
|       data->call_type = COMPLETE_ENUMERATE;
 | |
|       while( (*data->function)(data) )
 | |
|       { ncommon = common(match, data->candidate, data->case_insensitive);
 | |
| 	match[ncommon] = EOS;
 | |
| 	nmatches++;
 | |
|       }
 | |
|       data->call_type = COMPLETE_CLOSE;
 | |
|       (*data->function)(data);
 | |
|        
 | |
|       delete(ln, data->replace_from, patlen);
 | |
|       ln->point = data->replace_from;
 | |
|       make_room(ln, ncommon);
 | |
|       _tcsncpy(&ln->data[data->replace_from], match, ncommon);
 | |
|       ln->point += ncommon;
 | |
|       if ( nmatches == 1 && data->quote )
 | |
| 	insert_self(ln, data->quote);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| #define MAX_LIST_COMPLETIONS 256
 | |
| 
 | |
| static void
 | |
| list_completions(Line ln, int chr)
 | |
| { if ( _rlc_complete_function )
 | |
|   { rlc_complete_data dbuf;
 | |
|     RlcCompleteData data = &dbuf;
 | |
| 
 | |
|     memset(data, 0, sizeof(dbuf));
 | |
|     data->line      = ln;
 | |
|     data->call_type = COMPLETE_INIT;
 | |
| 
 | |
|     if ( (*_rlc_complete_function)(data) )
 | |
|     { TCHAR *buf[COMPLETE_MAX_MATCHES];
 | |
|       int n, nmatches = 0;
 | |
|       size_t len = _tcslen(data->candidate) + 1;
 | |
|       size_t longest = len;
 | |
|       size_t cols;
 | |
| 
 | |
|       buf[nmatches] = rlc_malloc(len*sizeof(TCHAR));
 | |
|       _tcsncpy(buf[nmatches], data->candidate, len);
 | |
|       nmatches++;
 | |
| 
 | |
|       data->call_type = COMPLETE_ENUMERATE;
 | |
|       while( (*data->function)(data) )
 | |
|       { len = _tcslen(data->candidate) + 1;
 | |
| 	buf[nmatches] = rlc_malloc(len*sizeof(TCHAR));
 | |
| 	_tcsncpy(buf[nmatches], data->candidate, len);
 | |
| 	nmatches++;
 | |
| 	longest = max(longest, len);
 | |
| 
 | |
| 	if ( nmatches > COMPLETE_MAX_MATCHES )
 | |
| 	{ TCHAR *msg = _T("\r\n! Too many matches\r\n");
 | |
| 	  
 | |
| 	  while(*msg)
 | |
| 	    rlc_putchar(ln->console, *msg++);
 | |
| 	  ln->reprompt = TRUE;
 | |
| 	  data->call_type = COMPLETE_CLOSE;
 | |
| 	  (*data->function)(data);
 | |
| 	  return;
 | |
| 	}
 | |
|       }
 | |
|       data->call_type = COMPLETE_CLOSE;
 | |
|       (*data->function)(data);
 | |
| 
 | |
|       cols = ScreenCols(ln->console) / longest;
 | |
|       rlc_putchar(ln->console, '\r');
 | |
|       rlc_putchar(ln->console, '\n');
 | |
| 
 | |
|       for(n=0; n<nmatches; )
 | |
|       { TCHAR *s = buf[n];
 | |
| 	len = 0;
 | |
| 
 | |
| 	while(*s)
 | |
| 	{ len++;
 | |
| 	  rlc_putchar(ln->console, *s++);
 | |
| 	}
 | |
| 	
 | |
| 	rlc_free(buf[n++]);
 | |
| 
 | |
| 	if ( n % cols == 0 )
 | |
| 	{ rlc_putchar(ln->console, '\r');
 | |
| 	  rlc_putchar(ln->console, '\n');
 | |
| 	} else
 | |
| 	{ while( len++ < longest )
 | |
| 	  rlc_putchar(ln->console, ' ');
 | |
| 	}
 | |
|       }
 | |
|       if ( nmatches % cols != 0 )
 | |
|       { rlc_putchar(ln->console, '\r');
 | |
| 	rlc_putchar(ln->console, '\n');
 | |
|       }
 | |
| 
 | |
|       ln->reprompt = TRUE;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	      REPAINT		*
 | |
| 		 *******************************/
 | |
| 
 | |
| static void
 | |
| output(rlc_console b, TCHAR *s, size_t len)
 | |
| { while(len-- > 0)
 | |
|   { if ( *s == '\n' )
 | |
|       rlc_putchar(b, '\r');
 | |
|     rlc_putchar(b, *s++);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| update_display(Line ln)
 | |
| { if ( ln->reprompt )
 | |
|   { const TCHAR *prompt = rlc_prompt(ln->console, NULL);
 | |
|     const TCHAR *s = prompt;
 | |
|       
 | |
|     rlc_putchar(ln->console, '\r');
 | |
|     while(*s)
 | |
|       rlc_putchar(ln->console, *s++);
 | |
| 
 | |
|     rlc_get_mark(ln->console, &ln->origin);
 | |
| 
 | |
|     ln->change_start = 0;
 | |
|     ln->reprompt = FALSE;
 | |
|   }
 | |
| 
 | |
|   rlc_goto_mark(ln->console, &ln->origin, ln->data, ln->change_start);
 | |
|   output(ln->console,
 | |
| 	 &ln->data[ln->change_start], ln->size - ln->change_start);
 | |
|   rlc_erase_from_caret(ln->console);
 | |
|   rlc_goto_mark(ln->console, &ln->origin, ln->data, ln->point);
 | |
|   rlc_update(ln->console);
 | |
| 
 | |
|   ln->change_start = ln->size;
 | |
| }
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	     TOPLEVEL		*
 | |
| 		 *******************************/
 | |
| 
 | |
| TCHAR *
 | |
| read_line(rlc_console b)
 | |
| { line ln;
 | |
| 
 | |
|   init_line_package(b);
 | |
| 
 | |
|   memset(&ln, 0, sizeof(line));
 | |
|   ln.console = b;
 | |
|   rlc_get_mark(b, &ln.origin);
 | |
| 
 | |
|   while(!ln.complete)
 | |
|   { int c;
 | |
|     rlc_mark m0, m1;
 | |
|     function func;
 | |
| 
 | |
|     rlc_get_mark(b, &m0);
 | |
|     if ( (c = getch(b)) == IMODE_SWITCH_CHAR )
 | |
|       return RL_CANCELED_CHARP;
 | |
| 
 | |
|     if ( c == EOF )
 | |
|     { eof(&ln, c);
 | |
|       update_display(&ln);
 | |
|       break;
 | |
|     } else if ( c == ESC )
 | |
|     { if ( (c = getch(b)) == IMODE_SWITCH_CHAR )
 | |
| 	return RL_CANCELED_CHARP;
 | |
|       if ( c > 256 )
 | |
| 	func = undefined;
 | |
|       else
 | |
| 	func = dispatch_meta[c&0xff];
 | |
|     } else
 | |
|     { if ( c >= 256 )
 | |
| 	func = insert_self;
 | |
|       else
 | |
| 	func = dispatch_table[c&0xff];
 | |
|     }
 | |
| 
 | |
|     rlc_get_mark(b, &m1);
 | |
| 
 | |
|     (*func)(&ln, c);
 | |
|     if ( m0.mark_x != m1.mark_x || m0.mark_y != m1.mark_y )
 | |
|       ln.reprompt = TRUE;
 | |
|     update_display(&ln);
 | |
|   }
 | |
|   rlc_clearprompt(b);
 | |
| 
 | |
|   add_history(b, ln.data);
 | |
| 
 | |
|   return ln.data;
 | |
| }
 | |
| 
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	     DISPATCH		*
 | |
| 		 *******************************/
 | |
| 
 | |
| static void
 | |
| init_dispatch_table()
 | |
| { static int done;
 | |
| 
 | |
|   if ( !done )
 | |
|   { int n;
 | |
| 
 | |
|     for(n=0; n<32; n++)
 | |
|       dispatch_table[n] = undefined;
 | |
|     for(n=32; n<256; n++)
 | |
|       dispatch_table[n] = insert_self;
 | |
|     for(n=0; n<256; n++)
 | |
|       dispatch_meta[n] = undefined;
 | |
|       
 | |
|     bind_actions();
 | |
| 
 | |
|     done = TRUE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| init_line_package(RlcData b)
 | |
| { init_dispatch_table();
 | |
|   rlc_init_history(b, 50);
 | |
| }
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	       BIND		*
 | |
| 		 *******************************/
 | |
| 
 | |
| typedef struct _action
 | |
| { char		*name;
 | |
|   function	 function;
 | |
|   unsigned char  keys[4];
 | |
| } action, *Action;
 | |
| 
 | |
| #define ACTION(n, f, k) { n, f, k }
 | |
| 
 | |
| static action actions[] = {
 | |
|   ACTION("insert_self",		      insert_self,		 ""),
 | |
|   ACTION("backward_delete_character", backward_delete_character, "\b"),
 | |
|   ACTION("complete",		      complete,			 "\t"),
 | |
|   ACTION("enter",		      enter, 			 "\r\n"),
 | |
|   ACTION("start_of_line",	      start_of_line,		 {ctrl('A')}),
 | |
|   ACTION("backward_character",	      backward_character,        {ctrl('B')}),
 | |
|   ACTION("interrupt",		      interrupt,		 {ctrl('C')}),
 | |
|   ACTION("end_of_line",		      end_of_line,		 {ctrl('E')}),
 | |
|   ACTION("forward_character",	      forward_character,	 {ctrl('F')}),
 | |
|   ACTION("transpose_chars",	      transpose_chars,		 {ctrl('T')}),
 | |
|   ACTION("kill_line",		      kill_line,		 {ctrl('K')}),
 | |
|   ACTION("backward_history",	      backward_history,		 {ctrl('P')}),
 | |
|   ACTION("forward_history",	      forward_history,		 {ctrl('N')}),
 | |
|   ACTION("empty_line",		      empty_line,		 {ctrl('U')}),
 | |
|   ACTION("eof",			      eof,			 {ctrl('Z')}),
 | |
| 
 | |
|   ACTION("delete_character_or_eof",   delete_character_or_eof,	 {ctrl('D')}),
 | |
|   ACTION("delete_character",	      delete_character,		 {127}),
 | |
|   { "forward_word",		forward_word,  {meta(ctrl('F')), meta('f')}},
 | |
|   { "backward_word",		backward_word, {meta(ctrl('B')), meta('b')}},
 | |
|   { "forward_delete_word",	forward_delete_word, {meta(127), meta('d')}},
 | |
|   ACTION("list_completions",	      list_completions,     {meta('?')}),
 | |
|   ACTION("backward_delete_word",      backward_delete_word, {meta('\b')}),
 | |
| 
 | |
|   ACTION(NULL,			      NULL,			 "")
 | |
| };
 | |
| 
 | |
| int
 | |
| rlc_bind(int chr, const char *fname)
 | |
| { if ( chr >= 0 && chr <= 256 )
 | |
|   { Action a = actions;
 | |
|     
 | |
|     for( ; a->name; a++ )
 | |
|     { if ( strcmp(a->name, fname) == 0 )
 | |
|       { if ( chr > META_OFFSET )
 | |
| 	  dispatch_meta[chr-META_OFFSET] = a->function;
 | |
| 	else
 | |
| 	  dispatch_table[chr] = a->function;
 | |
| 
 | |
| 	return TRUE;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| bind_actions()
 | |
| { Action a = actions;
 | |
| 
 | |
|   for( ; a->name; a++ )
 | |
|   { unsigned char *k = a->keys;
 | |
| 
 | |
|     for( ; *k; k++ )
 | |
|     { int chr = *k & 0xff;
 | |
| 
 | |
|       if ( chr > META_OFFSET )
 | |
| 	dispatch_meta[chr-META_OFFSET] = a->function;
 | |
|       else
 | |
| 	dispatch_table[chr] = a->function;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 |