Changeset 5b5f3e6 for editwin.c


Ignore:
Timestamp:
Jul 11, 2009, 1:14:34 PM (15 years ago)
Author:
Nelson Elhage <nelhage@mit.edu>
Branches:
master, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
7d25006
Parents:
98f1e69
git-author:
Karl Ramm <kcr@1ts.org> (06/10/09 03:29:20)
git-committer:
Nelson Elhage <nelhage@mit.edu> (07/11/09 13:14:34)
Message:
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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • editwin.c

    r98f1e69 r5b5f3e6  
    3939static int owl_editwin_limit_maxcols(int v, int maxv);
    4040static int owl_editwin_check_dotsend(owl_editwin *e);
    41 static void _owl_editwin_process_char(owl_editwin *e, gunichar j);
    4241static int owl_editwin_is_char_in(owl_editwin *e, char *set);
    43 static int owl_editwin_is_char_in(owl_editwin *e, char *set);
    44 static int owl_editwin_linewrap_word(owl_editwin *e);
    4542static gunichar owl_editwin_get_char_at_point(owl_editwin *e);
    46 
    47 static void _owl_editwin_addspace(owl_editwin *e);
    48 static void owl_editwin_overwrite_char(owl_editwin *e, gunichar c);
    49 static void owl_editwin_insert_char(owl_editwin *e, gunichar c);
    50 static void owl_editwin_overwrite_string(owl_editwin *e, char *string);
    51 
    52 #define INCR 5000
     43static void owl_editwin_replace(owl_editwin *e, int count, char *s);
     44static int oe_count_glyphs(char *s);
     45
     46#define INCR 4096
    5347
    5448#define WHITESPACE " \n\t"
     
    5751{
    5852  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;
    5965}
    6066
     
    192198{
    193199  oe_set_index(e, 0);
    194   owl_editwin_overwrite_string(e, text);
    195   owl_editwin_overwrite_char(e, '\0');
    196   e->lock=strlen(text);
     200  e->lock = 0;
     201  owl_editwin_replace(e, e->bufflen, text);
     202  e->buff[e->bufflen] = 0;
     203  e->lock=e->bufflen;
    197204  oe_set_index(e, e->lock);
    198205  owl_editwin_redisplay(e, 0);
     
    206213void owl_editwin_new_style(owl_editwin *e, int newstyle, owl_history *h)
    207214{
    208   char *ptr;
    209 
    210215  e->hist = h;
    211216
     
    218223
    219224    /* nuke everything after the first line */
    220     if (e->bufflen > 0) {
    221       ptr=strchr(e->buff, '\n')-1;
    222       if (ptr) {
    223         e->bufflen=ptr - e->buff;
    224         e->buff[e->bufflen]='\0';
    225         oe_set_index(e, 0);
    226       }
    227     }
     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),  "");
    228228  }
    229229}
     
    248248
    249249  if (lock > 0) {
    250     locktext=owl_malloc(e->lock+20);
    251     strncpy(locktext, e->buff, e->lock);
    252     locktext[e->lock]='\0';
     250    locktext = owl_malloc(lock+1);
     251    strncpy(locktext, e->buff, lock);
     252    locktext[lock] = 0;
    253253  }
    254254
     
    266266  }
    267267
    268   if (locktext) owl_free(locktext);
     268  if (locktext)
     269    owl_free(locktext);
    269270
    270271  oe_set_index(e, lock);
    271 }
    272 
    273 /* malloc more space for the buffer */
    274 static void _owl_editwin_addspace(owl_editwin *e)
    275 {
    276   e->buff=owl_realloc(e->buff, e->allocated+INCR);
    277   if (!e->buff) {
    278     /* error *//*XXXXXXXXXXXXXXXX*/
    279     return;
    280   }
    281   e->allocated+=INCR;
    282272}
    283273
     
    449439}
    450440
    451 /* Remove n bytes at cursor. */
    452 void _owl_editwin_remove_bytes(owl_editwin *e, int n) /*noproto*/
    453 {
    454   int i = e->index + n;
    455   for (; i < e->bufflen; i++) {
    456     e->buff[i-n] = e->buff[i];
    457   }
    458 
    459   e->bufflen -= n;
    460   e->buff[e->bufflen] = '\0';
    461 }
    462 
    463 /* Insert n bytes at cursor.*/
    464 void _owl_editwin_insert_bytes(owl_editwin *e, int n) /*noproto*/
    465 {
    466   int i;
    467 
    468   if ((e->bufflen + n) > (e->allocated - 5)) {
    469     _owl_editwin_addspace(e);
    470   }
    471 
    472   if(e->index != e->bufflen) {
    473     for (i = e->bufflen + n - 1; i > e->index; i--) {
    474       e->buff[i] = e->buff[i - n];
    475     }
    476   }
    477 
    478   e->bufflen += n;
    479   e->buff[e->bufflen] = '\0';
    480 
    481 }
    482 
    483 
     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*/
    484480/* linewrap the word just before the cursor.
    485481 * returns 0 on success
    486482 * returns -1 if we could not wrap.
    487483 */
    488 static int owl_editwin_linewrap_word(owl_editwin *e)
     484static int _owl_editwin_linewrap_word(owl_editwin *e)
    489485{
    490486  int i;
     
    517513  return -1;
    518514}
    519 
    520 /* insert a character at the current point (shift later
    521  * characters over)
    522  */
    523 static void owl_editwin_insert_char(owl_editwin *e, gunichar c)
    524 {
    525   int i, ret, len;
    526   char tmp[6];
    527   memset(tmp, '\0', 6);
    528 
    529   /* \r is \n */
    530   if (c == '\r') {
    531     c = '\n';
    532   }
    533 
    534   if (c == '\n' && e->style == OWL_EDITWIN_STYLE_ONELINE) {
    535     /* perhaps later this will change some state that allows the string
    536        to be read */
    537     return;
    538   }
    539 
    540   g_unichar_to_utf8(c, tmp);
    541   len = strlen(tmp);
    542 
    543   /* make sure there is enough memory for the new text */
    544   if ((e->bufflen + len) > (e->allocated - 5)) {
    545     _owl_editwin_addspace(e);
    546   }
    547 
    548   /* If we're going to insert at the last column do word wrapping, unless it's a \n */
    549 #if 0 /* XXX */
    550   if ((e->buffx + 1 == e->wrapcol) && (c != '\n')) {
    551     ret = _owl_editwin_linewrap_word(e);
    552     if (ret == -1) {
    553       /* we couldn't wrap, insert a hard newline instead */
    554       owl_editwin_insert_char(e, '\n');
    555     }
    556   }
    557515#endif
    558 
    559   /* shift all the other characters right */
    560   _owl_editwin_insert_bytes(e, len);
    561 
    562   /* insert the new character */
    563   for(i = 0; i < len; i++) {
    564     e->buff[e->index + i] = tmp[i];
    565   }
    566 
    567   /* advance the cursor */
    568   oe_set_index(e, e->index + len);
    569 }
    570 
    571 /* overwrite the character at the current point with 'c' */
    572 static void owl_editwin_overwrite_char(owl_editwin *e, gunichar c)
    573 {
    574   int oldlen, newlen, i;
    575   char tmp[6], *t;
    576   memset(tmp, '\0', 6);
    577 
    578   /* \r is \n */
    579   if (c == '\r') {
    580     c = '\n';
    581   }
    582 
    583   if (c == '\n' && e->style == OWL_EDITWIN_STYLE_ONELINE) {
    584     /* perhaps later this will change some state that allows the string
    585        to be read */
    586     return;
    587   }
    588 
    589   g_unichar_to_utf8(c, tmp);
    590   newlen = strlen(tmp);
    591 
    592   t = g_utf8_find_next_char(e->buff + e->index, NULL);
    593   oldlen = (t ? (t - (e->buff + e->index)) : 0);
    594 
    595   /* only if we are at the end of the buffer do we create new space here */
    596   if (e->index == e->bufflen) {
    597     if ((e->bufflen+newlen) > (e->allocated-5)) {
    598       _owl_editwin_addspace(e);
    599     }
    600   }
    601   /* if not at the end of the buffer, adjust based in char size difference. */
    602   else if (oldlen > newlen) {
    603     _owl_editwin_remove_bytes(e, oldlen-newlen);
    604   }
    605   else /* oldlen < newlen */ {
    606     _owl_editwin_insert_bytes(e, newlen-oldlen);
    607   }
    608   /* Overwrite the old char*/
    609   for (i = 0; i < newlen; i++) {
    610     e->buff[e->index + i] = tmp[i];
    611   }
    612 
    613   /* housekeeping */
    614   if (e->index == e->bufflen) {
    615     e->bufflen += newlen;
    616     e->buff[e->bufflen] = '\0';
    617   }
    618 
    619   /* advance the cursor */
    620   oe_set_index(e, e->index + newlen);
    621 }
    622516
    623517/* delete the character at the current point, following chars
     
    626520void owl_editwin_delete_char(owl_editwin *e)
    627521{
    628   char *p1, *p2;
    629   gunichar c;
    630 
    631   if (e->bufflen == 0) return;
    632 
    633   if (e->index == e->bufflen) return;
    634 
    635   p1 = e->buff + e->index;
    636   p2 = g_utf8_next_char(p1);
    637   c = g_utf8_get_char(p2);
    638   while (g_unichar_ismark(c)) {
    639     p2 = g_utf8_next_char(p2);
    640     c = g_utf8_get_char(p2);
    641   }
    642   _owl_editwin_remove_bytes(e, p2-p1);
     522  owl_editwin_replace(e, 1, "");
    643523}
    644524
     
    650530void owl_editwin_transpose_chars(owl_editwin *e)
    651531{
    652   char *p1, *p2, *p3, *tmp;
     532  char *middle, *end, *start, *tmp;
    653533
    654534  if (e->bufflen == 0) return;
    655535
    656   if (e->index == e->bufflen) {
    657     /* point is after last character */
    658     oe_set_index(e, e->index - 1);
    659   }
    660 
    661   if (e->index - 1 < e->lock) {
    662     /* point is at beginning of buffer, do nothing */
     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)
    663547    return;
    664   }
    665 
    666   /* Transpose two utf-8 unicode glyphs. */
    667   p1 = e->buff + e->index;
    668 
    669   p2 = oe_next_point(e, p1); /* XXX make sure we can't transpose past the end
    670                                 of the buffer */
    671   if (p2 == NULL)
     548
     549  start = oe_prev_point(e, middle);
     550  if (start == NULL)
    672551    return;
    673552
    674   p3 = oe_prev_point(e, p1);
    675   if (p3 == NULL)
    676     return;
    677 
    678   tmp = owl_malloc(p2 - p3 + 5);
    679   *tmp = '\0';
    680   strncat(tmp, p1, p2 - p1);
    681   strncat(tmp, p3, p1 - p3);
    682   strncpy(p3, tmp, p2 - p3);
    683   owl_free(tmp);
    684   oe_set_index(e, p3 - e->buff);
     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);
    685560}
    686561
     
    688563 * right
    689564 */
    690 void owl_editwin_insert_string(owl_editwin *e, char *string)
    691 {
    692   char *p;
    693   gunichar c;
    694   if (!g_utf8_validate(string, -1, NULL)) {
    695     owl_function_debugmsg("owl_editwin_insert_string: received non-utf-8 string.");
    696     return;
    697   }
    698   p = string;
    699   c = g_utf8_get_char(p);
    700   while (c) {
    701     _owl_editwin_process_char(e, c);
    702     p = g_utf8_next_char(p);
    703     c = g_utf8_get_char(p);
    704   }
    705 }
    706 
    707 /* write 'string' at the current point, overwriting text that is
    708  * already there
    709  */
    710 
    711 static void owl_editwin_overwrite_string(owl_editwin *e, char *string)
    712 {
    713   char *p;
    714   gunichar c;
    715 
    716   if (!g_utf8_validate(string, -1, NULL)) {
    717     owl_function_debugmsg("owl_editwin_overwrite_string: received non-utf-8 string.");
    718     return;
    719   }
    720   p = string;
    721   c = g_utf8_get_char(p);
    722   while (c) {
    723     owl_editwin_overwrite_char(e, c);
    724     p = g_utf8_next_char(p);
    725     c = g_utf8_get_char(p);
    726   }
     565void owl_editwin_insert_string(owl_editwin *e, char *s)
     566{
     567  owl_editwin_replace(e, 0, s);
    727568}
    728569
     
    788629{
    789630  char *p;
    790   /* It would be awfully nice if we could do UTF-8 comparisons */
    791   for (p = set; *p != 0; p++)
    792     if (owl_editwin_get_char_at_point(e) == *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))
    793634      return 1;
    794635  return 0;
     
    902743}
    903744
     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
    904757void owl_editwin_move_to_nextword(owl_editwin *e)
    905758{
    906   /* if we're starting on a space, find the first non-space */
    907   owl_editwin_move_if_in(e, 1, WHITESPACE);
    908 
    909   /* now find the end of this word */
    910   owl_editwin_move_if_not_in(e, 1, WHITESPACE);
     759  owl_editwin_forward_word(e);
    911760}
    912761
    913762/* go backwards to the last non-space character
    914763 */
    915 void owl_editwin_move_to_previousword(owl_editwin *e)
     764int owl_editwin_backward_word(owl_editwin *e)
    916765{
    917766  oe_excursion x;
     767  int distance = 0;
     768  int further = 0;
    918769  int beginning;
    919770  /* if in middle of word, beginning of word */
     
    923774  if (owl_editwin_is_char_in(e, WHITESPACE)) {
    924775    /* if in whitespace past end of word, find a word , the find the beginning*/
    925     owl_editwin_move_if_in(e, -1, WHITESPACE); /* leaves us on the last
    926                                                     character of the word */
     776    distance += owl_editwin_move_if_in(e, -1, WHITESPACE); /* leaves us on the last
     777                                                              character of the word */
    927778    oe_save_excursion(e, &x);
    928779    /* are we at the beginning of a word? */
     
    931782    oe_restore_excursion(e, &x);
    932783    if (beginning)
    933       return;
     784      return distance;
    934785   } else {
    935786    /* in the middle of the word; */
    936787    oe_save_excursion(e, &x);
    937     owl_editwin_point_move(e, -1);
     788    further += owl_editwin_point_move(e, -1);
    938789    if (owl_editwin_is_char_in(e, WHITESPACE)) { /* we were at the beginning */
    939       owl_editwin_move_to_previousword(e); /* previous case */
    940       return;
     790      distance += owl_editwin_backward_word(e); /* previous case */
     791      return distance + further;
    941792    } else {
    942793      oe_restore_excursion(e, &x);
    943794    }
    944795  }
    945   owl_editwin_move_if_not_in(e, -1, WHITESPACE);
     796  distance += owl_editwin_move_if_not_in(e, -1, WHITESPACE);
    946797  /* will go past */
    947798  if (e->index > e->lock)
    948     owl_editwin_point_move(e, 1);
     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);
    949806}
    950807
     
    952809{
    953810  oe_excursion x;
    954   int end;
     811  int distance;
    955812
    956813  oe_save_excursion(e, &x);
    957   owl_editwin_move_to_nextword(e);
    958   end = e->index;
     814  distance = owl_editwin_forward_word(e);
    959815  oe_restore_excursion(e, &x);
    960   _owl_editwin_remove_bytes(e, end - e->index);
     816  owl_editwin_replace(e, distance, "");
    961817}
    962818
     
    964820{
    965821  /* go backwards to the last non-space character, then delete chars */
    966   int startpos, endpos;
    967 
    968   startpos = e->index;
    969   owl_editwin_move_to_previousword(e);
    970   endpos = e->index;
    971   _owl_editwin_remove_bytes(e, startpos-endpos);
     822  int distance;
     823
     824  distance = owl_editwin_backward_word(e);
     825  owl_editwin_replace(e, -distance, "");
    972826}
    973827
     
    980834{
    981835  oe_excursion x;
    982   int end;
     836  int distance;
    983837
    984838  oe_save_excursion(e, &x);
    985   owl_editwin_move_to_line_end(e);
    986   end = e->index;
     839  distance = owl_editwin_move_to_end_of_line(e);
    987840  oe_restore_excursion(e, &x);
    988   if (end - e->index)
    989     _owl_editwin_remove_bytes(e, end - e->index);
    990   else if (end < e->bufflen)
    991     _owl_editwin_remove_bytes(e, 1);
     841  owl_editwin_replace(e, distance ? distance : 1, "");
    992842}
    993843
     
    1127977}
    1128978
    1129 static void _owl_editwin_process_char(owl_editwin *e, gunichar j)
    1130 {
    1131   if (!(g_unichar_iscntrl(j) && (j != 10) && (j != 13)) || j==9 ) {
    1132     owl_editwin_insert_char(e, j);
    1133   }
    1134 }
    1135 
    1136 
    1137979void owl_editwin_process_char(owl_editwin *e, owl_input j)
    1138980{
    1139   if (j.ch == ERR) return;
     981#if 0
     982  int i, ret, len;
     983#endif
     984  char tmp[7];
     985
     986  if (j.ch == ERR)
     987    return;
    1140988  /* Ignore ncurses control characters. */
    1141989  if (j.ch < 0x100) {
    1142     _owl_editwin_process_char(e, j.uch);
     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    }
    11431016  }
    11441017}
Note: See TracChangeset for help on using the changeset viewer.