source: editwin.c @ 5b5f3e6

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