source: editwin.c @ dab82f29

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