source: editwin.c @ 94cbc453

barnowl_perlaimdebianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 94cbc453 was e74c01c, checked in by Nelson Elhage <nelhage@mit.edu>, 18 years ago
I failed to commit this in the last ci
  • Property mode set to 100644
File size: 21.9 KB
Line 
1#include "owl.h"
2#include <stdlib.h>
3#include <unistd.h>
4#include <string.h>
5#include <ctype.h>
6
7static const char fileIdent[] = "$Id$";
8
9#define INCR 5000
10
11/* initialize the editwin e.
12 * 'win' is an already initialzed curses window that will be used by editwin
13 */
14void owl_editwin_init(owl_editwin *e, WINDOW *win, int winlines, int wincols, int style, owl_history *hist)
15{
16  e->buff=owl_malloc(INCR); 
17  e->buff[0]='\0';
18  e->bufflen=0;
19  e->hist=hist;
20  e->allocated=INCR;
21  e->buffx=0;
22  e->buffy=0;
23  e->topline=0;
24  e->winlines=winlines;
25  e->wincols=wincols;
26  e->fillcol=owl_editwin_limit_maxcols(wincols-1, owl_global_get_edit_maxfillcols(&g));
27  e->wrapcol=owl_editwin_limit_maxcols(wincols-1, owl_global_get_edit_maxwrapcols(&g));
28  e->curswin=win;
29  e->style=style;
30  if ((style!=OWL_EDITWIN_STYLE_MULTILINE) &&
31      (style!=OWL_EDITWIN_STYLE_ONELINE)) {
32    e->style=OWL_EDITWIN_STYLE_MULTILINE;
33  }
34  e->lock=0;
35  e->dotsend=0;
36  e->echochar='\0';
37
38  /*
39    // We get initialized multiple times, but we need to hold on to
40    // the callbacks, so we can't NULL them here.
41    e->command = NULL;
42    e->callback = NULL;
43    e->cbdata = NULL;
44  */
45  if (win) werase(win);
46}
47
48void owl_editwin_set_curswin(owl_editwin *e, WINDOW *w, int winlines, int wincols)
49{
50  e->curswin=w;
51  e->winlines=winlines;
52  e->wincols=wincols;
53  e->fillcol=owl_editwin_limit_maxcols(wincols-1, owl_global_get_edit_maxfillcols(&g));
54  e->wrapcol=owl_editwin_limit_maxcols(wincols-1, owl_global_get_edit_maxwrapcols(&g));
55}
56
57/* echo the character 'ch' for each normal character keystroke,
58 * excepting locktext.  This is useful for entering passwords etc.  If
59 * ch=='\0' characters are echo'd normally
60 */
61void owl_editwin_set_echochar(owl_editwin *e, int ch)
62{
63  e->echochar=ch;
64}
65
66WINDOW *owl_editwin_get_curswin(owl_editwin *e)
67{
68  return(e->curswin);
69}
70
71void owl_editwin_set_history(owl_editwin *e, owl_history *h)
72{
73  e->hist=h;
74}
75
76owl_history *owl_editwin_get_history(owl_editwin *e)
77{
78  return(e->hist);
79}
80
81void owl_editwin_set_dotsend(owl_editwin *e)
82{
83  e->dotsend=1;
84}
85
86void owl_editwin_set_command(owl_editwin *e, char *command) {
87  if(e->command) owl_free(e->command);
88  e->command = owl_strdup(command);
89}
90
91char *owl_editwin_get_command(owl_editwin *e) {
92  if(e->command) return e->command;
93  return "";
94}
95
96void owl_editwin_set_callback(owl_editwin *e, void (*cb)(owl_editwin*)) {
97  e->callback = cb;
98}
99
100void (*owl_editwin_get_callback(owl_editwin *e))(owl_editwin*) {
101  return e->callback;
102}
103
104void owl_editwin_set_cbdata(owl_editwin *e, void *data) {
105  e->cbdata = data;
106}
107
108void* owl_editwin_get_cbdata(owl_editwin *e) {
109  return e->cbdata;
110}
111
112void owl_editwin_do_callback(owl_editwin *e) {
113  void (*cb)(owl_editwin*);
114  cb=owl_editwin_get_callback(e);
115  if(!cb) {
116    owl_function_error("Internal error: No editwin callback!");
117  } else {
118    // owl_function_error("text: |%s|", owl_editwin_get_text(e));
119    cb(e);
120  }
121}
122
123int owl_editwin_limit_maxcols(int v, int maxv)
124{
125  if (maxv > 5 && v > maxv) {
126    return(maxv);
127  } else {
128    return(v);
129  }
130}
131
132/* set text to be 'locked in' at the beginning of the buffer, any
133 * previous text (including locked text) will be overwritten
134 */
135void owl_editwin_set_locktext(owl_editwin *e, char *text)
136{
137 
138  int x, y;
139
140  x=e->buffx;
141  y=e->buffy;
142  e->buffx=0;
143  e->buffy=0;
144  owl_editwin_overwrite_string(e, text);
145  e->lock=strlen(text);
146  /* if (text[e->lock-1]=='\n') e->lock--; */
147  e->buffx=x;
148  e->buffy=y;
149  owl_editwin_adjust_for_locktext(e);
150  owl_editwin_redisplay(e, 0);
151}
152
153int owl_editwin_get_style(owl_editwin *e)
154{
155  return(e->style);
156}
157
158void owl_editwin_new_style(owl_editwin *e, int newstyle, owl_history *h)
159{
160  char *ptr;
161
162  owl_editwin_set_history(e, h);
163  if (e->style==newstyle) return;
164
165  if (newstyle==OWL_EDITWIN_STYLE_MULTILINE) {
166    e->style=newstyle;
167  } else if (newstyle==OWL_EDITWIN_STYLE_ONELINE) {
168    e->style=newstyle;
169
170    /* nuke everything after the first line */
171    if (e->bufflen > 0) {
172      ptr=strchr(e->buff, '\n')-1;
173      if (ptr) {
174        e->bufflen=ptr - e->buff;
175        e->buff[e->bufflen]='\0';
176        e->buffx=0;
177        e->buffy=0;
178      }
179    }
180  }
181}
182
183/* completly reinitialize the buffer */
184void owl_editwin_fullclear(owl_editwin *e)
185{
186  owl_free(e->buff);
187  owl_editwin_init(e, e->curswin, e->winlines, e->wincols, e->style, e->hist);
188}
189
190/* clear all text except for locktext and put the cursor at the
191 * beginning
192 */
193void owl_editwin_clear(owl_editwin *e)
194{
195
196  int lock;
197  int dotsend=e->dotsend;
198  char *locktext=NULL;
199
200  lock=0;
201  if (e->lock > 0) {
202    lock=1;
203
204    locktext=owl_malloc(e->lock+20);
205    strncpy(locktext, e->buff, e->lock);
206    locktext[e->lock]='\0';
207  }
208
209  owl_free(e->buff);
210  owl_editwin_init(e, e->curswin, e->winlines, e->wincols, e->style, e->hist);
211
212  if (lock > 0) {
213    owl_editwin_set_locktext(e, locktext);
214  }
215  if (dotsend) {
216    owl_editwin_set_dotsend(e);
217  }
218
219  if (locktext) owl_free(locktext);
220  owl_editwin_adjust_for_locktext(e);
221}
222
223/* malloc more space for the buffer */
224void _owl_editwin_addspace(owl_editwin *e)
225{
226  e->buff=owl_realloc(e->buff, e->allocated+INCR);
227  if (!e->buff) {
228    /* error */
229    return;
230  }
231  e->allocated+=INCR;
232}
233
234void owl_editwin_recenter(owl_editwin *e)
235{
236  e->topline=e->buffy-(e->winlines/2);
237  if (e->topline<0) e->topline=0;
238  if (e->topline>owl_editwin_get_numlines(e)) e->topline=owl_editwin_get_numlines(e);
239}
240
241/* regenerate the text on the curses window */
242/* if update == 1 then do a doupdate(), otherwise do not */
243void owl_editwin_redisplay(owl_editwin *e, int update)
244{
245 
246  char *ptr1, *ptr2, *ptr3, *buff;
247  int i;
248
249  werase(e->curswin);
250  wmove(e->curswin, 0, 0);
251
252  /* start at topline */
253  ptr1=e->buff;
254  for (i=0; i<e->topline; i++) {
255    ptr2=strchr(ptr1, '\n');
256    if (!ptr2) {
257      /* we're already on the last line */
258      break;
259    }
260    ptr1=ptr2+1;
261  }
262  /* ptr1 now stores the starting point */
263
264  /* find the ending point and store it in ptr3 */
265  ptr2=ptr1;
266  ptr3=ptr1;
267  for (i=0; i<e->winlines; i++) {
268    ptr3=strchr(ptr2, '\n');
269    if (!ptr3) {
270      /* we've hit the last line */
271      /* print everything to the end */
272      ptr3=e->buff+e->bufflen-1;
273      ptr3--;
274      break;
275    }
276    ptr2=ptr3+1;
277  }
278  ptr3+=2;
279
280  buff=owl_malloc(ptr3-ptr1+50);
281  strncpy(buff, ptr1, ptr3-ptr1);
282  buff[ptr3-ptr1]='\0';
283  if (e->echochar=='\0') {
284    waddstr(e->curswin, buff);
285  } else {
286    /* translate to echochar, *except* for the locktext */
287    int len;
288    int dolocklen=e->lock-(ptr1-e->buff);
289
290    for (i=0; i<dolocklen; i++) {
291      waddch(e->curswin, buff[i]);
292    }
293    len=strlen(buff);
294    for (i=0; i<len-dolocklen; i++) {
295      waddch(e->curswin, e->echochar);
296    }
297  }
298  wmove(e->curswin, e->buffy-e->topline, e->buffx);
299  wnoutrefresh(e->curswin);
300  if (update==1) {
301    doupdate();
302  }
303  owl_free(buff);
304}
305
306
307/* linewrap the word just before the cursor.
308 * returns 0 on success
309 * returns -1 if we could not wrap.
310 */
311int _owl_editwin_linewrap_word(owl_editwin *e)
312{
313  int i, z;
314
315  z=_owl_editwin_get_index_from_xy(e);
316  /* move back and line wrap the previous word */
317  for (i=z-1; ; i--) {
318    /* move back until you find a space or hit the beginning of the line */
319    if (e->buff[i]==' ') {
320      /* replace the space with a newline */
321      e->buff[i]='\n';
322      e->buffy++;
323      e->buffx=z-i-1;
324      /* were we on the last line */
325      return(0);
326    } else if (e->buff[i]=='\n' || i<=e->lock) {
327      /* we hit the begginning of the line or the buffer, we cannot
328       * wrap.
329       */
330      return(-1);
331    }
332  }
333}
334
335/* insert a character at the current point (shift later
336 * characters over)
337 */
338void owl_editwin_insert_char(owl_editwin *e, char c)
339{
340 
341  int z, i, ret;
342
343  /* \r is \n */
344  if (c=='\r') {
345    c='\n';
346  }
347
348  if (c=='\n' && e->style==OWL_EDITWIN_STYLE_ONELINE) {
349    /* perhaps later this will change some state that allows the string
350       to be read */
351    return;
352  }
353
354  /* make sure there is enough memory for the new text */
355  if ((e->bufflen+1) > (e->allocated-5)) {
356    _owl_editwin_addspace(e);
357  }
358
359  /* get the insertion point */
360  z=_owl_editwin_get_index_from_xy(e);
361
362  /* If we're going to insert at the last column do word wrapping, unless it's a \n */
363  if ((e->buffx+1==e->wrapcol) && (c!='\n')) {
364    ret=_owl_editwin_linewrap_word(e);
365    if (ret==-1) {
366      /* we couldn't wrap, insert a hard newline instead */
367      owl_editwin_insert_char(e, '\n');
368    }
369  }
370
371  z=_owl_editwin_get_index_from_xy(e);
372  /* shift all the other characters right */
373  for (i=e->bufflen; i>z; i--) {
374    e->buff[i]=e->buff[i-1];
375  }
376
377  /* insert the new one */
378  e->buff[z]=c;
379
380  /* housekeeping */
381  e->bufflen++;
382  e->buff[e->bufflen]='\0';
383
384  /* advance the cursor */
385  if (c=='\n') {
386    e->buffx=0;
387    e->buffy++;
388  } else {
389    e->buffx++;
390  }
391}
392
393/* overwrite the character at the current point with 'c' */
394void owl_editwin_overwrite_char(owl_editwin *e, char c)
395{
396  int z;
397 
398  /* \r is \n */
399  if (c=='\r') {
400    c='\n';
401  }
402
403  if (c=='\n' && e->style==OWL_EDITWIN_STYLE_ONELINE) {
404    /* perhaps later this will change some state that allows the string
405       to be read */
406    return;
407  }
408
409  z=_owl_editwin_get_index_from_xy(e);
410
411  /* only if we are at the end of the buffer do we create new space */
412  if (z==e->bufflen) {
413    if ((e->bufflen+1) > (e->allocated-5)) {
414      _owl_editwin_addspace(e);
415    }
416  }
417 
418  e->buff[z]=c;
419
420  /* housekeeping if we are at the end of the buffer */
421  if (z==e->bufflen) {
422    e->bufflen++;
423    e->buff[e->bufflen]='\0';
424  }
425
426  /* advance the cursor */
427  if (c=='\n') {
428    e->buffx=0;
429    e->buffy++;
430  } else {
431    e->buffx++;
432  }
433
434}
435
436/* delete the character at the current point, following chars
437 * shift left.
438 */ 
439void owl_editwin_delete_char(owl_editwin *e)
440{
441  int z, i;
442
443  if (e->bufflen==0) return;
444 
445  /* get the deletion point */
446  z=_owl_editwin_get_index_from_xy(e);
447
448  if (z==e->bufflen) return;
449
450  for (i=z; i<e->bufflen; i++) {
451    e->buff[i]=e->buff[i+1];
452  }
453  e->bufflen--;
454  e->buff[e->bufflen]='\0';
455}
456
457/* Swap the character at point with the character at point-1 and
458 * advance the pointer.  If point is at beginning of buffer do
459 * nothing.  If point is after the last character swap point-1 with
460 * point-2.  (Behaves as observed in tcsh and emacs). 
461 */
462void owl_editwin_transpose_chars(owl_editwin *e)
463{
464  int z;
465  char tmp;
466
467  if (e->bufflen==0) return;
468 
469  /* get the cursor point */
470  z=_owl_editwin_get_index_from_xy(e);
471
472  if (z==e->bufflen) {
473    /* point is after last character */
474    z--;
475  } 
476
477  if (z-1 < e->lock) {
478    /* point is at beginning of buffer, do nothing */
479    return;
480  }
481
482  tmp=e->buff[z];
483  e->buff[z]=e->buff[z-1];
484  e->buff[z-1]=tmp;
485  owl_editwin_key_right(e);
486}
487
488/* insert 'string' at the current point, later text is shifted
489 * right
490 */
491void owl_editwin_insert_string(owl_editwin *e, char *string)
492{
493  int i, j;
494
495  j=strlen(string);
496  for (i=0; i<j; i++) {
497    owl_editwin_insert_char(e, string[i]);
498  }
499}
500
501/* write 'string' at the current point, overwriting text that is
502 * already there
503 */
504
505void owl_editwin_overwrite_string(owl_editwin *e, char *string)
506{
507  int i, j;
508
509  j=strlen(string);
510  for (i=0; i<j; i++) {
511    owl_editwin_overwrite_char(e, string[i]);
512  }
513}
514
515/* get the index into e->buff for the current cursor
516 * position.
517 */
518int _owl_editwin_get_index_from_xy(owl_editwin *e)
519{
520  int i;
521  char *ptr1, *ptr2;
522
523  if (e->bufflen==0) return(0);
524 
525  /* first go to the yth line */
526  ptr1=e->buff;
527  for (i=0; i<e->buffy; i++) {
528    ptr2=strchr(ptr1, '\n');
529    if (!ptr2) {
530      /* we're already on the last line */
531      break;
532    }
533    ptr1=ptr2+1;
534  }
535
536  /* now go to the xth character */
537  ptr2=strchr(ptr1, '\n');
538  if (!ptr2) {
539    ptr2=e->buff+e->bufflen;
540  }
541
542  if ((ptr2-ptr1) < e->buffx) {
543    ptr1=ptr2-1;
544  } else {
545    ptr1+=e->buffx;
546  }
547
548  /* printf("DEBUG: index is %i\r\n", ptr1-e->buff); */
549  return(ptr1-e->buff);
550}
551
552void _owl_editwin_set_xy_by_index(owl_editwin *e, int index)
553{
554  int z, i;
555
556  z=_owl_editwin_get_index_from_xy(e);
557  if (index>z) {
558    for (i=0; i<index-z; i++) {
559      owl_editwin_key_right(e);
560    }
561  } else if (index<z) {
562    for (i=0; i<z-index; i++) {
563      owl_editwin_key_left(e);
564    }
565  }
566}
567
568void owl_editwin_adjust_for_locktext(owl_editwin *e)
569{
570  /* if we happen to have the cursor over locked text
571   * move it to be out of the locktext region */
572  if (_owl_editwin_get_index_from_xy(e)<e->lock) {
573    _owl_editwin_set_xy_by_index(e, e->lock);
574  }
575}
576
577void owl_editwin_backspace(owl_editwin *e)
578{
579  /* delete the char before the current one
580   * and shift later chars left
581   */
582  if (_owl_editwin_get_index_from_xy(e) > e->lock) {
583    owl_editwin_key_left(e);
584    owl_editwin_delete_char(e);
585  }
586  owl_editwin_adjust_for_locktext(e);
587}
588
589void owl_editwin_key_up(owl_editwin *e)
590{
591  if (e->buffy > 0) e->buffy--;
592  if (e->buffx >= owl_editwin_get_numchars_on_line(e, e->buffy)) {
593    e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
594  }
595
596  /* do we need to scroll? */
597  if (e->buffy-e->topline < 0) {
598    e->topline-=e->winlines/2;
599  }
600
601  owl_editwin_adjust_for_locktext(e);
602}
603
604void owl_editwin_key_down(owl_editwin *e)
605{
606  /* move down if we can */
607  if (e->buffy+1 < owl_editwin_get_numlines(e)) e->buffy++;
608
609  /* if we're past the last character move back */
610  if (e->buffx >= owl_editwin_get_numchars_on_line(e, e->buffy)) {
611    e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
612  }
613
614  /* do we need to scroll? */
615  if (e->buffy-e->topline > e->winlines) {
616    e->topline+=e->winlines/2;
617  }
618
619  /* adjust for locktext */
620  owl_editwin_adjust_for_locktext(e);
621}
622
623void owl_editwin_key_left(owl_editwin *e)
624{
625  /* move left if we can, and maybe up a line */
626  if (e->buffx>0) {
627    e->buffx--;
628  } else if (e->buffy>0) {
629    e->buffy--;
630    e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
631  }
632
633  /* do we need to scroll up? */
634  if (e->buffy-e->topline < 0) {
635    e->topline-=e->winlines/2;
636  }
637
638  /* make sure to avoid locktext */
639  owl_editwin_adjust_for_locktext(e);
640}
641
642void owl_editwin_key_right(owl_editwin *e)
643{
644  int i;
645
646  /* move right if we can, and skip down a line if needed */
647  i=owl_editwin_get_numchars_on_line(e, e->buffy);
648  if (e->buffx < i) {
649    e->buffx++;
650    /*  } else if (e->buffy+1 < owl_editwin_get_numlines(e)) { */
651  } else if (_owl_editwin_get_index_from_xy(e) < e->bufflen) {
652    if (e->style==OWL_EDITWIN_STYLE_MULTILINE) {
653      e->buffx=0;
654      e->buffy++;
655    }
656  }
657
658  /* do we need to scroll down? */
659  if (e->buffy-e->topline >= e->winlines) {
660    e->topline+=e->winlines/2;
661  }
662}
663
664void owl_editwin_move_to_nextword(owl_editwin *e)
665{
666  int i, x;
667
668  /* if we're starting on a space, find the first non-space */
669  i=_owl_editwin_get_index_from_xy(e);
670  if (e->buff[i]==' ') {
671    for (x=i; x<e->bufflen; x++) {
672      if (e->buff[x]!=' ' && e->buff[x]!='\n') {
673        _owl_editwin_set_xy_by_index(e, x);
674        break;
675      }
676    }
677  }
678
679  /* find the next space, newline or end of line and go there, if
680     already at the end of the line, continue on to the next */
681  i=owl_editwin_get_numchars_on_line(e, e->buffy);
682  if (e->buffx < i) {
683    /* move right till end of line */
684    while (e->buffx < i) {
685      e->buffx++;
686      if (e->buff[_owl_editwin_get_index_from_xy(e)]==' ') return;
687      if (e->buffx == i) return;
688    }
689  } else if (e->buffx == i) {
690    /* try to move down */
691    if (e->style==OWL_EDITWIN_STYLE_MULTILINE) {
692      if (e->buffy+1 <  owl_editwin_get_numlines(e)) {
693        e->buffx=0;
694        e->buffy++;
695        owl_editwin_move_to_nextword(e);
696      }
697    }
698  }
699}
700
701/* go backwards to the last non-space character
702 */
703void owl_editwin_move_to_previousword(owl_editwin *e)
704{
705  int i, x;
706
707  /* are we already at the beginning of the word? */
708  i=_owl_editwin_get_index_from_xy(e);
709  if ( (e->buff[i]!=' ' && e->buff[i]!='\n' && e->buff[i]!='\0') &&
710       (e->buff[i-1]==' ' || e->buff[i-1]=='\n') ) {
711    owl_editwin_key_left(e);
712  }
713   
714  /* are we starting on a space character? */
715  i=_owl_editwin_get_index_from_xy(e);
716  if (e->buff[i]==' ' || e->buff[i]=='\n' || e->buff[i]=='\0') {
717    /* find the first non-space */
718    for (x=i; x>=e->lock; x--) {
719      if (e->buff[x]!=' ' && e->buff[x]!='\n' && e->buff[x]!='\0') {
720        _owl_editwin_set_xy_by_index(e, x);
721        break;
722      }
723    }
724  }
725
726  /* find the last non-space */
727  i=_owl_editwin_get_index_from_xy(e);
728  for (x=i; x>=e->lock; x--) {
729    if (e->buff[x-1]==' ' || e->buff[x-1]=='\n') {
730      _owl_editwin_set_xy_by_index(e, x);
731      break;
732    }
733  }
734  _owl_editwin_set_xy_by_index(e, x);
735}
736
737
738void owl_editwin_delete_nextword(owl_editwin *e)
739{
740  int z;
741
742  if (e->bufflen==0) return;
743
744  /* if we start out on a space character then gobble all the spaces
745     up first */
746  while (1) {
747    z=_owl_editwin_get_index_from_xy(e);
748    if (e->buff[z]==' ' || e->buff[z]=='\n') {
749      owl_editwin_delete_char(e);
750    } else {
751      break;
752    }
753  }
754
755  /* then nuke the next word */
756  while (1) {
757    z=_owl_editwin_get_index_from_xy(e);
758    /* z == e->bufflen check added to prevent a hang I (nelhage) have
759       seen repeatedly while using owl. I'm not sure precisely what
760       conditions lead to it. */
761    if (z == e->bufflen
762        || e->buff[z+1]==' ' || e->buff[z+1]=='\n' || e->buff[z+1]=='\0') break;
763    owl_editwin_delete_char(e);
764  }
765  owl_editwin_delete_char(e);
766}
767
768void owl_editwin_delete_previousword(owl_editwin *e)
769{
770  /* go backwards to the last non-space character, then delete chars */
771  int i, startpos, endpos;
772
773  startpos = _owl_editwin_get_index_from_xy(e);
774  owl_editwin_move_to_previousword(e);
775  endpos = _owl_editwin_get_index_from_xy(e);
776  for (i=0; i<startpos-endpos; i++) {
777    owl_editwin_delete_char(e);
778  }
779}
780
781void owl_editwin_delete_to_endofline(owl_editwin *e)
782{
783  int i;
784
785  if (owl_editwin_get_numchars_on_line(e, e->buffy)>e->buffx) {
786    /* normal line */
787    i=_owl_editwin_get_index_from_xy(e);
788    while(i < e->bufflen) {
789      if (e->buff[i]!='\n') {
790        owl_editwin_delete_char(e);
791      } else if ((e->buff[i]=='\n') && (i==e->bufflen-1)) {
792        owl_editwin_delete_char(e);
793      } else {
794        return;
795      }
796    }
797  } else if (e->buffy+1 < owl_editwin_get_numlines(e)) {
798    /* line with cursor at the end but not on very last line */
799    owl_editwin_key_right(e);
800    owl_editwin_backspace(e);
801  }
802}
803
804void owl_editwin_move_to_line_end(owl_editwin *e)
805{
806  e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
807}
808
809void owl_editwin_move_to_line_start(owl_editwin *e)
810{
811  e->buffx=0;
812  owl_editwin_adjust_for_locktext(e);
813}
814
815void owl_editwin_move_to_end(owl_editwin *e)
816{
817  /* go to last char */
818  e->buffy=owl_editwin_get_numlines(e)-1;
819  e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
820  owl_editwin_key_right(e);
821
822  /* do we need to scroll? */
823  /*
824  if (e->buffy-e->topline > e->winlines) {
825    e->topline+=e->winlines/2;
826  }
827  */
828  owl_editwin_recenter(e);
829}
830
831void owl_editwin_move_to_top(owl_editwin *e)
832{
833  _owl_editwin_set_xy_by_index(e, 0);
834
835  /* do we need to scroll? */
836  e->topline=0;
837
838  owl_editwin_adjust_for_locktext(e);
839}
840
841void owl_editwin_fill_paragraph(owl_editwin *e)
842{
843  int i, save;
844
845  /* save our starting point */
846  save=_owl_editwin_get_index_from_xy(e);
847
848  /* scan back to the beginning of this paragraph */
849  for (i=save; i>=e->lock; i--) {
850    if ( (i<=e->lock) ||
851         ((e->buff[i]=='\n') && (e->buff[i-1]=='\n'))) {
852      _owl_editwin_set_xy_by_index(e, i+1);
853      break;
854    }
855  }
856
857  /* main loop */
858  while (1) {
859    i=_owl_editwin_get_index_from_xy(e);
860
861    /* bail if we hit the end of the buffer */
862    if (i>=e->bufflen) break;
863
864    /* bail if we hit the end of the paragraph */
865    if (e->buff[i]=='\n' && e->buff[i+1]=='\n') break;
866
867    /* if we've travelled too far, linewrap */
868    if ((e->buffx) >= e->fillcol) {
869      _owl_editwin_linewrap_word(e);
870    }
871
872    /* did we hit the end of a line too soon? */
873    i=_owl_editwin_get_index_from_xy(e);
874    if (e->buff[i]=='\n' && e->buffx<e->fillcol-1) {
875      /* ********* we need to make sure we don't pull in a word that's too long ***********/
876      e->buff[i]=' ';
877    }
878   
879    /* fix spacing */
880    i=_owl_editwin_get_index_from_xy(e);
881    if (e->buff[i]==' ' && e->buff[i+1]==' ') {
882      if (e->buff[i-1]=='.' || e->buff[i-1]=='!' || e->buff[i-1]=='?') {
883        owl_editwin_key_right(e);
884      } else {
885        owl_editwin_delete_char(e);
886        /* if we did this ahead of the save point, adjust it */
887        if (i<save) save--;
888      }
889    } else {
890      owl_editwin_key_right(e);
891    }
892
893  }
894
895  /* put cursor back at starting point */
896  _owl_editwin_set_xy_by_index(e, save);
897
898  /* do we need to scroll? */
899  if (e->buffy-e->topline < 0) {
900    e->topline-=e->winlines/2;
901  }
902}
903
904/* returns true if only whitespace remains */
905int owl_editwin_is_at_end(owl_editwin *e)
906{
907  int cur=_owl_editwin_get_index_from_xy(e);
908  return (only_whitespace(e->buff+cur));
909}
910
911int owl_editwin_check_dotsend(owl_editwin *e)
912{
913  int i;
914
915  if (!e->dotsend) return(0);
916  for (i=e->bufflen-1; i>0; i--) {
917    if (e->buff[i] == '.' 
918        && (e->buff[i-1] == '\n' || e->buff[i-1] == '\r')
919        && (e->buff[i+1] == '\n' || e->buff[i+1] == '\r')) {
920      e->bufflen = i;
921      e->buff[i] = '\0';
922      return(1);
923    }
924    if (!isspace((int) e->buff[i])) {
925      return(0);
926    }
927  }
928  return(0);
929}
930
931void owl_editwin_post_process_char(owl_editwin *e, int j)
932{
933  /* check if we need to scroll down */
934  if (e->buffy-e->topline >= e->winlines) {
935    e->topline+=e->winlines/2;
936  }
937  if ((j==13 || j==10) && owl_editwin_check_dotsend(e)) {
938    owl_command_editmulti_done(e);
939    return;
940  }
941  owl_editwin_redisplay(e, 0); 
942}
943
944void owl_editwin_process_char(owl_editwin *e, int j)
945{
946  if (j == ERR) return;
947  if (j>127 || ((j<32) && (j!=10) && (j!=13))) {
948    return;
949  } else {
950    owl_editwin_insert_char(e, j);
951  }
952}
953
954char *owl_editwin_get_text(owl_editwin *e)
955{
956  return(e->buff+e->lock);
957}
958
959int owl_editwin_get_numchars_on_line(owl_editwin *e, int line)
960{
961  int i;
962  char *ptr1, *ptr2;
963
964  if (e->bufflen==0) return(0);
965 
966  /* first go to the yth line */
967  ptr1=e->buff;
968  for (i=0; i<line; i++) {
969    ptr2=strchr(ptr1, '\n');
970    if (!ptr2) {
971      /* we're already on the last line */
972      return(0);
973    }
974    ptr1=ptr2+1;
975  }
976
977  /* now go to the xth character */
978  ptr2=strchr(ptr1, '\n');
979  if (!ptr2) {
980    return(e->buff + e->bufflen - ptr1);
981  }
982  return(ptr2-ptr1); /* don't count the newline for now */
983}
984
985int owl_editwin_get_numlines(owl_editwin *e)
986{
987  return(owl_text_num_lines(e->buff));
988}
989
Note: See TracBrowser for help on using the repository browser.