Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
siodeditline.c
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1996,1997 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Alan W Black */
34 /* Date : December 1998 */
35 /*-----------------------------------------------------------------------*/
36 /* */
37 /* Due to incompatibility between the GPL for readline and Festival's */
38 /* current licence readline support was removed after 1.3.0 */
39 /* This uses a much simpler but much poorer command line editor called */
40 /* editline instead. */
41 /* */
42 /* Although this code is included in our distribution we still offer */
43 /* optional compilation as it may not work on all platforms */
44 /* */
45 /*=======================================================================*/
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include "EST_unix.h"
49 #include <string.h>
50 #include "EST_cutils.h"
51 #include "siodeditline.h"
52 
53 FILE *stddebug = NULL;
54 extern int el_pos;
55 extern char *repl_prompt;
56 
57 #ifndef SUPPORT_EDITLINE
58 
59 /* If for some reason you don't want editline the following */
60 /* functions are provided. They are functional but minimal. They are */
61 /* suitable when you are in an embedded environment and don't need */
62 /* command lin editing */
63 int el_no_echo;
64 int editline_histsize;
65 
66 int siod_el_getc(FILE *f)
67 {
68  int c;
69 
70  if (el_pos == -1)
71  {
72  fprintf(stdout,"%s",repl_prompt);
73  fflush(stdout);
74  el_pos = 0;
75  }
76 
77  c = getc(f);
78 
79  if (c == '\n')
80  el_pos = -1;
81 
82  return c;
83 }
84 
85 void siod_el_ungetc(int c, FILE *f)
86 {
87  ungetc(c,f);
88 }
89 
90 void siod_el_init(void)
91 {
92  return;
93 }
94 #else
95 #include "editline.h"
96 
97 static int possible_commandp(char *text, int start, int end);
98 static int possible_variablep(char *text, int start, int end);
99 static char **command_completion (char *text,int start,int end);
100 
101 static char *el_line = NULL;
102 
103 char *editline_history_file = ".editline_history";
104 static char *full_history_file = ".editline_history";
105 
106 static STATUS siod_display_doc ()
107 {
108  /* Find the current symbol and check for a documentation string */
109  char *symbol;
110  const char *docstring;
111  int i;
112 
113  symbol = el_current_sym();
114  putc('\n',stderr);
115  docstring = siod_docstring(symbol);
116  for (i=0; docstring[i] != '\0'; i++)
117  putc(docstring[i],stderr);
118  putc('\n',stderr);
119  fflush(stderr);
120  wfree(symbol);
121  el_redisplay();
122  return CSmove;
123 }
124 
125 static STATUS siod_say_doc ()
126 {
127  /* Find the current symbol and check for a documentation string */
128  /* Now this is what you call wasting your time. Here we get the */
129  /* synthesizer to say the documentation string */
130  char *symbol;
131 
132  symbol = el_current_sym();
133  fprintf(stderr,"\nsynthesizing doc string ...");
134  fflush(stderr);
135  siod_saydocstring(symbol);
136  putc('\n',stderr);
137  fflush(stderr);
138  wfree(symbol);
139  el_redisplay();
140  return CSmove;
141 }
142 
143 static STATUS siod_manual()
144 {
145  /* Find the current symbol and check for a documentation string */
146  /* Look for a "see " reference in its documentation string, if so */
147  /* access that section of the manual by sending a call to netscape */
148  char *symbol;
149  const char *infostring;
150 
151  symbol = el_current_sym();
152  infostring = siod_manual_sym(symbol);
153  putc('\n',stderr);
154  fprintf(stderr,"%s",infostring);
155  fflush(stderr);
156  putc('\n',stderr);
157  fflush(stderr);
158  el_redisplay();
159  wfree(symbol);
160  return CSmove;
161 }
162 
163 void siod_el_init(void)
164 {
165  /* Various initialization completion, history etc */
166  char *home;
167 
168  home = getenv("HOME");
169  if (home==NULL)
170  home="";
171  full_history_file =
172  walloc(char,strlen(home)+strlen(editline_history_file)+2);
173  sprintf(full_history_file,"%s/%s",home,editline_history_file);
174  read_history(full_history_file);
175  el_user_intr = TRUE; /* we want SIGINT to raise a signal */
176 
177  el_user_completion_function = command_completion;
178  el_bind_key_in_metamap('h',siod_display_doc);
179  el_bind_key_in_metamap('s',siod_say_doc);
180  el_bind_key_in_metamap('m',siod_manual);
181 }
182 
183 int siod_el_getc(FILE *f)
184 {
185  int c;
186 
187  if (el_pos == -1)
188  {
189  el_line=readline(repl_prompt);
190  if (el_line != NULL)
191  {
192  add_history(el_line);
193  write_history(full_history_file);
194  }
195  el_pos = 0;
196  }
197  if ((el_line==NULL) ||
198  (strlen(el_line) <= el_pos))
199  el_pos = -1;
200  if (el_line==NULL)
201  c = EOF;
202  else if (el_pos == -1)
203  c = '\n'; /* whitespace representing end of line */
204  else
205  {
206  c = el_line[el_pos];
207  el_pos++;
208  }
209 
210  return c;
211 }
212 
213 void siod_el_ungetc(int c, FILE *f)
214 {
215  if (el_pos > 0)
216  el_pos--;
217  else
218  {
219  fprintf(stderr,"fix ungetc when nothing is there");
220  }
221 }
222 
223 static int qsort_str_compare(const void *p1,const void *p2)
224 {
225  const char *s1;
226  const char *s2;
227 
228  s1 = *(const char **)p1;
229  s2 = *(const char **)p2;
230 
231  return strcmp(s1,s2);
232 }
233 
234 static char **command_completion (char *text,int start,int end)
235 {
236  char **matches = NULL;
237  int i;
238 
239  /* If preceding non-alphanum character is a left paren, */
240  /* look for a command else look for any variable */
241  if (possible_commandp(text,start,end))
242  matches = siod_command_generator(text+start,end-start);
243  else if (possible_variablep(text,start,end))
244  matches = siod_variable_generator(text+start,end-start);
245 
246  if (matches && matches[0] && matches[1])
247  {
248  /* If there are at least two, Sort them */
249  for (i=0; matches[i] != NULL; i++);
250  qsort(matches,i,sizeof(char **),qsort_str_compare);
251  }
252 
253  return matches;
254 }
255 
256 static int possible_commandp(char *text, int start, int end)
257 {
258  /* If non-white space previous to this is a left paren */
259  /* signal we are looking for a function name */
260  int t;
261 
262  for (t=start-1; t >= 0; t--)
263  if (strchr(" \t\n\r",text[t]) != NULL)
264  continue;
265  else if (text[t] == '(')
266  return TRUE;
267  else
268  return FALSE;
269 
270  return FALSE;
271 }
272 
273 static int possible_variablep(char *text, int start, int end)
274 {
275  /* Almost negative of above but if previous symbol is a quote */
276  /* let the file completion stuff do it */
277  int t;
278 
279  for (t=start-1; t >= 0; t--)
280  if (strchr(" \t\n",text[t]) != NULL)
281  continue;
282  else if (text[t] == '(')
283  return FALSE;
284  else if ((text[t] == '"') &&
285  (t == start-1))
286  return FALSE;
287  else
288  return TRUE;
289 
290  return TRUE;
291 }
292 
293 #endif /* SUPPORT_EDITLINE */