1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 
5 #include "ppport.h"
6 
7 #include <histedit.h>
8 
9 #include <stdio.h>
10 
11 #include "const-c.inc"
12 
13 #define HERE printf("%d\n",__LINE__)
14 
15 unsigned char pwrapper (EditLine *, int, unsigned int);
16 
17 typedef struct _HistEdit {
18   EditLine * el;    /* the editline struct */
19   History  *hist;   /* the history struct */
20   SV *el_ref;       /* perl reference of the editline struct */
21   SV *promptSv;     /* perl prompt subref */
22   SV *rpromptSv;    /* perl rprompt subref */
23   SV *getcSv;       /* perl EL_GETCFN subref */
24   char *prompt;
25   char *rprompt;
26 } HistEdit;
27 
28 extern void re_refresh(EditLine *);
29 
30 /* user defined functions */
uf00(EditLine * e,int k)31 static unsigned char uf00 (EditLine * e, int k) { return pwrapper(e,k,0); }
uf01(EditLine * e,int k)32 static unsigned char uf01 (EditLine * e, int k) { return pwrapper(e,k,1); }
uf02(EditLine * e,int k)33 static unsigned char uf02 (EditLine * e, int k) { return pwrapper(e,k,2); }
uf03(EditLine * e,int k)34 static unsigned char uf03 (EditLine * e, int k) { return pwrapper(e,k,3); }
uf04(EditLine * e,int k)35 static unsigned char uf04 (EditLine * e, int k) { return pwrapper(e,k,4); }
uf05(EditLine * e,int k)36 static unsigned char uf05 (EditLine * e, int k) { return pwrapper(e,k,5); }
uf06(EditLine * e,int k)37 static unsigned char uf06 (EditLine * e, int k) { return pwrapper(e,k,6); }
uf07(EditLine * e,int k)38 static unsigned char uf07 (EditLine * e, int k) { return pwrapper(e,k,7); }
uf08(EditLine * e,int k)39 static unsigned char uf08 (EditLine * e, int k) { return pwrapper(e,k,8); }
uf09(EditLine * e,int k)40 static unsigned char uf09 (EditLine * e, int k) { return pwrapper(e,k,9); }
uf10(EditLine * e,int k)41 static unsigned char uf10 (EditLine * e, int k) { return pwrapper(e,k,10); }
uf11(EditLine * e,int k)42 static unsigned char uf11 (EditLine * e, int k) { return pwrapper(e,k,11); }
uf12(EditLine * e,int k)43 static unsigned char uf12 (EditLine * e, int k) { return pwrapper(e,k,12); }
uf13(EditLine * e,int k)44 static unsigned char uf13 (EditLine * e, int k) { return pwrapper(e,k,13); }
uf14(EditLine * e,int k)45 static unsigned char uf14 (EditLine * e, int k) { return pwrapper(e,k,14); }
uf15(EditLine * e,int k)46 static unsigned char uf15 (EditLine * e, int k) { return pwrapper(e,k,15); }
uf16(EditLine * e,int k)47 static unsigned char uf16 (EditLine * e, int k) { return pwrapper(e,k,16); }
uf17(EditLine * e,int k)48 static unsigned char uf17 (EditLine * e, int k) { return pwrapper(e,k,17); }
uf18(EditLine * e,int k)49 static unsigned char uf18 (EditLine * e, int k) { return pwrapper(e,k,18); }
uf19(EditLine * e,int k)50 static unsigned char uf19 (EditLine * e, int k) { return pwrapper(e,k,19); }
uf20(EditLine * e,int k)51 static unsigned char uf20 (EditLine * e, int k) { return pwrapper(e,k,20); }
uf21(EditLine * e,int k)52 static unsigned char uf21 (EditLine * e, int k) { return pwrapper(e,k,21); }
uf22(EditLine * e,int k)53 static unsigned char uf22 (EditLine * e, int k) { return pwrapper(e,k,22); }
uf23(EditLine * e,int k)54 static unsigned char uf23 (EditLine * e, int k) { return pwrapper(e,k,23); }
uf24(EditLine * e,int k)55 static unsigned char uf24 (EditLine * e, int k) { return pwrapper(e,k,24); }
uf25(EditLine * e,int k)56 static unsigned char uf25 (EditLine * e, int k) { return pwrapper(e,k,25); }
uf26(EditLine * e,int k)57 static unsigned char uf26 (EditLine * e, int k) { return pwrapper(e,k,26); }
uf27(EditLine * e,int k)58 static unsigned char uf27 (EditLine * e, int k) { return pwrapper(e,k,27); }
uf28(EditLine * e,int k)59 static unsigned char uf28 (EditLine * e, int k) { return pwrapper(e,k,28); }
uf29(EditLine * e,int k)60 static unsigned char uf29 (EditLine * e, int k) { return pwrapper(e,k,29); }
uf30(EditLine * e,int k)61 static unsigned char uf30 (EditLine * e, int k) { return pwrapper(e,k,30); }
uf31(EditLine * e,int k)62 static unsigned char uf31 (EditLine * e, int k) { return pwrapper(e,k,31); }
63 
64 static struct ufe {
65   unsigned char (*cwrapper)(EditLine * , int);
66   SV *pfunc;
67 } uf_tbl[] = {
68   { uf00, NULL },
69   { uf01, NULL },
70   { uf02, NULL },
71   { uf03, NULL },
72   { uf04, NULL },
73   { uf05, NULL },
74   { uf06, NULL },
75   { uf07, NULL },
76   { uf08, NULL },
77   { uf09, NULL },
78   { uf10, NULL },
79   { uf11, NULL },
80   { uf12, NULL },
81   { uf13, NULL },
82   { uf14, NULL },
83   { uf15, NULL },
84   { uf16, NULL },
85   { uf17, NULL },
86   { uf18, NULL },
87   { uf19, NULL },
88   { uf20, NULL },
89   { uf21, NULL },
90   { uf22, NULL },
91   { uf23, NULL },
92   { uf24, NULL },
93   { uf25, NULL },
94   { uf26, NULL },
95   { uf27, NULL },
96   { uf28, NULL },
97   { uf29, NULL },
98   { uf30, NULL },
99   { uf31, NULL }
100 };
101 
pwrapper(EditLine * e,int k,unsigned int id)102 unsigned char pwrapper (EditLine * e, int k, unsigned int id)
103 {
104 
105   dSP;
106 
107   HistEdit *he;
108   int count;
109   int ret = CC_NORM;
110 
111   if(id < 32) {
112     if(uf_tbl[id].pfunc != NULL) {
113 
114       el_get(e,EL_CLIENTDATA,&he);
115 
116       dXSTARG;
117 
118       ENTER;
119       SAVETMPS;
120 
121       PUSHMARK(SP);
122       XPUSHs(he->el_ref);
123       XPUSHi(k);
124       PUTBACK;
125 
126       count = perl_call_sv(uf_tbl[id].pfunc,G_SCALAR);
127 
128       SPAGAIN;
129 
130       if(count != 1) {
131 	croak ("Term::EditLine: internal error\n");
132       }
133 
134       ret = POPi;
135 
136       PUTBACK;
137       FREETMPS;
138       LEAVE;
139 
140     }
141   }
142   return (unsigned char)ret;
143 }
144 
145 char *
pvsubwrapper(HistEdit * he,SV * sub,char * def)146 pvsubwrapper(HistEdit *he, SV *sub, char *def)
147 {
148   dSP;
149   SV *svret;
150   int count,a,b;
151   STRLEN len;
152 
153   if (sub == NULL)
154     return def;
155 
156   ENTER;
157   SAVETMPS;
158   PUSHMARK(SP);
159   XPUSHs(he->el_ref);
160   PUTBACK;
161 
162   count = perl_call_sv(sub,G_SCALAR);
163 
164   SPAGAIN;
165 
166   if (count != 1)
167     croak ("Term::EditLine: error calling perl sub\n");
168 
169   svret = POPs;
170 
171   if(SvPOK(svret)) {
172 
173     b = SvLEN(svret);
174 
175     if(def == NULL)
176       def = malloc(b+1);
177     else if ((a = strlen(def)) < b)
178       def = realloc(def,b-a);
179 
180     Copy(SvPV(svret,PL_na),def,b,char);
181     *(def+b) = '\0';
182 
183   }
184 
185   PUTBACK;
186   FREETMPS;
187   LEAVE;
188   return def;
189 }
190 
promptfunc(EditLine * e)191 char *promptfunc (EditLine *e)
192 {
193   HistEdit *he;
194   el_get(e,EL_CLIENTDATA,&he);
195   return pvsubwrapper(he,he->promptSv,he->prompt);
196 }
197 
rpromptfunc(EditLine * e)198 char *rpromptfunc (EditLine *e)
199 {
200   HistEdit *he;
201   el_get(e,EL_CLIENTDATA,&he);
202   return pvsubwrapper(he,he->rpromptSv,he->rprompt);
203 }
204 
te_getc_fun(EditLine * e,char * c)205 int te_getc_fun (EditLine *e, char *c)
206 {
207   SV *svret;
208   int count,len;
209   HistEdit *he;
210 
211   el_get(e,EL_CLIENTDATA,&he);
212 
213   if (he->getcSv != NULL) {
214 
215     dSP;
216 
217     ENTER;
218     SAVETMPS;
219     PUSHMARK(SP);
220     XPUSHs(he->el_ref);
221     PUTBACK;
222 
223     count = perl_call_sv(he->getcSv,G_SCALAR);
224 
225     SPAGAIN;
226 
227     if (count != 1)
228       croak ("Term::EditLine: error calling perl sub\n");
229 
230     svret = POPs;
231 
232     if(SvPOK(svret)) {
233       Copy(SvPV(svret,PL_na),c,1,char);
234     }
235 
236     PUTBACK;
237     FREETMPS;
238     LEAVE;
239 
240     return 1;
241   }
242   return 0;
243 }
244 
245 MODULE = Term::EditLine   PACKAGE = Term::EditLine   PREFIX = el_
246 INCLUDE: const-xs.inc
247 
248 void
249 el_beep(he)
250 	HistEdit * 	he
251 CODE:
252 {
253   el_beep(he->el);
254 }
255 
256 void
el_deletestr(he,count)257 el_deletestr(he, count)
258 	HistEdit * 	he
259 	int		count
260 CODE:
261 {
262   el_deletestr(he->el,count);
263 }
264 
265 char *
266 el_getc(he)
267 	HistEdit * 	he
268 PREINIT:
269   char ch[2];
270   char c;
271   int ret;
272 CODE:
273 {
274   el_getc(he->el,&c);
275   ch[0] = c;
276   ch[1] = '\0';
277   RETVAL = ch;
278 }
279 
280 void
281 el_gets(he)
282 	HistEdit* he
283 PREINIT:
284   int count;
285   const char *line;
286 PPCODE:
287 {
288   line = el_gets(he->el,&count);
289 
290   dXSTARG;
291   if (line != NULL)
292     XPUSHp(line,count);
293   else
294     XPUSHs(&PL_sv_undef);
295 }
296 
297 HistEdit *
298 el_new(pkg,name,fin=stdin,fout=stdout,ferr=stderr)
299      char *     pkg
300      char *     name
301      FILE *	fin
302      FILE *	fout
303      FILE *	ferr
304 PREINIT:
305    HistEvent ev;
306    SV *el;
307 CODE:
308 {
309 
310   RETVAL = malloc(sizeof(HistEdit));
311 
312   RETVAL->el = el_init(name, fin, fout, ferr);
313   RETVAL->el_ref = newSVsv(sv_newmortal());
314   sv_setref_pv(RETVAL->el_ref,"Term::EditLine",(void*)RETVAL);
315 
316   RETVAL->promptSv = NULL;
317   RETVAL->prompt = NULL;
318   RETVAL->rpromptSv = NULL;
319   RETVAL->rprompt = NULL;
320   RETVAL->getcSv = NULL;
321 
322   ST(0) = RETVAL->el_ref;
323 
324   RETVAL->hist = history_init();
325   history (RETVAL->hist,&ev,H_SETSIZE,100);
326 
327   el_set(RETVAL->el,EL_HIST,history,RETVAL->hist);
328   el_set(RETVAL->el,EL_CLIENTDATA,RETVAL);
329 
330   el_source(RETVAL->el, NULL);
331 }
332 
el_DESTROY(he)333 void el_DESTROY(he)
334      HistEdit *he
335 PREINIT:
336 SV *el;
337 CODE:
338 {
339   if(he->prompt != NULL)
340     free(he->prompt);
341   if(he->rprompt != NULL)
342     free(he->rprompt);
343   if(he->promptSv != NULL) {
344     sv_free(he->promptSv);
345   }
346   if(he->rpromptSv != NULL)
347     sv_free(he->rpromptSv);
348 
349   sv_free(he->el_ref);
350   el_end(he->el);
351   history_end(he->hist);
352   free(he);
353 }
354 
355 int
el_history_set_size(he,size)356 el_history_set_size(he,size)
357          HistEdit *he
358          int size
359 PREINIT:
360 HistEvent ev;
361 CODE:
362 {
363   RETVAL = history(he->hist,&ev,H_SETSIZE,size);
364 }
365 OUTPUT:
366   RETVAL
367 
368 int
el_history_enter(he,str)369 el_history_enter(he,str)
370      HistEdit *he
371      char *str
372 PREINIT:
373   HistEvent ev;
374 CODE:
375 {
376   RETVAL = history(he->hist,&ev,H_ENTER,str);
377 }
378 OUTPUT:
379   RETVAL
380 
381 int
el_history_append(he,str)382 el_history_append (he,str)
383      HistEdit *he
384      char *str
385 PREINIT:
386   HistEvent ev;
387 CODE:
388 {
389   RETVAL = history(he->hist,&ev,H_APPEND,str);
390 }
391 OUTPUT:
392   RETVAL
393 
394 int
el_history_add(he,str)395 el_history_add (he,str)
396      HistEdit *he
397      char *str
398 PREINIT:
399   HistEvent ev;
400 CODE:
401 {
402   RETVAL = history(he->hist,&ev,H_ADD,str);
403 }
404 OUTPUT:
405   RETVAL
406 
407 void
el_history_get_size(he)408 el_history_get_size (he)
409      HistEdit *he
410 PREINIT:
411   HistEvent ev;
412 PPCODE:
413 {
414   dTARG;
415   int ret = history(he->hist,&ev,H_GETSIZE);
416   if (GIMME_V == G_ARRAY) {
417     mXPUSHi(ret);
418   }
419   mXPUSHi(ev.num);
420 }
421 
422 int
el_history_clear(he)423 el_history_clear (he)
424      HistEdit *he
425 PREINIT:
426   HistEvent ev;
427 CODE:
428 {
429   RETVAL = history(he->hist,&ev,H_CLEAR);
430 }
431 OUTPUT:
432   RETVAL
433 
434 void
el_history_get_first(he)435 el_history_get_first(he)
436      HistEdit *he
437 PREINIT:
438   HistEvent ev;
439 PPCODE:
440 {
441   dTARG;
442   int ret = history(he->hist,&ev,H_FIRST);
443   if (GIMME_V == G_ARRAY) {
444     mXPUSHi(ret);
445   }
446   mXPUSHp(ev.str, strlen(ev.str));
447 }
448 
449 void
el_history_get_last(he)450 el_history_get_last(he)
451      HistEdit *he
452 PREINIT:
453   HistEvent ev;
454 PPCODE:
455 {
456   dTARG;
457   int ret = history(he->hist,&ev,H_LAST);
458   if (GIMME_V == G_ARRAY) {
459     mXPUSHi(ret);
460   }
461   mXPUSHp(ev.str, strlen(ev.str));
462 }
463 
464 void
el_history_get_prev(he)465 el_history_get_prev(he)
466      HistEdit *he
467 PREINIT:
468   HistEvent ev;
469 PPCODE:
470 {
471   dTARG;
472   int ret = history(he->hist,&ev,H_PREV);
473   if (GIMME_V == G_ARRAY) {
474     mXPUSHi(ret);
475   }
476   mXPUSHp(ev.str, strlen(ev.str));
477 }
478 
479 
480 void
el_history_get_next(he)481 el_history_get_next(he)
482      HistEdit *he
483 PREINIT:
484   HistEvent ev;
485 PPCODE:
486 {
487   dTARG;
488   int ret = history(he->hist,&ev,H_NEXT);
489   if (GIMME_V == G_ARRAY) {
490     mXPUSHi(ret);
491   }
492   mXPUSHp(ev.str, strlen(ev.str));
493 }
494 
495 
496 void
el_history_get_curr(he)497 el_history_get_curr(he)
498      HistEdit *he
499 PREINIT:
500   HistEvent ev;
501 PPCODE:
502 {
503   dTARG;
504   int ret = history(he->hist,&ev,H_CURR);
505   if (GIMME_V == G_ARRAY) {
506     mXPUSHi(ret);
507   }
508   mXPUSHp(ev.str, strlen(ev.str));
509 }
510 
511 int
el_history_set(he)512 el_history_set(he)
513      HistEdit *he
514 PREINIT:
515   HistEvent ev;
516 CODE:
517 {
518   RETVAL = history(he->hist,&ev,H_SET);
519 }
520 OUTPUT:
521   RETVAL
522 
523 void
el_history_get_prev_str(he,str)524 el_history_get_prev_str(he,str)
525      HistEdit *he
526      char *str
527 PREINIT:
528   HistEvent ev;
529 PPCODE:
530 {
531   dTARG;
532   int ret = history(he->hist,&ev,H_PREV_STR,str);
533   if (GIMME_V == G_ARRAY) {
534     mXPUSHi(ret);
535   }
536   mXPUSHp(ev.str, strlen(ev.str));
537 }
538 
539 void
el_history_get_next_str(he,str)540 el_history_get_next_str(he,str)
541      HistEdit *he
542      char *str
543 PREINIT:
544   HistEvent ev;
545 PPCODE:
546 {
547   dTARG;
548   int ret = history(he->hist,&ev,H_NEXT_STR,str);
549   if (GIMME_V == G_ARRAY) {
550     mXPUSHi(ret);
551   }
552   mXPUSHp(ev.str, strlen(ev.str));
553 }
554 
555 int
el_history_load(he,str)556 el_history_load(he,str)
557      HistEdit *he
558      char *str
559 PREINIT:
560   HistEvent ev;
561 CODE:
562 {
563   RETVAL = history(he->hist,&ev,H_LOAD,str);
564 }
565 OUTPUT:
566   RETVAL
567 
568 int
el_history_save(he,str)569 el_history_save(he,str)
570      HistEdit *he
571      char *str
572 PREINIT:
573   HistEvent ev;
574 CODE:
575 {
576   RETVAL = history(he->hist,&ev,H_SAVE,str);
577 }
578 OUTPUT:
579   RETVAL
580 
581 int
el_insertstr(he,str)582 el_insertstr(he, str)
583 	HistEdit * 	he
584 	char *		str
585 CODE:
586 {
587   RETVAL = el_insertstr(he->el,str);
588 }
589 
590 void
el_line(he)591 el_line(he)
592      HistEdit * 	he
593 PREINIT:
594      const LineInfo *le;
595 PPCODE:
596 {
597   le = el_line(he->el);
598   EXTEND(sp,3);
599   PUSHs(sv_2mortal(newSVpv(le->buffer,le->lastchar - le->buffer)));
600   /*  printf("%s, %d, %d\n",le->buffer,le->cursor - le->buffer,le->lastchar - le->buffer);*/
601   PUSHs(sv_2mortal(newSViv(le->cursor - le->buffer)));
602   PUSHs(sv_2mortal(newSViv(le->lastchar - le->buffer)));
603 }
604 
el_set_line(he,buffer,cursor)605 void el_set_line(he,buffer,cursor)
606      HistEdit * he
607      char * buffer
608      int cursor
609 CODE:
610 {
611   LineInfo *l = (LineInfo*) el_line(he->el);
612   l->buffer = buffer;
613   l->lastchar = buffer+strlen(buffer);
614   if(buffer+cursor > l->lastchar)
615     l->cursor = l->lastchar;
616   else
617     l->cursor = buffer+cursor;
618 }
619 
620 int el_parse(he,...)
621         HistEdit * he
622 PREINIT:
623   int alen,i;
624   const char **argv;
625   char* tmp;
626   STRLEN len;
627 PPCODE:
628 {
629   if (items > 1) {
630 
631     argv = malloc(sizeof(char*)*items);
632 
633     alen = items - 1;
634 
635     for(i=1;i<items;i++) {
636       if(SvPOK(ST(i))) {
637 	argv[i-1] = SvPV(ST(i),len);
638       } else {
639 	argv[i-1] = NULL;
640       }
641     }
642 
643     argv[alen] = NULL;
644 
645     XPUSHi(el_parse(he->el,alen,argv));
646 
647     free(argv);
648 
649   } else {
650     XSRETURN_UNDEF;
651   }
652 }
653 
654 void
el_push(he,arg1)655 el_push(he, arg1)
656 	HistEdit * he
657 	char *	arg1
658 CODE:
659 {
660   el_push(he->el,arg1);
661 }
662 
663 void
el_reset(he)664 el_reset(he)
665 	HistEdit * 	he
666 CODE:
667 {
668   el_reset(he->el);
669 }
670 
671 void
el_resize(he)672 el_resize(he)
673 	HistEdit * 	he
674 CODE:
675 {
676   el_resize(he->el);
677 }
678 
679 
el_set_prompt(he,func)680 int el_set_prompt(he, func)
681      HistEdit * he
682      SV * func
683 CODE:
684 {
685   if(strcmp(sv_reftype(SvRV(func),0),"CODE") == 0) {
686     he->promptSv = newSVsv(func);
687     RETVAL = el_set(he->el,EL_PROMPT,promptfunc);
688   } else {
689     if(he->promptSv != NULL) {
690       sv_free(he->promptSv);
691       he->promptSv = NULL;
692     }
693     if(SvPOK(func)) {
694       he->prompt = malloc(SvLEN(func)+1);
695       strcpy(he->prompt,SvPV(func,PL_na));
696     }
697     RETVAL = el_set(he->el,EL_PROMPT,promptfunc);
698   }
699 }
700 
el_set_rprompt(he,func)701 int el_set_rprompt(he, func)
702      HistEdit * he
703      SV * func
704 CODE:
705 {
706   if(strcmp(sv_reftype(SvRV(func),0),"CODE") == 0) {
707     he->rpromptSv = newSVsv(func);
708     RETVAL = el_set(he->el,EL_RPROMPT,rpromptfunc);
709   } else {
710     if(he->rpromptSv != NULL) {
711       sv_free(he->rpromptSv);
712       he->rpromptSv = NULL;
713     }
714     if(SvPOK(func)) {
715       he->rprompt = malloc(SvLEN(func)+1);
716       strcpy(he->rprompt,SvPV(func,PL_na));
717     }
718     RETVAL = el_set(he->el,EL_PROMPT,rpromptfunc);
719   }
720 }
721 
el_get_prompt(he)722 void el_get_prompt(he)
723      HistEdit *he
724 PPCODE:
725 {
726   if(he->promptSv != NULL)
727     XPUSHs(sv_2mortal(he->promptSv));
728   else if(he->prompt != NULL)
729     XPUSHs(sv_2mortal(newSVpv(he->prompt,0)));
730   else
731     XSRETURN_UNDEF;
732 }
733 
el_get_rprompt(he)734 void el_get_rprompt(he)
735      HistEdit *he
736 PPCODE:
737 {
738   if(he->rpromptSv != NULL)
739     XPUSHs(sv_2mortal(he->rpromptSv));
740   else if(he->rprompt != NULL)
741     XPUSHs(sv_2mortal(newSVpv(he->rprompt,0)));
742   else
743     XSRETURN_UNDEF;
744 }
745 
746 void
el_set_editor(he,mode)747 el_set_editor(he,mode)
748      HistEdit * he
749      char *mode
750 CODE:
751 {
752   if (!strcmp(mode,"vi") || !strcmp(mode,"emacs"))
753     el_set(he->el,EL_EDITOR,mode);
754 }
755 
756 char*
el_get_editor(he)757 el_get_editor(he)
758      HistEdit *he
759 PREINIT:
760      char mode[6];
761 CODE:
762 {
763   el_get(he->el,EL_EDITOR,mode);
764   RETVAL = mode;
765 }
766 
767 void
el_set_terminal(he,type)768 el_set_terminal(he,type)
769      HistEdit * he
770      char *type
771 CODE:
772 {
773   el_set(he->el,EL_TERMINAL,type);
774 }
775 
776 
777 void
el_signal(he,flag)778 el_signal(he,flag)
779      HistEdit *he
780      int flag
781 CODE:
782 {
783   el_set(he->el,EL_SIGNAL,flag);
784 }
785 
786 int el_bind(he,...)
787         HistEdit * he
788 PREINIT:
789   const char *cmd;
790   int alen,i;
791   const char **argv;
792 CODE:
793 {
794   if (items > 1) {
795 
796     argv = malloc(sizeof(char*) * (items+1));
797     argv[0] = "bind";
798 
799     for(i=1;i<items;i++) {
800       if(SvPOK(ST(i))) {
801 	argv[i] = SvPV(ST(i),PL_na);
802       } else {
803 	argv[i] = NULL;
804       }
805     }
806 
807     argv[items] = NULL;
808 
809     RETVAL = el_parse(he->el,items,argv);
810 
811     free(argv);
812 
813   } else {
814     XSRETURN_UNDEF;
815   }
816 }
817 
el_add_fun(he,name,help,sub)818 int el_add_fun (he,name,help,sub)
819      HistEdit * he
820      char *name
821      char *help
822      SV *sub
823 PREINIT:
824   int i;
825 CODE:
826 {
827   for(i=0;i<32;i++)
828     if(uf_tbl[i].pfunc == NULL) {
829       uf_tbl[i].pfunc = newSVsv(sub);
830       break;
831     }
832 
833   if(i == 32) {
834     croak("Term::EditLine: Error: you can only add up to 32 functions\n");
835     RETVAL = -1;
836   } else {
837     RETVAL = el_set(he->el,EL_ADDFN,name,help,uf_tbl[i].cwrapper);
838   }
839 }
840 
el_set_getc_fun(he,sub)841 int el_set_getc_fun (he,sub)
842      HistEdit *he
843      SV *sub
844 CODE:
845 {
846   if (SvTYPE(SvRV(sub)) == SVt_PVCV) {
847     he->getcSv = newSVsv(sub);
848     RETVAL = el_set(he->el,EL_GETCFN,te_getc_fun);
849   } else {
850     RETVAL = 0;
851   }
852 }
853 
el_restore_getc_fun(he)854 int el_restore_getc_fun(he)
855      HistEdit *he
856 CODE:
857 {
858   sv_free(he->getcSv);
859   he->getcSv = NULL;
860   RETVAL = el_set(he->el,EL_GETCFN,EL_BUILTIN_GETCFN);
861 }
862 
863 int
el_source(he,arg1)864 el_source(he, arg1)
865 	HistEdit * 	he
866 	const char *	arg1
867 CODE:
868 {
869   el_source(he->el,arg1);
870 }
871