Changeset dfb6c7d


Ignore:
Timestamp:
Feb 22, 2008, 10:59:41 AM (17 years ago)
Author:
Alejandro R. Sedeño <asedeno@mit.edu>
Branches:
master, barnowl_perlaim, debian, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
f8d9df1
Parents:
c020e73 (diff), b24029a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:
Merged revisions 958-963 via svnmerge from 
file:///afs/sipb.mit.edu/project/barnowl/src/svn/trunk

........
  r960 | chmrr | 2008-02-19 20:48:44 -0500 (Tue, 19 Feb 2008) | 3 lines
  
   r2008@utwig:  chmrr | 2008-02-19 20:48:27 -0500
    * Fix admin messages
........
  r963 | asedeno | 2008-02-22 10:58:32 -0500 (Fri, 22 Feb 2008) | 1 line
  
  resize should always refresh the editwin.
........
Files:
2 added
28 edited
1 moved

Legend:

Unmodified
Added
Removed
  • global.c

    r5f3168a rdfb6c7d  
    444444  owl_mainwin_redisplay(&(g->mw));
    445445  sepbar(NULL);
    446 
    447   if (owl_global_is_typwin_active(g)) {
    448     owl_editwin_redisplay(&(g->tw), 0);
    449   }     
     446  owl_editwin_redisplay(&(g->tw), 0);
     447
    450448  /* TODO: this should handle other forms of popwins */
    451449  if (owl_popwin_is_active(owl_global_get_popwin(g))
  • perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm

    r9c7a701 r1951db8  
    125125    BarnOwl::admin_message("IRC",
    126126            BarnOwl::Style::boldify('IRC ' . $evt->type . ' message from '
    127                 . $evt->alias) . "\n"
     127                . $self->alias) . "\n"
    128128            . strip_irc_formatting(join '\n', cdr $evt->args));
    129129}
  • Makefile.in

    r9c7a701 r5f3168a  
    2626     keypress.c keymap.c keybinding.c cmd.c context.c zcrypt.c \
    2727     aim.c buddy.c buddylist.c timer.c style.c stylefunc.c errqueue.c \
    28      zbuddylist.c muxevents.c popexec.c obarray.c select.c
     28     zbuddylist.c muxevents.c popexec.c obarray.c select.c wcwidth.c \
     29     glib_compat.c
    2930OWL_SRC = owl.c
    3031TESTER_SRC = tester.c
  • aim.c

    r9854278 r34509d5  
    948948 
    949949  if (modname) {
    950     if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
     950    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
    951951      /* perror("memrequest: malloc"); */
    952952      return -1;
     
    954954    sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
    955955  } else {
    956     if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
     956    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
    957957      /* perror("memrequest: malloc"); */
    958958      return -1;
     
    964964    if (!modname) {
    965965      /* perror("memrequest: stat"); */
    966       free(filename);
     966      owl_free(filename);
    967967      return -1;
    968968    }
     
    986986    int i;
    987987   
    988     free(filename); /* not needed */
     988    owl_free(filename); /* not needed */
    989989    owl_function_error("getaimdata memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
    990990    i = 8;
     
    993993    }
    994994   
    995     if (!(buf = malloc(i))) {
     995    if (!(buf = owl_malloc(i))) {
    996996      return -1;
    997997    }
     
    10171017    *buflenret = i;
    10181018  } else {
    1019     if (!(buf = malloc(len))) {
    1020       free(filename);
     1019    if (!(buf = owl_malloc(len))) {
     1020      owl_free(filename);
    10211021      return -1;
    10221022    }
     
    10241024    if (!(f = fopen(filename, "r"))) {
    10251025      /* perror("memrequest: fopen"); */
    1026       free(filename);
    1027       free(buf);
     1026      owl_free(filename);
     1027      owl_free(buf);
    10281028      return -1;
    10291029    }
    10301030   
    1031     free(filename);
     1031    owl_free(filename);
    10321032   
    10331033    if (fseek(f, offset, SEEK_SET) == -1) {
    10341034      /* perror("memrequest: fseek"); */
    10351035      fclose(f);
    1036       free(buf);
     1036      owl_free(buf);
    10371037      return -1;
    10381038    }
     
    10411041      /* perror("memrequest: fread"); */
    10421042      fclose(f);
    1043       free(buf);
     1043      owl_free(buf);
    10441044      return -1;
    10451045    }
     
    10761076  if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
    10771077    aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
    1078     free(buf);
     1078    owl_free(buf);
    10791079  } else {
    10801080    owl_function_debugmsg("faimtest_memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
     
    13421342      int z;
    13431343     
    1344       newbuf = malloc(i+1);
     1344      newbuf = owl_malloc(i+1);
    13451345      for (z = 0; z < i; z++)
    13461346        newbuf[z] = (z % 10)+0x30;
    13471347      newbuf[i] = '\0';
    13481348      /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK | AIM_IMFLAGS_AWAY, newbuf); */
    1349       free(newbuf);
     1349      owl_free(newbuf);
    13501350    }
    13511351  } else if (strstr(tmpstr, "seticqstatus")) {
  • cmd.c

    r6922edd r34509d5  
    7474  owl_cmd *cmd;
    7575
    76   tmpbuff=strdup(cmdbuff);
     76  tmpbuff=owl_strdup(cmdbuff);
    7777  argv=owl_parseline(tmpbuff, &argc);
    7878  if (argc < 0) {
  • config.h.in

    r03cf6b9 re23eb2b  
    2222#undef HAVE_LIBCOM_ERR
    2323
    24 /* Define to 1 if you have the `curses' library (-lcurses). */
    25 #undef HAVE_LIBCURSES
    26 
    2724/* Define to 1 if you have the `des425' library (-ldes425). */
    2825#undef HAVE_LIBDES425
     
    3936/* Define to 1 if you have the `krb5' library (-lkrb5). */
    4037#undef HAVE_LIBKRB5
    41 
    42 /* Define to 1 if you have the `ncurses' library (-lncurses). */
    43 #undef HAVE_LIBNCURSES
    4438
    4539/* Define to 1 if you have the `ncursesw' library (-lncursesw). */
  • configure.ac

    r18e28a4 r680ed23  
    1212fi
    1313
     14m4_include(/usr/share/aclocal/pkg.m4)
     15dnl m4_include(pkg.m4)
    1416
    1517dnl Check for Athena
     
    4446fi
    4547
    46 AC_CHECK_LIB(ncursesw, initscr,,
    47   AC_CHECK_LIB(ncurses, initscr,,
    48     AC_CHECK_LIB(curses, initscr,, AC_MSG_ERROR(No curses library found.))))
     48AC_CHECK_LIB(ncursesw, initscr,, AC_MSG_ERROR(No curses library found.))
    4949AC_CHECK_LIB(com_err, com_err)
    5050AC_CHECK_LIB(nsl, gethostbyname)
     
    109109LDFLAGS=${LDFLAGS}\ ${FOO}
    110110
     111dnl Add CFLAGS and LDFLAGS for glib-2.0
     112PKG_CHECK_MODULES(GLIB,glib-2.0)
     113
     114echo Adding glib-2.0 CFLAGS ${GLIB_CFLAGS}
     115CFLAGS=${CFLAGS}\ ${GLIB_CFLAGS}
     116echo Adding glib-2.0 LDFLAGS ${GLIB_LIBS}
     117LDFLAGS=${LDFLAGS}\ ${GLIB_LIBS}
     118
     119
    111120dnl Checks for typedefs, structures, and compiler characteristics.
    112121
  • editwin.c

    raf1920fd rc020e73  
    143143  e->buffy=0;
    144144  owl_editwin_overwrite_string(e, text);
     145  owl_editwin_overwrite_char(e, '\0');
    145146  e->lock=strlen(text);
    146147  /* if (text[e->lock-1]=='\n') e->lock--; */
    147   e->buffx=x;
    148   e->buffy=y;
    149   owl_editwin_adjust_for_locktext(e);
     148  /*  e->buffx=x; */
     149  /*  e->buffy=y; */
     150  _owl_editwin_set_xy_by_index(e, e->lock);
    150151  owl_editwin_redisplay(e, 0);
    151152}
     
    255256
    256257  /* start at topline */
    257   ptr1=e->buff;
    258   for (i=0; i<e->topline; i++) {
    259     ptr2=strchr(ptr1, '\n');
     258  ptr1 = e->buff;
     259  for (i = 0; i < e->topline; i++) {
     260    ptr2 = strchr(ptr1, '\n');
    260261    if (!ptr2) {
    261262      /* we're already on the last line */
    262263      break;
    263264    }
    264     ptr1=ptr2+1;
     265    ptr1 = ptr2 + 1;
    265266  }
    266267  /* ptr1 now stores the starting point */
    267268
    268269  /* find the ending point and store it in ptr3 */
    269   ptr2=ptr1;
    270   ptr3=ptr1;
    271   for (i=0; i<e->winlines; i++) {
    272     ptr3=strchr(ptr2, '\n');
     270  ptr2 = ptr1;
     271  ptr3 = ptr1;
     272  for (i = 0; i < e->winlines; i++) {
     273    ptr3 = strchr(ptr2, '\n');
    273274    if (!ptr3) {
    274275      /* we've hit the last line */
    275276      /* print everything to the end */
    276       ptr3=e->buff+e->bufflen-1;
     277      ptr3 = e->buff + e->bufflen - 1;
    277278      ptr3--;
    278279      break;
    279280    }
    280     ptr2=ptr3+1;
    281   }
    282   ptr3+=2;
    283 
    284   buff=owl_malloc(ptr3-ptr1+50);
    285   strncpy(buff, ptr1, ptr3-ptr1);
    286   buff[ptr3-ptr1]='\0';
    287   if (e->echochar=='\0') {
     281    ptr2 = ptr3 + 1;
     282  }
     283  ptr3 += 2;
     284
     285  buff = owl_malloc(ptr3 - ptr1 + 50);
     286  strncpy(buff, ptr1, ptr3 - ptr1);
     287  buff[ptr3 - ptr1] = '\0';
     288  if (e->echochar == '\0') {
    288289    waddstr(e->curswin, buff);
    289290  } else {
    290291    /* translate to echochar, *except* for the locktext */
    291292    int len;
    292     int dolocklen=e->lock-(ptr1-e->buff);
    293 
    294     for (i=0; i<dolocklen; i++) {
    295       waddch(e->curswin, buff[i]);
    296     }
    297     len=strlen(buff);
    298     for (i=0; i<len-dolocklen; i++) {
     293    int dolocklen = e->lock - (ptr1 - e->buff);
     294    char *locktext;
     295    char tmp = e->buff[dolocklen];
     296
     297    e->buff[dolocklen] = '\0';
     298    locktext = owl_strdup(e->buff);
     299    e->buff[dolocklen] = tmp;
     300
     301    waddstr(e->curswin, locktext);
     302   
     303    len = strlen(buff);
     304    for (i = 0; i < len-dolocklen; i++) {
    299305      waddch(e->curswin, e->echochar);
    300306    }
    301307  }
    302   wmove(e->curswin, e->buffy-e->topline, e->buffx);
     308  wmove(e->curswin, e->buffy-e->topline, e->buffx + _owl_editwin_cursor_adjustment(e));
    303309  wnoutrefresh(e->curswin);
    304   if (update==1) {
     310  if (update == 1) {
    305311    doupdate();
    306312  }
    307313  owl_free(buff);
     314}
     315
     316/* Remove n bytes at cursor. */
     317void _owl_editwin_remove_bytes(owl_editwin *e, int n) /*noproto*/
     318{
     319  int i = _owl_editwin_get_index_from_xy(e) + n;
     320  for (; i < e->bufflen; i++) {
     321    e->buff[i-n] = e->buff[i];
     322  }
     323 
     324  e->bufflen -= n;
     325  e->buff[e->bufflen] = '\0';
     326}
     327
     328/* Insert n bytes at cursor.*/
     329void _owl_editwin_insert_bytes(owl_editwin *e, int n) /*noproto*/
     330{
     331  int i, z;
     332 
     333  if ((e->bufflen + n) > (e->allocated - 5)) {
     334    _owl_editwin_addspace(e);
     335  }
     336
     337  e->bufflen += n;
     338  e->buff[e->bufflen] = '\0';
     339 
     340  z = _owl_editwin_get_index_from_xy(e);
     341  for (i = e->bufflen - 1; i > z; i--) {
     342    e->buff[i] = e->buff[i - n];
     343  }
    308344}
    309345
     
    315351int _owl_editwin_linewrap_word(owl_editwin *e)
    316352{
    317   int i, z;
    318 
    319   z=_owl_editwin_get_index_from_xy(e);
    320   /* move back and line wrap the previous word */
    321   for (i=z-1; ; i--) {
    322     /* move back until you find a space or hit the beginning of the line */
    323     if (e->buff[i]==' ') {
    324       /* replace the space with a newline */
    325       e->buff[i]='\n';
    326       e->buffy++;
    327       e->buffx=z-i-1;
    328       /* were we on the last line */
    329       return(0);
    330     } else if (e->buff[i]=='\n' || i<=e->lock) {
    331       /* we hit the begginning of the line or the buffer, we cannot
    332        * wrap.
    333        */
    334       return(-1);
    335     }
    336   }
     353  int x, y;
     354  int i;
     355  char *ptr1, *start;
     356  gunichar c;
     357
     358  /* saving values */
     359  x = e->buffx;
     360  y = e->buffy;
     361  start = e->buff + e->lock;
     362
     363  ptr1 = e->buff + _owl_editwin_get_index_from_xy(e);
     364  ptr1 = g_utf8_find_prev_char(start, ptr1);
     365
     366  while (ptr1) {
     367    c = g_utf8_get_char(ptr1);
     368    if (owl_util_can_break_after(c)) {
     369      if (c != ' ') {
     370        i = ptr1 - e->buff;
     371        _owl_editwin_set_xy_by_index(e, i);
     372        _owl_editwin_insert_bytes(e, 1);
     373        /* _owl_editwin_insert_bytes may move e->buff. */
     374        ptr1 = e->buff + i;
     375      }
     376      *ptr1 = '\n';
     377      return 0;
     378    }
     379    ptr1 = g_utf8_find_prev_char(start, ptr1);
     380  }
     381  return -1;
    337382}
    338383
     
    340385 * characters over)
    341386 */
    342 void owl_editwin_insert_char(owl_editwin *e, char c)
    343 {
    344  
    345   int z, i, ret;
     387void owl_editwin_insert_char(owl_editwin *e, gunichar c)
     388{
     389  int z, i, ret, len;
     390  char tmp[6];
     391  memset(tmp, '\0', 6);
    346392
    347393  /* \r is \n */
    348   if (c=='\r') {
    349     c='\n';
    350   }
    351 
    352   if (c=='\n' && e->style==OWL_EDITWIN_STYLE_ONELINE) {
     394  if (c == '\r') {
     395    c = '\n';
     396  }
     397
     398  if (c == '\n' && e->style == OWL_EDITWIN_STYLE_ONELINE) {
    353399    /* perhaps later this will change some state that allows the string
    354400       to be read */
     
    356402  }
    357403
     404  g_unichar_to_utf8(c, tmp);
     405  len = strlen(tmp);
     406
    358407  /* make sure there is enough memory for the new text */
    359   if ((e->bufflen+1) > (e->allocated-5)) {
     408  if ((e->bufflen + len) > (e->allocated - 5)) {
    360409    _owl_editwin_addspace(e);
    361410  }
    362411
    363412  /* get the insertion point */
    364   z=_owl_editwin_get_index_from_xy(e);
     413  z = _owl_editwin_get_index_from_xy(e);
    365414
    366415  /* If we're going to insert at the last column do word wrapping, unless it's a \n */
    367   if ((e->buffx+1==e->wrapcol) && (c!='\n')) {
    368     ret=_owl_editwin_linewrap_word(e);
    369     if (ret==-1) {
     416  if ((e->buffx + 1 == e->wrapcol) && (c != '\n')) {
     417    ret = _owl_editwin_linewrap_word(e);
     418    if (ret == -1) {
    370419      /* we couldn't wrap, insert a hard newline instead */
    371420      owl_editwin_insert_char(e, '\n');
     
    373422  }
    374423
    375   z=_owl_editwin_get_index_from_xy(e);
    376424  /* shift all the other characters right */
    377   for (i=e->bufflen; i>z; i--) {
    378     e->buff[i]=e->buff[i-1];
    379   }
    380 
    381   /* insert the new one */
    382   e->buff[z]=c;
     425  if (z != e->bufflen) {
     426    _owl_editwin_insert_bytes(e, len);
     427  }
     428
     429  /* insert the new character */
     430  for(i = 0; i < len; i++) {
     431    e->buff[z + i] = tmp[i];
     432  }
    383433
    384434  /* housekeeping */
    385   e->bufflen++;
    386   e->buff[e->bufflen]='\0';
    387 
     435  e->bufflen += len;
     436  e->buff[e->bufflen] = '\0';
     437 
    388438  /* advance the cursor */
    389   if (c=='\n') {
    390     e->buffx=0;
    391     e->buffy++;
    392   } else {
    393     e->buffx++;
    394   }
     439  z += len;
     440  _owl_editwin_set_xy_by_index(e, z);
    395441}
    396442
    397443/* overwrite the character at the current point with 'c' */
    398 void owl_editwin_overwrite_char(owl_editwin *e, char c)
    399 {
    400   int z;
    401  
     444void owl_editwin_overwrite_char(owl_editwin *e, gunichar c)
     445{
     446  int z, oldlen, newlen, i;
     447  char tmp[6];
     448  memset(tmp, '\0', 6);
     449
    402450  /* \r is \n */
    403   if (c=='\r') {
    404     c='\n';
    405   }
    406 
    407   if (c=='\n' && e->style==OWL_EDITWIN_STYLE_ONELINE) {
     451  if (c == '\r') {
     452    c = '\n';
     453  }
     454 
     455  if (c == '\n' && e->style == OWL_EDITWIN_STYLE_ONELINE) {
    408456    /* perhaps later this will change some state that allows the string
    409457       to be read */
     
    411459  }
    412460
    413   z=_owl_editwin_get_index_from_xy(e);
    414 
    415   /* only if we are at the end of the buffer do we create new space */
    416   if (z==e->bufflen) {
    417     if ((e->bufflen+1) > (e->allocated-5)) {
     461  g_unichar_to_utf8(c, tmp);
     462  newlen = strlen(tmp);
     463
     464  z = _owl_editwin_get_index_from_xy(e);
     465  {
     466    char *t = g_utf8_find_next_char(e->buff + z, NULL);
     467    oldlen = (t ? (t - (e->buff + z)) : 0);
     468  }
     469
     470  /* only if we are at the end of the buffer do we create new space here */
     471  if (z == e->bufflen) {
     472    if ((e->bufflen+newlen) > (e->allocated-5)) {
    418473      _owl_editwin_addspace(e);
    419474    }
    420475  }
    421  
    422   e->buff[z]=c;
    423 
    424   /* housekeeping if we are at the end of the buffer */
    425   if (z==e->bufflen) {
    426     e->bufflen++;
    427     e->buff[e->bufflen]='\0';
    428   }
    429 
     476  /* if not at the end of the buffer, adjust based in char size difference. */
     477  else if (oldlen > newlen) {
     478    _owl_editwin_remove_bytes(e, oldlen-newlen);
     479  }
     480  else /* oldlen < newlen */ {
     481    _owl_editwin_insert_bytes(e, newlen-oldlen);
     482  }
     483  /* Overwrite the old char*/
     484  for (i = 0; i < newlen; i++) {
     485    e->buff[z+i] = tmp[i];
     486  }
     487       
     488  /* housekeeping */
     489  if (z == e->bufflen) {
     490    e->bufflen += newlen;
     491    e->buff[e->bufflen] = '\0';
     492  }
     493 
    430494  /* advance the cursor */
    431   if (c=='\n') {
    432     e->buffx=0;
    433     e->buffy++;
    434   } else {
    435     e->buffx++;
    436   }
    437 
     495  z += newlen;
     496  _owl_editwin_set_xy_by_index(e, z);
    438497}
    439498
     
    443502void owl_editwin_delete_char(owl_editwin *e)
    444503{
    445   int z, i;
    446 
    447   if (e->bufflen==0) return;
     504  int z;
     505  char *p1, *p2;
     506  gunichar c;
     507
     508  if (e->bufflen == 0) return;
    448509 
    449510  /* get the deletion point */
    450   z=_owl_editwin_get_index_from_xy(e);
    451 
    452   if (z==e->bufflen) return;
    453 
    454   for (i=z; i<e->bufflen; i++) {
    455     e->buff[i]=e->buff[i+1];
    456   }
    457   e->bufflen--;
    458   e->buff[e->bufflen]='\0';
     511  z = _owl_editwin_get_index_from_xy(e);
     512
     513  if (z == e->bufflen) return;
     514
     515  p1 = e->buff + z;
     516  p2 = g_utf8_next_char(p1);
     517  c = g_utf8_get_char(p2);
     518  while (g_unichar_ismark(c)) {
     519    p2 = g_utf8_next_char(p2);
     520    c = g_utf8_get_char(p2);
     521  }
     522  _owl_editwin_remove_bytes(e, p2-p1);
    459523}
    460524
     
    467531{
    468532  int z;
    469   char tmp;
    470 
    471   if (e->bufflen==0) return;
     533  char *p1, *p2, *p3, *tmp;
     534
     535  if (e->bufflen == 0) return;
    472536 
    473537  /* get the cursor point */
    474   z=_owl_editwin_get_index_from_xy(e);
    475 
    476   if (z==e->bufflen) {
     538  z = _owl_editwin_get_index_from_xy(e);
     539
     540  if (z == e->bufflen) {
    477541    /* point is after last character */
    478542    z--;
    479543  } 
    480544
    481   if (z-1 < e->lock) {
     545  if (z - 1 < e->lock) {
    482546    /* point is at beginning of buffer, do nothing */
    483547    return;
    484548  }
    485549
    486   tmp=e->buff[z];
    487   e->buff[z]=e->buff[z-1];
    488   e->buff[z-1]=tmp;
    489   owl_editwin_key_right(e);
     550  /* Transpose two utf-8 unicode glyphs. */
     551  p1 = e->buff + z;
     552
     553  p2 = g_utf8_find_next_char(p1, NULL);
     554  while (p2 != NULL && g_unichar_ismark(g_utf8_get_char(p2))) {
     555    p2 = g_utf8_find_next_char(p2, NULL);
     556  }
     557  if (p2 == NULL) return;
     558
     559  p3 = g_utf8_find_prev_char(e->buff, p1);
     560  while (p3 != NULL && g_unichar_ismark(g_utf8_get_char(p3))) {
     561    p3 = g_utf8_find_prev_char(p3, NULL);
     562  }
     563  if (p3 == NULL) return;
     564
     565  tmp = owl_malloc(p2 - p3 + 5);
     566  *tmp = '\0';
     567  strncat(tmp, p1, p2 - p1);
     568  strncat(tmp, p3, p1 - p3);
     569  strncpy(p3, tmp, p2 - p3);
     570  owl_free(tmp);
     571  _owl_editwin_set_xy_by_index(e, p3 - e->buff);
    490572}
    491573
     
    495577void owl_editwin_insert_string(owl_editwin *e, char *string)
    496578{
    497   int i, j;
    498 
    499   j=strlen(string);
    500   for (i=0; i<j; i++) {
    501     owl_editwin_insert_char(e, string[i]);
     579  char *p;
     580  gunichar c;
     581  if (!g_utf8_validate(string, -1, NULL)) {
     582    owl_function_debugmsg("owl_editwin_insert_string: received non-utf-8 string.");
     583    return;
     584  }
     585  p = string;
     586  c = g_utf8_get_char(p);
     587  while (c) {
     588    _owl_editwin_process_char(e, c);
     589    p = g_utf8_next_char(p);
     590    c = g_utf8_get_char(p);
    502591  }
    503592}
     
    509598void owl_editwin_overwrite_string(owl_editwin *e, char *string)
    510599{
    511   int i, j;
    512 
    513   j=strlen(string);
    514   for (i=0; i<j; i++) {
    515     owl_editwin_overwrite_char(e, string[i]);
     600  char *p;
     601  gunichar c;
     602
     603  if (!g_utf8_validate(string, -1, NULL)) {
     604    owl_function_debugmsg("owl_editwin_overwrite_string: received non-utf-8 string.");
     605    return;
     606  }
     607  p = string;
     608  c = g_utf8_get_char(p);
     609  while (c) {
     610    owl_editwin_overwrite_char(e, c);
     611    p = g_utf8_next_char(p);
     612    c = g_utf8_get_char(p);
    516613  }
    517614}
     
    524621  int i;
    525622  char *ptr1, *ptr2;
    526 
    527   if (e->bufflen==0) return(0);
     623  gunichar c;
     624
     625  if (e->bufflen == 0) return(0);
    528626 
    529627  /* first go to the yth line */
    530   ptr1=e->buff;
    531   for (i=0; i<e->buffy; i++) {
    532     ptr2=strchr(ptr1, '\n');
     628  ptr1 = e->buff;
     629  for (i = 0; i < e->buffy; i++) {
     630    ptr2= strchr(ptr1, '\n');
    533631    if (!ptr2) {
    534632      /* we're already on the last line */
    535633      break;
    536634    }
    537     ptr1=ptr2+1;
    538   }
    539 
    540   /* now go to the xth character */
    541   ptr2=strchr(ptr1, '\n');
    542   if (!ptr2) {
    543     ptr2=e->buff+e->bufflen;
    544   }
    545 
    546   if ((ptr2-ptr1) < e->buffx) {
    547     ptr1=ptr2-1;
    548   } else {
    549     ptr1+=e->buffx;
    550   }
    551 
    552   /* printf("DEBUG: index is %i\r\n", ptr1-e->buff); */
    553   return(ptr1-e->buff);
    554 }
     635    ptr1 = ptr2 + 1;
     636  }
     637
     638  /* now go to the xth cell */
     639  ptr2 = ptr1;
     640  i = 0;
     641  while (ptr2 != NULL && i < e->buffx && (ptr2 - e->buff) < e->bufflen) {
     642    c = g_utf8_get_char(ptr2);
     643    i += (c == '\n' ? 1 : mk_wcwidth(c));
     644    ptr2 = g_utf8_next_char(ptr2);
     645  }
     646  while(ptr2 != NULL && g_unichar_ismark(g_utf8_get_char(ptr2))) {
     647    ptr2 = g_utf8_next_char(ptr2);
     648  }
     649  if (ptr2 == NULL) return e->bufflen;
     650  return(ptr2 - e->buff);
     651}
     652
     653/* We assume x,y are not set to point to a mid-char */
     654gunichar _owl_editwin_get_char_at_xy(owl_editwin *e)
     655{
     656  return g_utf8_get_char(e->buff + _owl_editwin_get_index_from_xy(e));
     657}
     658
    555659
    556660void _owl_editwin_set_xy_by_index(owl_editwin *e, int index)
    557661{
    558   int z, i;
    559 
    560   z=_owl_editwin_get_index_from_xy(e);
    561   if (index>z) {
    562     for (i=0; i<index-z; i++) {
    563       owl_editwin_key_right(e);
    564     }
    565   } else if (index<z) {
    566     for (i=0; i<z-index; i++) {
    567       owl_editwin_key_left(e);
    568     }
    569   }
     662  char *ptr1, *ptr2, *target;
     663  gunichar c;
     664
     665  e->buffx = 0;
     666  e->buffy = 0;
     667
     668  ptr1 = e->buff;
     669  target = ptr1 + index;
     670  /* target sanitizing */
     671  if ((target[0] & 0x80) && (~target[0] & 0x40)) {
     672    /* middle of a utf-8 character, back up to previous character. */
     673    target = g_utf8_find_prev_char(e->buff, target);
     674  }
     675  c = g_utf8_get_char(target);
     676  while (g_unichar_ismark(c) && target > e->buff) {
     677    /* Adjust the target off of combining characters and the like. */
     678    target = g_utf8_find_prev_char(e->buff, target);
     679    c = g_utf8_get_char(target);
     680  }
     681  /* If we start with a mark, something is wrong.*/
     682  if (g_unichar_ismark(c)) return;
     683
     684  /* Now our target should be acceptable. */
     685  ptr2 = strchr(ptr1, '\n');
     686  while (ptr2 != NULL && ptr2 < target) {
     687    e->buffy++;
     688    ptr1 = ptr2 + 1;
     689    ptr2 = strchr(ptr1, '\n');
     690  }
     691  ptr2 = ptr1;
     692  while (ptr2 != NULL && ptr2 < target) {
     693    c = g_utf8_get_char(ptr2);
     694    e->buffx += mk_wcwidth(c);
     695    ptr2 = g_utf8_next_char(ptr2);
     696  }
     697}
     698
     699int _owl_editwin_cursor_adjustment(owl_editwin *e)
     700{
     701  char *ptr1, *ptr2;
     702  gunichar c;
     703  int x, i;
     704
     705  /* Find line */
     706  ptr1 = e->buff;
     707  ptr2 = strchr(ptr1, '\n');
     708  for (i = 0; ptr2 != NULL && i < e->buffy; i++) {
     709    ptr1 = ptr2 + 1;
     710    ptr2 = strchr(ptr1, '\n');
     711  }
     712  ptr2 = ptr1;
     713
     714  /* Find char */
     715  x = 0;
     716  while (ptr2 != NULL && x < e->buffx) {
     717    if (*ptr2 == '\n') return 0;
     718    c = g_utf8_get_char(ptr2);
     719    x += mk_wcwidth(c);
     720    ptr2 = g_utf8_next_char(ptr2);
     721  }
     722 
     723  /* calculate x offset */
     724  return x - e->buffx;
    570725}
    571726
     
    574729  /* if we happen to have the cursor over locked text
    575730   * move it to be out of the locktext region */
    576   if (_owl_editwin_get_index_from_xy(e)<e->lock) {
     731  if (_owl_editwin_get_index_from_xy(e) < e->lock) {
    577732    _owl_editwin_set_xy_by_index(e, e->lock);
    578733  }
     
    594749{
    595750  if (e->buffy > 0) e->buffy--;
    596   if (e->buffx >= owl_editwin_get_numchars_on_line(e, e->buffy)) {
    597     e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     751  if (e->buffx >= owl_editwin_get_numcells_on_line(e, e->buffy)) {
     752    e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    598753  }
    599754
     
    612767
    613768  /* if we're past the last character move back */
    614   if (e->buffx >= owl_editwin_get_numchars_on_line(e, e->buffy)) {
    615     e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     769  if (e->buffx >= owl_editwin_get_numcells_on_line(e, e->buffy)) {
     770    e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    616771  }
    617772
     
    627782void owl_editwin_key_left(owl_editwin *e)
    628783{
    629   /* move left if we can, and maybe up a line */
    630   if (e->buffx>0) {
    631     e->buffx--;
    632   } else if (e->buffy>0) {
    633     e->buffy--;
    634     e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
    635   }
    636 
    637   /* do we need to scroll up? */
    638   if (e->buffy-e->topline < 0) {
    639     e->topline-=e->winlines/2;
     784  int i;
     785  char * p;
     786  i = _owl_editwin_get_index_from_xy(e);
     787  p = e->buff + i;
     788  p = g_utf8_find_prev_char(e->buff, p);
     789  while (p && g_unichar_ismark(g_utf8_get_char(p))) {
     790    p = g_utf8_find_prev_char(e->buff, p);
     791  }
     792  if (p == NULL) p = e->buff;
     793  _owl_editwin_set_xy_by_index(e, p - e->buff);
     794
     795  if (e->buffy - e->topline < 0) {
     796    e->topline -= e->winlines / 2;
    640797  }
    641798
     
    647804{
    648805  int i;
    649 
    650   /* move right if we can, and skip down a line if needed */
    651   i=owl_editwin_get_numchars_on_line(e, e->buffy);
    652   if (e->buffx < i) {
    653     e->buffx++;
    654     /*  } else if (e->buffy+1 < owl_editwin_get_numlines(e)) { */
    655   } else if (_owl_editwin_get_index_from_xy(e) < e->bufflen) {
    656     if (e->style==OWL_EDITWIN_STYLE_MULTILINE) {
    657       e->buffx=0;
    658       e->buffy++;
    659     }
     806  char * p;
     807  i = _owl_editwin_get_index_from_xy(e);
     808  p = e->buff + i;
     809  p = g_utf8_find_next_char(p, NULL);
     810  while (p && g_unichar_ismark(g_utf8_get_char(p))) {
     811    p = g_utf8_find_next_char(p, NULL);
     812  }
     813  if (p == NULL) {
     814    _owl_editwin_set_xy_by_index(e, e->bufflen);
     815  }
     816  else {
     817    _owl_editwin_set_xy_by_index(e, p - e->buff);
    660818  }
    661819
    662820  /* do we need to scroll down? */
    663   if (e->buffy-e->topline >= e->winlines) {
    664     e->topline+=e->winlines/2;
     821  if (e->buffy - e->topline >= e->winlines) {
     822    e->topline += e->winlines / 2;
    665823  }
    666824}
     
    669827{
    670828  int i, x;
     829  gunichar c = '\0';
    671830
    672831  /* if we're starting on a space, find the first non-space */
     
    681840  }
    682841
    683   /* find the next space, newline or end of line and go there, if
    684      already at the end of the line, continue on to the next */
    685   i=owl_editwin_get_numchars_on_line(e, e->buffy);
     842  /* find the next space, newline or end of line and go
     843     there, if already at the end of the line, continue on to the next */
     844  i=owl_editwin_get_numcells_on_line(e, e->buffy);
     845  c = _owl_editwin_get_char_at_xy(e);
    686846  if (e->buffx < i) {
    687847    /* move right till end of line */
    688848    while (e->buffx < i) {
    689       e->buffx++;
    690       if (e->buff[_owl_editwin_get_index_from_xy(e)]==' ') return;
     849      owl_editwin_key_right(e);
     850      c = _owl_editwin_get_char_at_xy(e);
     851      if (c == ' ') return;
    691852      if (e->buffx == i) return;
    692853    }
     
    694855    /* try to move down */
    695856    if (e->style==OWL_EDITWIN_STYLE_MULTILINE) {
    696       if (e->buffy+1 <  owl_editwin_get_numlines(e)) {
     857      if (e->buffy+1 < owl_editwin_get_numlines(e)) {
    697858        e->buffx=0;
    698859        e->buffy++;
     
    707868void owl_editwin_move_to_previousword(owl_editwin *e)
    708869{
    709   int i, x;
     870  int i;
     871  gunichar c;
     872  char *ptr1, *ptr2;
    710873
    711874  /* are we already at the beginning of the word? */
    712   i=_owl_editwin_get_index_from_xy(e);
    713   if ( (e->buff[i]!=' ' && e->buff[i]!='\n' && e->buff[i]!='\0') &&
    714        (e->buff[i-1]==' ' || e->buff[i-1]=='\n') ) {
     875  c = _owl_editwin_get_char_at_xy(e);
     876  i = _owl_editwin_get_index_from_xy(e);
     877  ptr1 = e->buff + i;
     878  if (*ptr1 != ' ' && *ptr1 != '\n' && *ptr1 != '\0' ) {
     879    ptr1 = g_utf8_find_prev_char(e->buff, ptr1);
     880    c = g_utf8_get_char(ptr1);
     881    if (c == ' ' || c == '\n') {
     882      owl_editwin_key_left(e);     
     883    }
     884  }
     885
     886  /* are we starting on a space character? */
     887  i = _owl_editwin_get_index_from_xy(e);
     888  while (i > e->lock && (e->buff[i] == ' ' || e->buff[i] == '\n' || e->buff[i] == '\0')) {
     889    /* find the first non-space */
     890    owl_editwin_key_left(e);     
     891    i = _owl_editwin_get_index_from_xy(e);
     892  }
     893
     894  /* find the last non-space */
     895  ptr1 = e->buff + _owl_editwin_get_index_from_xy(e);
     896  while (ptr1 >= e->buff + e->lock) {
     897    ptr2 = g_utf8_find_prev_char(e->buff, ptr1);
     898    if (!ptr2) break;
     899   
     900    c = g_utf8_get_char(ptr2);
     901    if (c == ' ' || c == '\n'){
     902      break;
     903    }
    715904    owl_editwin_key_left(e);
    716   }
    717    
    718   /* are we starting on a space character? */
    719   i=_owl_editwin_get_index_from_xy(e);
    720   if (e->buff[i]==' ' || e->buff[i]=='\n' || e->buff[i]=='\0') {
    721     /* find the first non-space */
    722     for (x=i; x>=e->lock; x--) {
    723       if (e->buff[x]!=' ' && e->buff[x]!='\n' && e->buff[x]!='\0') {
    724         _owl_editwin_set_xy_by_index(e, x);
    725         break;
    726       }
    727     }
    728   }
    729 
    730   /* find the last non-space */
    731   i=_owl_editwin_get_index_from_xy(e);
    732   for (x=i; x>=e->lock; x--) {
    733     if (e->buff[x-1]==' ' || e->buff[x-1]=='\n') {
    734       _owl_editwin_set_xy_by_index(e, x);
    735       break;
    736     }
    737   }
    738   _owl_editwin_set_xy_by_index(e, x);
     905    ptr1 = e->buff + _owl_editwin_get_index_from_xy(e);
     906  }
    739907}
    740908
     
    742910void owl_editwin_delete_nextword(owl_editwin *e)
    743911{
    744   int z;
     912  char *ptr1, *start;
     913  gunichar c;
    745914
    746915  if (e->bufflen==0) return;
    747916
    748   /* if we start out on a space character then gobble all the spaces
    749      up first */
    750   while (1) {
    751     z=_owl_editwin_get_index_from_xy(e);
    752     if (e->buff[z]==' ' || e->buff[z]=='\n') {
    753       owl_editwin_delete_char(e);
    754     } else {
    755       break;
    756     }
    757   }
    758 
    759   /* then nuke the next word */
    760   while (1) {
    761     z=_owl_editwin_get_index_from_xy(e);
    762     /* z == e->bufflen check added to prevent a hang I (nelhage) have
    763        seen repeatedly while using owl. I'm not sure precisely what
    764        conditions lead to it. */
    765     if (z == e->bufflen
    766         || e->buff[z+1]==' ' || e->buff[z+1]=='\n' || e->buff[z+1]=='\0') break;
    767     owl_editwin_delete_char(e);
    768   }
    769   owl_editwin_delete_char(e);
     917  start = ptr1 = e->buff + _owl_editwin_get_index_from_xy(e);
     918  /* if we start out on a space character then jump past all the
     919     spaces up first */
     920  while (*ptr1 == ' ' || *ptr1 == '\n') {
     921    ++ptr1;
     922  }
     923
     924  /* then jump past the next word */
     925 
     926  while (ptr1 && ptr1 - e->buff < e->bufflen) {
     927    c = g_utf8_get_char(ptr1);
     928    if (c == ' ' || c == '\n' || c == '\0') break;
     929    ptr1 = g_utf8_find_next_char(ptr1, NULL);
     930  }
     931
     932  if (ptr1) { /* We broke on a space, */
     933    ptr1 = g_utf8_find_next_char(ptr1, NULL);
     934    if (ptr1) { /* and there's a character after it, */
     935      /* nuke everything back to our starting point. */
     936      _owl_editwin_remove_bytes(e, ptr1 - start);
     937      return;
     938    }
     939  }
     940 
     941  /* If we get here, we ran out of string, drop what's left. */
     942  *start = '\0';
     943  e->bufflen = start - e->buff;
    770944}
    771945
     
    773947{
    774948  /* go backwards to the last non-space character, then delete chars */
    775   int i, startpos, endpos;
     949  int startpos, endpos;
    776950
    777951  startpos = _owl_editwin_get_index_from_xy(e);
    778952  owl_editwin_move_to_previousword(e);
    779953  endpos = _owl_editwin_get_index_from_xy(e);
    780   for (i=0; i<startpos-endpos; i++) {
    781     owl_editwin_delete_char(e);
    782   }
     954  _owl_editwin_remove_bytes(e, startpos-endpos);
    783955}
    784956
     
    787959  int i;
    788960
    789   if (owl_editwin_get_numchars_on_line(e, e->buffy)>e->buffx) {
     961  if (owl_editwin_get_numchars_on_line(e, e->buffy) > e->buffx) {
    790962    /* normal line */
    791963    i=_owl_editwin_get_index_from_xy(e);
     
    808980void owl_editwin_move_to_line_end(owl_editwin *e)
    809981{
    810   e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     982  e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    811983}
    812984
     
    821993  /* go to last char */
    822994  e->buffy=owl_editwin_get_numlines(e)-1;
    823   e->buffx=owl_editwin_get_numchars_on_line(e, e->buffy);
     995  e->buffx=owl_editwin_get_numcells_on_line(e, e->buffy);
    824996  owl_editwin_key_right(e);
    825997
     
    8611033  /* main loop */
    8621034  while (1) {
    863     i=_owl_editwin_get_index_from_xy(e);
     1035    i = _owl_editwin_get_index_from_xy(e);
    8641036
    8651037    /* bail if we hit the end of the buffer */
    866     if (i>=e->bufflen) break;
     1038    if (i >= e->bufflen || e->buff[i] == '\0') break;
    8671039
    8681040    /* bail if we hit the end of the paragraph */
    869     if (e->buff[i]=='\n' && e->buff[i+1]=='\n') break;
     1041    if (e->buff[i] == '\n' && e->buff[i+1] == '\n') break;
    8701042
    8711043    /* if we've travelled too far, linewrap */
    8721044    if ((e->buffx) >= e->fillcol) {
     1045      int len = e->bufflen;
    8731046      _owl_editwin_linewrap_word(e);
     1047      /* we may have added a character. */
     1048      if (i < save) save += e->bufflen - len;
     1049      _owl_editwin_set_xy_by_index(e, i);
    8741050    }
    8751051
    8761052    /* did we hit the end of a line too soon? */
    877     i=_owl_editwin_get_index_from_xy(e);
    878     if (e->buff[i]=='\n' && e->buffx<e->fillcol-1) {
     1053    /* asedeno: Here we replace a newline with a space. We may want to
     1054       consider removing the space if the characters to either side
     1055       are CJK ideograms.*/
     1056    i = _owl_editwin_get_index_from_xy(e);
     1057    if (e->buff[i] == '\n' && e->buffx < e->fillcol - 1) {
    8791058      /* ********* we need to make sure we don't pull in a word that's too long ***********/
    8801059      e->buff[i]=' ';
    8811060    }
    882    
     1061
    8831062    /* fix spacing */
    884     i=_owl_editwin_get_index_from_xy(e);
    885     if (e->buff[i]==' ' && e->buff[i+1]==' ') {
    886       if (e->buff[i-1]=='.' || e->buff[i-1]=='!' || e->buff[i-1]=='?') {
     1063    i = _owl_editwin_get_index_from_xy(e);
     1064    if (e->buff[i] == ' ' && e->buff[i+1] == ' ') {
     1065      if (e->buff[i-1] == '.' || e->buff[i-1] == '!' || e->buff[i-1] == '?') {
    8871066        owl_editwin_key_right(e);
    8881067      } else {
    8891068        owl_editwin_delete_char(e);
    890         /* if we did this ahead of the save point, adjust it */
    891         if (i<save) save--;
     1069        /* if we did this ahead of the save point, adjust it. Changing
     1070           by one is fine here because we're only removing an ASCII
     1071           space. */
     1072        if (i < save) save--;
    8921073      }
    8931074    } else {
    8941075      owl_editwin_key_right(e);
    8951076    }
    896 
    8971077  }
    8981078
     
    9151095int owl_editwin_check_dotsend(owl_editwin *e)
    9161096{
    917   int i;
     1097  char *p, *p_n, *p_p;
     1098  gunichar c;
    9181099
    9191100  if (!e->dotsend) return(0);
    920   for (i=e->bufflen-1; i>0; i--) {
    921     if (e->buff[i] == '.'
    922         && (e->buff[i-1] == '\n' || e->buff[i-1] == '\r')
    923         && (e->buff[i+1] == '\n' || e->buff[i+1] == '\r')) {
    924       e->bufflen = i;
    925       e->buff[i] = '\0';
     1101
     1102  p = g_utf8_find_prev_char(e->buff, e->buff + e->bufflen);
     1103  p_n = g_utf8_find_next_char(p, NULL);
     1104  p_p = g_utf8_find_prev_char(e->buff, p);
     1105  c = g_utf8_get_char(p);
     1106  while (p != NULL) {
     1107    if (*p == '.'
     1108        && p_p != NULL && (*p_p == '\n' || *p_p == '\r')
     1109        && p_n != NULL && (*p_n == '\n' || *p_n == '\r')) {
     1110      e->bufflen = p - e->buff;
     1111      e->buff[e->bufflen] = '\0';
    9261112      return(1);
    9271113    }
    928     if (!isspace((int) e->buff[i])) {
    929       return(0);
    930     }
     1114    if (c != '\0' && !g_unichar_isspace(c)) return(0);
     1115    p_n = p;
     1116    p = p_p;
     1117    c = g_utf8_get_char(p);
     1118    p_p = g_utf8_find_prev_char(e->buff, p);
    9311119  }
    9321120  return(0);
    9331121}
    9341122
    935 void owl_editwin_post_process_char(owl_editwin *e, int j)
     1123void owl_editwin_post_process_char(owl_editwin *e, owl_input j)
    9361124{
    9371125  /* check if we need to scroll down */
     
    9391127    e->topline+=e->winlines/2;
    9401128  }
    941   if ((j==13 || j==10) && owl_editwin_check_dotsend(e)) {
     1129  if ((j.ch==13 || j.ch==10) && owl_editwin_check_dotsend(e)) {
    9421130    owl_command_editmulti_done(e);
    9431131    return;
     
    9461134}
    9471135
    948 void owl_editwin_process_char(owl_editwin *e, int j)
    949 {
    950   if (j == ERR) return;
    951   if (j>127 || ((j<32) && (j!=10) && (j!=13))) {
    952     return;
    953   } else {
     1136void _owl_editwin_process_char(owl_editwin *e, gunichar j)
     1137{
     1138  if (!(g_unichar_iscntrl(j) && (j != 10) && (j != 13))) {
    9541139    owl_editwin_insert_char(e, j);
     1140  }
     1141}
     1142
     1143
     1144void owl_editwin_process_char(owl_editwin *e, owl_input j)
     1145{
     1146  if (j.ch == ERR) return;
     1147  /* Ignore ncurses control characters. */
     1148  if (j.ch < 0x100) {
     1149    _owl_editwin_process_char(e, j.uch);
    9551150  }
    9561151}
     
    9791174  }
    9801175
    981   /* now go to the xth character */
    982   ptr2=strchr(ptr1, '\n');
    983   if (!ptr2) {
    984     return(e->buff + e->bufflen - ptr1);
    985   }
    986   return(ptr2-ptr1); /* don't count the newline for now */
     1176  /* now count characters */
     1177  i = 0;
     1178  ptr2 = ptr1;
     1179  while (ptr2 - e->buff < e->bufflen
     1180         && *ptr2 != '\n') {
     1181    ++i;
     1182    ptr2 = g_utf8_next_char(ptr2);
     1183  }
     1184  return i;
     1185}
     1186
     1187int owl_editwin_get_numcells_on_line(owl_editwin *e, int line)
     1188{
     1189  int i;
     1190  char *ptr1, *ptr2;
     1191  gunichar c;
     1192
     1193  if (e->bufflen==0) return(0);
     1194 
     1195  /* first go to the yth line */
     1196  ptr1=e->buff;
     1197  for (i=0; i<line; i++) {
     1198    ptr2=strchr(ptr1, '\n');
     1199    if (!ptr2) {
     1200      /* we're already on the last line */
     1201      return(0);
     1202    }
     1203    ptr1=ptr2+1;
     1204  }
     1205
     1206  /* now count cells */
     1207  i = 0;
     1208  ptr2 = ptr1;
     1209  while (ptr2 - e->buff < e->bufflen
     1210         && *ptr2 != '\n') {
     1211    c = g_utf8_get_char(ptr2);
     1212    i += mk_wcwidth(c);
     1213    ptr2 = g_utf8_next_char(ptr2);
     1214  }
     1215  return i;
    9871216}
    9881217
  • fmtext.c

    r005fc22 r6f6330b  
    88void owl_fmtext_init_null(owl_fmtext *f)
    99{
    10   f->textlen=0;
    11   f->bufflen=5;
    12   f->textbuff=owl_malloc(5);
    13   f->fmbuff=owl_malloc(5);
    14   f->fgcolorbuff=owl_malloc(5 * sizeof(short));
    15   f->bgcolorbuff=owl_malloc(5 * sizeof(short));
    16   f->textbuff[0]=0;
    17   f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
    18   f->fgcolorbuff[0]=OWL_COLOR_DEFAULT;
    19   f->bgcolorbuff[0]=OWL_COLOR_DEFAULT;
     10  f->textlen = 0;
     11  f->bufflen = 5;
     12  f->textbuff = owl_malloc(5);
     13  f->textbuff[0] = 0;
     14  f->default_attrs = OWL_FMTEXT_ATTR_NONE;
     15  f->default_fgcolor = OWL_COLOR_DEFAULT;
     16  f->default_bgcolor = OWL_COLOR_DEFAULT;
    2017}
    2118
     
    2421void owl_fmtext_clear(owl_fmtext *f)
    2522{
    26     f->textlen = 0;
    27     f->textbuff[0] = 0;
    28     f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
    29     f->fgcolorbuff[0]=OWL_COLOR_DEFAULT;
    30     f->bgcolorbuff[0]=OWL_COLOR_DEFAULT;
    31 }
    32 
    33 /* Internal function.  Set the attribute 'attr' from index 'first' to
    34  * index 'last'
    35  */
    36 void _owl_fmtext_set_attr(owl_fmtext *f, int attr, int first, int last)
    37 {
    38   int i;
    39   for (i=first; i<=last; i++) {
    40     f->fmbuff[i]=(unsigned char) attr;
    41   }
    42 }
    43 
    44 /* Internal function.  Add the attribute 'attr' to the existing
    45  * attributes from index 'first' to index 'last'
    46  */
    47 void _owl_fmtext_add_attr(owl_fmtext *f, int attr, int first, int last)
    48 {
    49   int i;
    50   for (i=first; i<=last; i++) {
    51     f->fmbuff[i]|=(unsigned char) attr;
    52   }
    53 }
    54 
    55 /* Internal function.  Set the color to be 'color' from index 'first'
    56  * to index 'last
    57  */
    58 void _owl_fmtext_set_fgcolor(owl_fmtext *f, int color, int first, int last)
    59 {
    60   int i;
    61   for (i=first; i<=last; i++) {
    62     f->fgcolorbuff[i]=(short)color;
    63   }
    64 }
    65 
    66 void _owl_fmtext_set_bgcolor(owl_fmtext *f, int color, int first, int last)
    67 {
    68   int i;
    69   for (i=first; i<=last; i++) {
    70     f->bgcolorbuff[i]=(short)color;
    71   }
     23  f->textlen = 0;
     24  f->textbuff[0] = 0;
     25  f->default_attrs = OWL_FMTEXT_ATTR_NONE;
     26  f->default_fgcolor = OWL_COLOR_DEFAULT;
     27  f->default_bgcolor = OWL_COLOR_DEFAULT;
    7228}
    7329
     
    7531{
    7632    if(newlen + 1 > f->bufflen) {
    77       f->textbuff=owl_realloc(f->textbuff, newlen+1);
    78       f->fmbuff=owl_realloc(f->fmbuff, newlen+1);
    79       f->fgcolorbuff=owl_realloc(f->fgcolorbuff, (newlen+1) * sizeof(short));
    80       f->bgcolorbuff=owl_realloc(f->bgcolorbuff, (newlen+1) * sizeof(short));
     33      f->textbuff = owl_realloc(f->textbuff, newlen + 1);
    8134      f->bufflen = newlen+1;
    8235  }
    8336}
    8437
     38int owl_fmtext_is_format_char(gunichar c)
     39{
     40  if ((c & ~OWL_FMTEXT_UC_ATTR_MASK) == OWL_FMTEXT_UC_ATTR) return 1;
     41  if ((c & ~(OWL_FMTEXT_UC_ALLCOLOR_MASK)) == OWL_FMTEXT_UC_COLOR_BASE) return 1;
     42  return 0;
     43}
    8544/* append text to the end of 'f' with attribute 'attr' and color
    8645 * 'color'
    8746 */
    88 void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int fgcolor, int bgcolor)
    89 {
    90   int newlen;
    91   newlen=strlen(f->textbuff)+strlen(text);
     47void owl_fmtext_append_attr(owl_fmtext *f, char *text, char attr, short fgcolor, short bgcolor)
     48{
     49  char attrbuff[6];
     50  int newlen, a = 0, fg = 0, bg = 0;
     51 
     52  if (attr != OWL_FMTEXT_ATTR_NONE) a=1;
     53  if (fgcolor != OWL_COLOR_DEFAULT) fg=1;
     54  if (bgcolor != OWL_COLOR_DEFAULT) bg=1;
     55
     56  /* Plane-16 characters in UTF-8 are 4 bytes long. */
     57  newlen = strlen(f->textbuff) + strlen(text) + (8 * (a + fg + bg));
    9258  _owl_fmtext_realloc(f, newlen);
     59
     60  /* Set attributes */
     61  if (a) {
     62    memset(attrbuff,0,6);
     63    g_unichar_to_utf8(OWL_FMTEXT_UC_ATTR | attr, attrbuff);
     64    strcat(f->textbuff, attrbuff);     
     65  }
     66  if (fg) {
     67    memset(attrbuff,0,6);
     68    g_unichar_to_utf8(OWL_FMTEXT_UC_FGCOLOR | fgcolor, attrbuff);
     69    strcat(f->textbuff, attrbuff);     
     70  }
     71  if (bg) {
     72    memset(attrbuff,0,6);
     73    g_unichar_to_utf8(OWL_FMTEXT_UC_BGCOLOR | bgcolor, attrbuff);
     74    strcat(f->textbuff, attrbuff);     
     75  }
    9376 
    9477  strcat(f->textbuff, text);
    95   _owl_fmtext_set_attr(f, attr, f->textlen, newlen);
    96   _owl_fmtext_set_fgcolor(f, fgcolor, f->textlen, newlen);
    97   _owl_fmtext_set_bgcolor(f, bgcolor, f->textlen, newlen);
     78
     79  /* Reset attributes */
     80  if (bg) strcat(f->textbuff, OWL_FMTEXT_UTF8_BGDEFAULT);
     81  if (fg) strcat(f->textbuff, OWL_FMTEXT_UTF8_FGDEFAULT);
     82  if (a)  strcat(f->textbuff, OWL_FMTEXT_UTF8_ATTR_NONE);
    9883  f->textlen=newlen;
    9984}
     
    129114}
    130115
    131 /* Add the attribute 'attr' to all text in 'f' */
    132 void owl_fmtext_addattr(owl_fmtext *f, int attr)
     116/* Add the attribute 'attr' to the default atts for the text in 'f' */
     117void owl_fmtext_addattr(owl_fmtext *f, char attr)
    133118{
    134119  /* add the attribute to all text */
    135   int i, j;
    136 
    137   j=f->textlen;
    138   for (i=0; i<j; i++) {
    139     f->fmbuff[i] |= attr;
    140   }
    141 }
    142 
    143 /* Anywhere the color is NOT ALREDY SET, set the color to 'color'.
    144  * Other colors are left unchanged
     120  f->default_attrs |= attr;
     121}
     122
     123/* Set the default foreground color for this fmtext to 'color'.
     124 * Only affects text that is colored default.
    145125 */
    146126void owl_fmtext_colorize(owl_fmtext *f, int color)
    147127{
    148   /* everywhere the fgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
    149   int i, j;
    150 
    151   j=f->textlen;
    152   for(i=0; i<j; i++) {
    153     if (f->fgcolorbuff[i]==OWL_COLOR_DEFAULT) f->fgcolorbuff[i] = (short)color;
    154   }
    155 }
    156 
     128  f->default_fgcolor = color;
     129}
     130
     131/* Set the default foreground color for this fmtext to 'color'.
     132 * Only affects text that is colored default.
     133 */
    157134void owl_fmtext_colorizebg(owl_fmtext *f, int color)
    158135{
    159   /* everywhere the bgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
    160   int i, j;
    161 
    162   j=f->textlen;
    163   for(i=0; i<j; i++) {
    164     if (f->bgcolorbuff[i]==OWL_COLOR_DEFAULT) f->bgcolorbuff[i] = (short)color;
    165   }
    166 }
     136  f->default_bgcolor = color;
     137}
     138
     139/* Internal function. Parse attrbute character. */
     140void _owl_fmtext_update_attributes(gunichar c, char *attr, short *fgcolor, short *bgcolor) /*noproto*/
     141{
     142  if ((c & OWL_FMTEXT_UC_ATTR) == OWL_FMTEXT_UC_ATTR) {
     143    *attr = c & OWL_FMTEXT_UC_ATTR_MASK;
     144  }
     145  else if ((c & OWL_FMTEXT_UC_COLOR_BASE) == OWL_FMTEXT_UC_COLOR_BASE) {
     146    if ((c & OWL_FMTEXT_UC_BGCOLOR) == OWL_FMTEXT_UC_BGCOLOR) {
     147      *bgcolor = (c == OWL_FMTEXT_UC_BGDEFAULT
     148                  ? OWL_COLOR_DEFAULT
     149                  : c & OWL_FMTEXT_UC_COLOR_MASK);
     150    }
     151    else if ((c & OWL_FMTEXT_UC_FGCOLOR) == OWL_FMTEXT_UC_FGCOLOR) {
     152      *fgcolor = (c == OWL_FMTEXT_UC_FGDEFAULT
     153                  ? OWL_COLOR_DEFAULT
     154                  : c & OWL_FMTEXT_UC_COLOR_MASK);
     155    }
     156  }
     157}
     158
     159/* Internal function. Scan for attribute characters. */
     160void _owl_fmtext_scan_attributes(owl_fmtext *f, int start, char *attr, short *fgcolor, short *bgcolor) /*noproto*/
     161{
     162  char *p;
     163  p = strchr(f->textbuff, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     164  while (p && p < f->textbuff + start) {
     165    _owl_fmtext_update_attributes(g_utf8_get_char(p), attr, fgcolor, bgcolor);
     166    p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     167  }
     168
    167169
    168170/* Internal function.  Append text from 'in' between index 'start' and
    169171 * 'stop' to the end of 'f'
    170172 */
    171 void _owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in, int start, int stop)
    172 {
    173   int newlen, i;
    174 
    175   newlen=strlen(f->textbuff)+(stop-start+1);
     173void _owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in, int start, int stop) /*noproto*/
     174{
     175  char attrbuff[6];
     176  int newlen, a = 0, fg = 0, bg = 0;
     177  char attr = 0;
     178  short fgcolor = OWL_COLOR_DEFAULT;
     179  short bgcolor = OWL_COLOR_DEFAULT;
     180
     181  _owl_fmtext_scan_attributes(in, start, &attr, &fgcolor, &bgcolor);
     182  if (attr != OWL_FMTEXT_ATTR_NONE) a=1;
     183  if (fgcolor != OWL_COLOR_DEFAULT) fg=1;
     184  if (bgcolor != OWL_COLOR_DEFAULT) bg=1;
     185
     186  /* We will reset to defaults after appending the text. We may need
     187     to set initial attributes. */
     188  newlen=strlen(f->textbuff)+(stop-start+1) + (4 * (a + fg + bg)) + 12;
    176189  _owl_fmtext_realloc(f, newlen);
    177190
     191  if (a) {
     192    memset(attrbuff,0,6);
     193    g_unichar_to_utf8(OWL_FMTEXT_UC_ATTR | attr, attrbuff);
     194    strcat(f->textbuff, attrbuff);     
     195  }
     196  if (fg) {
     197    memset(attrbuff,0,6);
     198    g_unichar_to_utf8(OWL_FMTEXT_UC_FGCOLOR | fgcolor, attrbuff);
     199    strcat(f->textbuff, attrbuff);     
     200  }
     201  if (bg) {
     202    memset(attrbuff,0,6);
     203    g_unichar_to_utf8(OWL_FMTEXT_UC_BGCOLOR | bgcolor, attrbuff);
     204    strcat(f->textbuff, attrbuff);     
     205  }
     206
    178207  strncat(f->textbuff, in->textbuff+start, stop-start+1);
     208
     209  /* Reset attributes */
     210  strcat(f->textbuff, OWL_FMTEXT_UTF8_BGDEFAULT);
     211  strcat(f->textbuff, OWL_FMTEXT_UTF8_FGDEFAULT);
     212  strcat(f->textbuff, OWL_FMTEXT_UTF8_ATTR_NONE);
     213
    179214  f->textbuff[newlen]='\0';
    180   for (i=start; i<=stop; i++) {
    181     f->fmbuff[f->textlen+(i-start)]=in->fmbuff[i];
    182     f->fgcolorbuff[f->textlen+(i-start)]=in->fgcolorbuff[i];
    183     f->bgcolorbuff[f->textlen+(i-start)]=in->bgcolorbuff[i];
    184   }
    185215  f->textlen=newlen;
    186216}
     
    207237char *owl_fmtext_print_plain(owl_fmtext *f)
    208238{
    209   return(owl_strdup(f->textbuff));
     239  return owl_strip_format_chars(f->textbuff);
     240}
     241
     242void _owl_fmtext_wattrset(WINDOW *w, int attrs) /*noproto*/
     243{
     244  wattrset(w, A_NORMAL);
     245  if (attrs & OWL_FMTEXT_ATTR_BOLD) wattron(w, A_BOLD);
     246  if (attrs & OWL_FMTEXT_ATTR_REVERSE) wattron(w, A_REVERSE);
     247  if (attrs & OWL_FMTEXT_ATTR_UNDERLINE) wattron(w, A_UNDERLINE);
     248}
     249
     250void _owl_fmtext_update_colorpair(short fg, short bg, short *pair) /*noproto*/
     251{
     252  if (owl_global_get_hascolors(&g)) {
     253    *pair = owl_fmtext_get_colorpair(fg, bg);
     254  }
     255}
     256
     257void _owl_fmtext_wcolor_set(WINDOW *w, short pair) /*noproto*/
     258{
     259  if (owl_global_get_hascolors(&g)) {
     260      wcolor_set(w,pair,NULL);
     261  }
    210262}
    211263
     
    213265 * must already be initiatlized with curses
    214266 */
    215 void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w)
    216 {
    217   char *tmpbuff;
    218   int position, trans1, trans2, trans3, len, lastsame;
    219 
     267void _owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w, int do_search) /*noproto*/
     268{
     269  /* char *tmpbuff; */
     270  /* int position, trans1, trans2, trans3, len, lastsame; */
     271  char *s, *p;
     272  char attr;
     273  short fg, bg, pair;
     274  int search_results, search_len;
     275 
    220276  if (w==NULL) {
    221277    owl_function_debugmsg("Hit a null window in owl_fmtext_curs_waddstr.");
     
    223279  }
    224280
    225   tmpbuff=owl_malloc(f->textlen+10);
    226 
    227   position=0;
    228   len=f->textlen;
    229   while (position<=len) {
    230     /* find the last char with the current format and color */
    231     trans1=owl_util_find_trans(f->fmbuff+position, len-position);
    232     trans2=owl_util_find_trans_short(f->fgcolorbuff+position, len-position);
    233     trans3=owl_util_find_trans_short(f->bgcolorbuff+position, len-position);
    234 
    235     lastsame = (trans1 < trans2) ? trans1 : trans2;
    236     lastsame = (lastsame < trans3) ? lastsame : trans3;
    237     lastsame += position;
    238 
    239     /* set the format */
    240     wattrset(w, A_NORMAL);
    241     if (f->fmbuff[position] & OWL_FMTEXT_ATTR_BOLD) {
    242       wattron(w, A_BOLD);
    243     }
    244     if (f->fmbuff[position] & OWL_FMTEXT_ATTR_REVERSE) {
    245       wattron(w, A_REVERSE);
    246     }
    247     if (f->fmbuff[position] & OWL_FMTEXT_ATTR_UNDERLINE) {
    248       wattron(w, A_UNDERLINE);
    249     }
    250 
    251     /* set the color */
    252     /* warning, this is sort of a hack */
    253     if (owl_global_get_hascolors(&g)) {
    254       short fg, bg, pair;
    255       fg = f->fgcolorbuff[position];
    256       bg = f->bgcolorbuff[position];
    257 
    258       pair = owl_fmtext_get_colorpair(fg, bg);
    259       if (pair != -1) {
    260         wcolor_set(w,pair,NULL);
    261       }
    262     }
    263 
    264     /* add the text */
    265     strncpy(tmpbuff, f->textbuff + position, lastsame-position+1);
    266     tmpbuff[lastsame-position+1]='\0';
    267     waddstr(w, tmpbuff);
    268 
    269     position=lastsame+1;
    270   }
    271   owl_free(tmpbuff);
    272 }
    273 
     281  search_results = (do_search
     282                    ? owl_fmtext_search(f, owl_global_get_search_string(&g))
     283                    : 0);
     284  search_len = (search_results
     285                ? strlen(owl_global_get_search_string(&g))
     286                : 0);
     287  s = f->textbuff;
     288  /* Set default attributes. */
     289  attr = f->default_attrs;
     290  fg = f->default_fgcolor;
     291  bg = f->default_bgcolor;
     292  _owl_fmtext_wattrset(w, attr);
     293  _owl_fmtext_update_colorpair(fg, bg, &pair);
     294  _owl_fmtext_wcolor_set(w, pair);
     295
     296  /* Find next possible format character. */
     297  p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     298  while(p) {
     299    if (owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     300      /* Deal with all text from last insert to here. */
     301      char tmp;
     302   
     303      tmp = p[0];
     304      p[0] = '\0';
     305      if (search_results) {
     306        /* Search is active, so highlight search results. */
     307        char tmp2, *ss;
     308        ss = stristr(s, owl_global_get_search_string(&g));
     309        while (ss) {
     310          /* Found search string, highlight it. */
     311
     312          tmp2 = ss[0];
     313          ss[0] = '\0';
     314          waddstr(w, s);
     315          ss[0] = tmp2;
     316
     317          _owl_fmtext_wattrset(w, attr ^ OWL_FMTEXT_ATTR_REVERSE);
     318          _owl_fmtext_wcolor_set(w, pair);
     319         
     320          tmp2 = ss[search_len];
     321          ss[search_len] = '\0';
     322          waddstr(w, ss);
     323          ss[search_len] = tmp2;
     324
     325          _owl_fmtext_wattrset(w, attr);
     326          _owl_fmtext_wcolor_set(w, pair);
     327
     328          s = ss + search_len;
     329          ss = stristr(s, owl_global_get_search_string(&g));
     330        }
     331      }
     332      /* Deal with remaining part of string. */
     333      waddstr(w, s);
     334      p[0] = tmp;
     335
     336      /* Deal with new attributes. Initialize to defaults, then
     337         process all consecutive formatting characters. */
     338      attr = f->default_attrs;
     339      fg = f->default_fgcolor;
     340      bg = f->default_bgcolor;
     341      while (p && owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     342        _owl_fmtext_update_attributes(g_utf8_get_char(p), &attr, &fg, &bg);
     343        p = g_utf8_next_char(p);
     344      }
     345      _owl_fmtext_wattrset(w, attr | f->default_attrs);
     346      if (fg == OWL_COLOR_DEFAULT) fg = f->default_fgcolor;
     347      if (bg == OWL_COLOR_DEFAULT) bg = f->default_bgcolor;
     348      _owl_fmtext_update_colorpair(fg, bg, &pair);
     349      _owl_fmtext_wcolor_set(w, pair);
     350
     351      /* Advance to next non-formatting character. */
     352      s = p;
     353      p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     354    }
     355    else {
     356      p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     357    }
     358  }
     359  if (s) {
     360    waddstr(w, s);
     361  }
     362}
     363
     364void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w)
     365{
     366  _owl_fmtext_curs_waddstr(f, w, owl_global_is_search_active(&g));
     367}
     368
     369void owl_fmtext_curs_waddstr_without_search(owl_fmtext *f, WINDOW *w)
     370{
     371  _owl_fmtext_curs_waddstr(f, w, 0);
     372}
    274373
    275374/* start with line 'aline' (where the first line is 0) and print
     
    282381 
    283382  /* find the starting line */
    284   ptr1=in->textbuff;
    285   if (aline!=0) {
    286     for (i=0; i<aline; i++) {
    287       ptr1=strchr(ptr1, '\n');
    288       if (!ptr1) return(-1);
    289       ptr1++;
    290     }
    291   }
     383  ptr1 = in->textbuff;
     384  for (i = 0; i < aline; i++) {
     385    ptr1 = strchr(ptr1, '\n');
     386    if (!ptr1) return(-1);
     387    ptr1++;
     388  }
     389 
    292390  /* ptr1 now holds the starting point */
    293391
     392  /* copy the default attributes */
     393  out->default_attrs = in->default_attrs;
     394  out->default_fgcolor = in->default_fgcolor;
     395  out->default_bgcolor = in->default_bgcolor;
     396   
    294397  /* copy in the next 'lines' lines */
    295   if (lines<1) return(-1);
    296 
    297   for (i=0; i<lines; i++) {
    298     offset=ptr1-in->textbuff;
    299     ptr2=strchr(ptr1, '\n');
     398  if (lines < 1) return(-1);
     399
     400  for (i = 0; i < lines; i++) {
     401    offset = ptr1 - in->textbuff;
     402    ptr2 = strchr(ptr1, '\n');
    300403    if (!ptr2) {
    301       _owl_fmtext_append_fmtext(out, in, offset, (in->textlen)-1);
     404      _owl_fmtext_append_fmtext(out, in, offset, (in->textlen) - 1);
    302405      return(-1);
    303406    }
    304     _owl_fmtext_append_fmtext(out, in, offset, (ptr2-ptr1)+offset);
    305     ptr1=ptr2+1;
     407    _owl_fmtext_append_fmtext(out, in, offset, (ptr2 - ptr1) + offset);
     408    ptr1 = ptr2 + 1;
    306409  }
    307410  return(0);
     
    311414 * ends at 'bcol' or sooner.  The first column is number 0.  The new
    312415 * message is placed in 'out'.  The message is * expected to end in a
    313  * new line for now
     416 * new line for now. NOTE: This needs to be modified to deal with
     417 * backing up if we find a SPACING COMBINING MARK at the end of a
     418 * line. If that happens, we should back up to the last non-mark
     419 * character and stop there.
    314420 */
    315421void owl_fmtext_truncate_cols(owl_fmtext *in, int acol, int bcol, owl_fmtext *out)
    316422{
    317   char *ptr1, *ptr2, *last;
    318   int len, offset;
     423  char *ptr_s, *ptr_e, *ptr_c, *last;
     424  int col, st, padding, chwidth;
     425
     426  /* copy the default attributes */
     427  out->default_attrs = in->default_attrs;
     428  out->default_fgcolor = in->default_fgcolor;
     429  out->default_bgcolor = in->default_bgcolor;
    319430
    320431  last=in->textbuff+in->textlen-1;
    321   ptr1=in->textbuff;
    322   while (ptr1<=last) {
    323     ptr2=strchr(ptr1, '\n');
    324     if (!ptr2) {
     432  ptr_s=in->textbuff;
     433  while (ptr_s <= last) {
     434    ptr_e=strchr(ptr_s, '\n');
     435    if (!ptr_e) {
    325436      /* but this shouldn't happen if we end in a \n */
    326437      break;
    327438    }
    328439   
    329     if (ptr2==ptr1) {
     440    if (ptr_e == ptr_s) {
    330441      owl_fmtext_append_normal(out, "\n");
    331       ptr1++;
     442      ++ptr_s;
    332443      continue;
    333444    }
    334445
    335     /* we need to check that we won't run over here */
    336     len=bcol-acol;
    337     if (len > (ptr2-(ptr1+acol))) {
    338       /* the whole line fits with room to spare, don't take a full 'len' */
    339       len=ptr2-(ptr1+acol);
    340     }
    341     if (len>last-ptr1) {
    342       /* the whole rest of the text fits with room to spare, adjust for it */
    343       len-=(last-ptr1);
    344     }
    345     if (len<=0) {
    346       /* saftey check */
     446    col = 0;
     447    st = 0;
     448    padding = 0;
     449    chwidth = 0;
     450    ptr_c = ptr_s;
     451    while(ptr_c < ptr_e) {
     452      gunichar c = g_utf8_get_char(ptr_c);
     453      if (!owl_fmtext_is_format_char(c)) {
     454        chwidth = mk_wcwidth(c);
     455        if (col + chwidth > bcol) break;
     456       
     457        if (col >= acol) {
     458          if (st == 0) {
     459            ptr_s = ptr_c;
     460            padding = col - acol;
     461            ++st;
     462          }
     463        }
     464        col += chwidth;
     465        chwidth = 0;
     466      }
     467      ptr_c = g_utf8_next_char(ptr_c);
     468    }
     469    if (st) {
     470      /* lead padding */
     471      owl_fmtext_append_spaces(out, padding);
     472      if (ptr_c == ptr_e) {
     473        /* We made it to the newline. */
     474        _owl_fmtext_append_fmtext(out, in, ptr_s - in->textbuff, ptr_c - in->textbuff);
     475      }
     476      else {
     477        if (chwidth > 1) {
     478          /* Last char is wide, truncate. */
     479          _owl_fmtext_append_fmtext(out, in, ptr_s - in->textbuff, ptr_c - in->textbuff - 1);
     480          owl_fmtext_append_normal(out, "\n");
     481        }
     482        else {
     483          /* Last char fits perfectly, leave alone.*/
     484          _owl_fmtext_append_fmtext(out, in, ptr_s - in->textbuff, ptr_c - in->textbuff);
     485        }
     486      }
     487    }
     488    else {
    347489      owl_fmtext_append_normal(out, "\n");
    348       ptr1=ptr2+1;
    349       continue;
    350     }
    351 
    352     offset=ptr1-in->textbuff;
    353     _owl_fmtext_append_fmtext(out, in, offset+acol, offset+acol+len);
    354 
    355     ptr1=ptr2+1;
     490    }
     491    ptr_s = g_utf8_next_char(ptr_e);
    356492  }
    357493}
     
    381517
    382518/* set the charater at 'index' to be 'char'.  If index is out of
    383  * bounds don't do anything */
    384 void owl_fmtext_set_char(owl_fmtext *f, int index, int ch)
     519 * bounds don't do anything. If c or char at index is not ASCII, don't
     520 * do anything because it's not UTF-8 safe. */
     521void owl_fmtext_set_char(owl_fmtext *f, int index, char ch)
    385522{
    386523  if ((index < 0) || (index > f->textlen-1)) return;
     524  /* NOT ASCII*/
     525  if (f->textbuff[index] & 0x80 || ch & 0x80) return;
    387526  f->textbuff[index]=ch;
    388527}
     
    401540  dst->bufflen=mallocsize;
    402541  dst->textbuff=owl_malloc(mallocsize);
    403   dst->fmbuff=owl_malloc(mallocsize);
    404   dst->fgcolorbuff=owl_malloc(mallocsize * sizeof(short));
    405   dst->bgcolorbuff=owl_malloc(mallocsize * sizeof(short));
    406542  memcpy(dst->textbuff, src->textbuff, src->textlen+1);
    407   memcpy(dst->fmbuff, src->fmbuff, src->textlen);
    408   memcpy(dst->fgcolorbuff, src->fgcolorbuff, src->textlen * sizeof(short));
    409   memcpy(dst->bgcolorbuff, src->bgcolorbuff, src->textlen * sizeof(short));
    410 }
    411 
    412 /* highlight all instances of "string".  Return the number of
    413  * instances found.  This is a case insensitive search.
    414  */
    415 int owl_fmtext_search_and_highlight(owl_fmtext *f, char *string)
    416 {
    417 
    418   int found, len;
    419   char *ptr1, *ptr2;
    420 
    421   len=strlen(string);
    422   found=0;
    423   ptr1=f->textbuff;
    424   while (ptr1-f->textbuff <= f->textlen) {
    425     ptr2=stristr(ptr1, string);
    426     if (!ptr2) return(found);
    427 
    428     found++;
    429     _owl_fmtext_add_attr(f, OWL_FMTEXT_ATTR_REVERSE,
    430                          ptr2 - f->textbuff,
    431                          ptr2 - f->textbuff + len - 1);
    432 
    433     ptr1=ptr2+len;
    434   }
    435   return(found);
     543  dst->default_attrs = src->default_attrs;
     544  dst->default_fgcolor = src->default_fgcolor;
     545  dst->default_bgcolor = src->default_bgcolor;
    436546}
    437547
     
    441551int owl_fmtext_search(owl_fmtext *f, char *string)
    442552{
    443 
    444553  if (stristr(f->textbuff, string)) return(1);
    445554  return(0);
     
    682791{
    683792  if (f->textbuff) owl_free(f->textbuff);
    684   if (f->fmbuff) owl_free(f->fmbuff);
    685   if (f->fgcolorbuff) owl_free(f->fgcolorbuff);
    686   if (f->bgcolorbuff) owl_free(f->bgcolorbuff);
    687793}
    688794
  • functions.c

    r6b580b0 r5f3168a  
    16061606          sprintf(buff, "  Field %i   : ", i+1);
    16071607         
    1608           ptr=owl_zephyr_get_field(n, i+1);
     1608          ptr=owl_zephyr_get_field_as_utf8(n, i+1);
    16091609          len=strlen(ptr);
    16101610          if (len<30) {
     
    21872187void owl_function_start_command(char *line)
    21882188{
    2189   int i, j;
    21902189  owl_editwin *tw;
    21912190
     
    21982197  owl_global_set_needrefresh(&g);
    21992198
    2200   j=strlen(line);
    2201   for (i=0; i<j; i++) {
    2202     owl_editwin_process_char(tw, line[i]);
    2203   }
     2199  owl_editwin_insert_string(tw, line);
    22042200  owl_editwin_redisplay(tw, 0);
    22052201
     
    25992595  }
    26002596  /* downcase it */
    2601   downstr(filtname);
     2597  {
     2598    char *temp = g_utf8_strdown(filtname, -1);
     2599    if (temp) {
     2600      owl_free(filtname);
     2601      filtname = temp;
     2602    }
     2603  }
    26022604  /* turn spaces, single quotes, and double quotes into dots */
    26032605  owl_text_tr(filtname, ' ', '.');
     
    30243026  char *quoted;
    30253027
    3026   buff=malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
     3028  buff=owl_malloc(strlen(class)+strlen(inst)+strlen(recip)+100);
    30273029  strcpy(buff, "class");
    30283030  if (!strcmp(class, "*")) {
     
    33283330          if (ret==0) {
    33293331            for (x=0; x<numlocs; x++) {
    3330               line=malloc(strlen(location[x].host)+strlen(location[x].time)+strlen(location[x].tty)+100);
     3332              line=owl_malloc(strlen(location[x].host)+strlen(location[x].time)+strlen(location[x].tty)+100);
    33313333              tmp=short_zuser(user);
    33323334              sprintf(line, "  %-10.10s %-24.24s %-12.12s  %20.20s\n",
     
    33713373  owl_view *v;
    33723374  FILE *file;
     3375  char *plaintext;
    33733376
    33743377  v=owl_global_get_current_view(&g);
     
    33933396  for (i=0; i<j; i++) {
    33943397    m=owl_view_get_element(v, i);
    3395     fputs(owl_message_get_text(m), file);
     3398    plaintext = owl_strip_format_chars(owl_message_get_text(m));
     3399    if (plaintext) {
     3400      fputs(plaintext, file);
     3401      owl_free(plaintext);
     3402    }
    33963403  }
    33973404  fclose(file);
     
    34343441          _exit(127);
    34353442        }
    3436         parsed=realloc(parsed, sizeof(*parsed) * (myargc+1));
     3443        parsed=owl_realloc(parsed, sizeof(*parsed) * (myargc+1));
    34373444        parsed[myargc] = NULL;
    34383445       
  • keymap.c

    rcf83b7a r428834d  
    55
    66/* returns 0 on success */
    7 int owl_keymap_init(owl_keymap *km, char *name, char *desc, void (*default_fn)(int), void (*prealways_fn)(int), void (*postalways_fn)(int))
     7int owl_keymap_init(owl_keymap *km, char *name, char *desc, void (*default_fn)(owl_input), void (*prealways_fn)(owl_input), void (*postalways_fn)(owl_input))
    88{
    99  if (!name || !desc) return(-1);
     
    151151}
    152152
    153 owl_keymap *owl_keyhandler_create_and_add_keymap(owl_keyhandler *kh, char *name, char *desc, void (*default_fn)(int), void (*prealways_fn)(int), void (*postalways_fn)(int))
     153owl_keymap *owl_keyhandler_create_and_add_keymap(owl_keyhandler *kh, char *name, char *desc, void (*default_fn)(owl_input), void (*prealways_fn)(owl_input), void (*postalways_fn)(owl_input))
    154154{
    155155  owl_keymap *km;
     
    202202/* processes a keypress.  returns 0 if the keypress was handled,
    203203 * 1 if not handled, -1 on error, and -2 if j==ERR. */
    204 int owl_keyhandler_process(owl_keyhandler *kh, int j)
     204int owl_keyhandler_process(owl_keyhandler *kh, owl_input j)
    205205{
    206206  owl_keymap     *km;
     
    214214
    215215  /* temporarily disallow C-`/C-SPACE until we fix associated bugs */
    216   if (j==ERR || j==0) {
     216  if (j.ch == ERR || j.ch == 0) {
    217217        return(-1);
    218218  }
     
    224224
    225225  /* deal with ESC prefixing */
    226   if (!kh->in_esc && j==27) {
     226  if (!kh->in_esc && j.ch == 27) {
    227227    kh->in_esc = 1;
    228228    return(0);
    229229  }
    230230  if (kh->in_esc) {
    231     j = OWL_META(j);
     231    j.ch = OWL_META(j.ch);
    232232    kh->in_esc = 0;
    233233  }
    234234 
    235   kh->kpstack[++(kh->kpstackpos)] = j;
     235  kh->kpstack[++(kh->kpstackpos)] = j.ch;
    236236  if (kh->kpstackpos >= OWL_KEYMAP_MAXSTACK) {
    237237    owl_keyhandler_reset(kh);
     
    260260      } else if (match == 2) {  /* exact match */
    261261        /* owl_function_debugmsg("processkey: found exact match in %s", km->name); */
    262         owl_keybinding_execute(kb, j);
     262        owl_keybinding_execute(kb, j.ch);
    263263        owl_keyhandler_reset(kh);
    264264        if (km->postalways_fn) {
  • keypress.c

    r948b942 r428834d  
    148148  }
    149149  if (!*kb) {
    150     if (j&OWL_META(0)) {
     150    if (j & OWL_META(0)) {
    151151      strcat(kb, "M-");
    152152      j &= ~OWL_META(0);
     
    163163      strcat(kb, kb2);   
    164164    }
     165   
    165166  } 
    166167  if (!*kb) {
  • keys.c

    ra6a4155 r5f3168a  
    296296/****************************************************************/
    297297
    298 void owl_keys_recwin_prealways(int j) {
     298void owl_keys_recwin_prealways(owl_input j) {
    299299  /* Clear the message line on subsequent key presses */
    300300  owl_function_makemsg("");
    301301}
    302302
    303 void owl_keys_editwin_default(int j) {
     303void owl_keys_editwin_default(owl_input j) {
    304304  owl_editwin *e;
    305305  if (NULL != (e=owl_global_get_typwin(&g))) {
    306     owl_editwin_process_char(e, j);
     306       owl_editwin_process_char(e, j);
    307307  }
    308308}
    309309
    310 void owl_keys_editwin_postalways(int j) {
     310void owl_keys_editwin_postalways(owl_input j) {
    311311  owl_editwin *e;
    312312  if (NULL != (e=owl_global_get_typwin(&g))) {
    313313    owl_editwin_post_process_char(e, j);
    314   } 
     314  }
    315315  owl_global_set_needrefresh(&g);
    316316}
    317317
    318 void owl_keys_popless_postalways(int j) {
     318void owl_keys_popless_postalways(owl_input j) {
    319319  owl_viewwin *v = owl_global_get_viewwin(&g);
    320320  owl_popwin *pw = owl_global_get_popwin(&g);
     
    325325}
    326326
    327 void owl_keys_default_invalid(int j) {
    328   if (j==ERR) return;
    329   if (j==410) return;
     327void owl_keys_default_invalid(owl_input j) {
     328  if (j.ch==ERR) return;
     329  if (j.ch==410) return;
    330330  owl_keyhandler_invalidkey(owl_global_get_keyhandler(&g));
    331331}
  • logging.c

    raf1920fd ree310eb  
    155155    to = owl_sprintf("jabber:%s", owl_message_get_recipient(m));
    156156  } else if (owl_message_is_type_aim(m)) {
     157    char *temp2;
    157158    temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
    158     downstr(temp);
    159     to = owl_sprintf("aim:%s", temp);
     159    temp2 = g_utf8_strdown(temp,-1);
     160    to = owl_sprintf("aim:%s", temp2);
     161    owl_free(temp2);
    160162    owl_free(temp);
    161163  } else {
     
    267269  } else if (owl_message_is_type_aim(m)) {
    268270    /* we do not yet handle chat rooms */
    269     char *normalto;
    270     normalto=owl_aim_normalize_screenname(owl_message_get_sender(m));
    271     downstr(normalto);
     271    char *normalto, *temp;
     272    temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
     273    normalto = g_utf8_strdown(temp, -1);
    272274    from=frombuff=owl_sprintf("aim:%s", normalto);
    273275    owl_free(normalto);
     276    owl_free(temp);
    274277  } else if (owl_message_is_type_loopback(m)) {
    275278    from=frombuff=owl_strdup("loopback");
     
    290293
    291294  ch=frombuff[0];
    292   if (!isalnum(ch)) from="weird";
     295  if (!g_ascii_isalnum(ch)) from="weird";
    293296
    294297  for (i=0; i<len; i++) {
     
    299302
    300303  if (!personal) {
    301     if (strcmp(from, "weird")) downstr(from);
     304    if (strcmp(from, "weird")) {
     305      char* temp = g_utf8_strdown(frombuff, -1);
     306      if (temp) {
     307        owl_free(frombuff);
     308        from = frombuff = temp;
     309      }
     310    }
    302311  }
    303312
  • message.c

    r18108b1e r07bfbc2  
    7979    owl_list_append_element(&(m->attributes), pair);
    8080  }
    81   owl_pair_set_value(pair, owl_strdup(attrvalue));
     81  owl_pair_set_value(pair, owl_validate_or_convert(attrvalue));
    8282}
    8383
     
    493493{
    494494  if(m->zwriteline) owl_free(m->zwriteline);
    495   m->zwriteline=strdup(line);
     495  m->zwriteline=owl_strdup(line);
    496496}
    497497
     
    535535  owl_fmtext_init_null(&b);
    536536 
    537   owl_fmtext_truncate_lines(&(m->fmtext->fmtext), aline, bline-aline+1, &a);
     537  owl_fmtext_truncate_lines(&(m->fmtext->fmtext), aline, bline-aline, &a);
    538538  owl_fmtext_truncate_cols(&a, acol, bcol, &b);
    539   if (fgcolor!=OWL_COLOR_DEFAULT) {
    540     owl_fmtext_colorize(&b, fgcolor);
    541   }
    542   if (bgcolor!=OWL_COLOR_DEFAULT) {
    543     owl_fmtext_colorizebg(&b, bgcolor);
    544   }
    545 
    546   if (owl_global_is_search_active(&g)) {
    547     owl_fmtext_search_and_highlight(&b, owl_global_get_search_string(&g));
    548   }
    549      
     539  owl_fmtext_colorize(&b, fgcolor);
     540  owl_fmtext_colorizebg(&b, bgcolor);
     541
    550542  owl_fmtext_curs_waddstr(&b, win);
    551543
     
    892884  }
    893885
    894   m->zwriteline=strdup("");
     886  m->zwriteline=owl_strdup("");
    895887
    896888  /* save the hostname */
     
    974966  }
    975967
    976   m->zwriteline=strdup("");
     968  m->zwriteline=owl_strdup("");
    977969
    978970  owl_message_set_body(m, "<uninitialized>");
  • owl.c

    r4cc0ee0b r07bfbc2  
    4949#include <termios.h>
    5050#include <sys/stat.h>
     51#include <locale.h>
    5152#include "owl.h"
    5253
     
    6061int stderr_replace(void);
    6162#endif
     63
     64#define STDIN 0
    6265
    6366static const char fileIdent[] = "$Id$";
     
    8588  int newstderr;
    8689#endif
     90 
     91  if (!GLIB_CHECK_VERSION (2, 12, 0))
     92    g_error ("GLib version 2.12.0 or above is needed.");
    8793
    8894  argcsave=argc;
     
    9399  debug=0;
    94100  initialsubs=1;
     101
     102  setlocale(LC_ALL, "");
     103 
    95104  if (argc>0) {
    96105    argv++;
     
    210219  {
    211220    owl_dispatch *d = owl_malloc(sizeof(owl_dispatch));
    212     d->fd = fileno(stdin);
     221    d->fd = STDIN;
    213222    d->cfunc = &owl_process_input;
    214223    d->pfunc = NULL;
     
    526535        owl_function_set_cursor(sepwin);
    527536      }
    528       owl_function_debugmsg("owl.c -- doupdate()");
    529537      doupdate();
    530538      owl_global_set_noneedrefresh(&g);
    531539    }
    532 
    533     /* Handle all keypresses.  If no key has been pressed, sleep for a
    534      * little bit, but otherwise do not.  This lets input be grabbed
    535      * as quickly as possbile */
    536540
    537541    /* select on FDs we know about. */
     
    670674void owl_process_input()
    671675{
    672   int ret, j;
     676  int ret;
     677  owl_input j;
    673678  owl_popwin *pw;
    674679  owl_editwin *tw;
    675 
     680  WINDOW *typwin;
     681
     682  typwin = owl_global_get_curs_typwin(&g);
    676683  while (1) {
    677     j = wgetch(owl_global_get_curs_typwin(&g));
    678     if (j == ERR) return;
    679 
     684    j.ch = wgetch(typwin);
     685    if (j.ch == ERR) return;
     686   
    680687    owl_global_set_lastinputtime(&g, time(NULL));
    681688    pw=owl_global_get_popwin(&g);
    682689    tw=owl_global_get_typwin(&g);
     690
     691    j.uch = '\0';
     692    if (j.ch >= KEY_MIN && j.ch <= KEY_MAX) {
     693      /* This is a curses control character. */
     694    }
     695    else if (j.ch > 0x7f && j.ch < 0xfe) {
     696      /* Pull in a full utf-8 character. */
     697      int bytes, i;
     698      char utf8buf[7];
     699      memset(utf8buf, '\0', 7);
     700     
     701      utf8buf[0] = j.ch;
     702     
     703      if ((j.ch & 0xc0) && (~j.ch & 0x20)) bytes = 2;
     704      else if ((j.ch & 0xe0) && (~j.ch & 0x10)) bytes = 3;
     705      else if ((j.ch & 0xf0) && (~j.ch & 0x08)) bytes = 4;
     706      else if ((j.ch & 0xf8) && (~j.ch & 0x04)) bytes = 5;
     707      else if ((j.ch & 0xfc) && (~j.ch & 0x02)) bytes = 6;
     708      else bytes = 1;
     709     
     710      for (i = 1; i < bytes; i++) {
     711        int tmp =  wgetch(typwin);
     712        /* If what we got was not a byte, or not a continuation byte */
     713        if (tmp > 0xff || !(tmp & 0x80 && ~tmp & 0x40)) {
     714          /* ill-formed UTF-8 code unit subsequence, put back the
     715             char we just got. */
     716          ungetch(tmp);
     717          j.ch = ERR;
     718          break;
     719        }
     720        utf8buf[i] = tmp;
     721      }
     722     
     723      if (j.ch != ERR) {
     724        if (g_utf8_validate(utf8buf, -1, NULL)) {
     725          j.uch = g_utf8_get_char(utf8buf);
     726        }
     727        else {
     728          j.ch = ERR;
     729        }
     730      }
     731    }
     732    else if (j.ch <= 0x7f) {
     733      j.uch = j.ch;
     734    }
    683735   
     736    owl_global_set_lastinputtime(&g, time(NULL));
    684737    /* find and activate the current keymap.
    685738     * TODO: this should really get fixed by activating
     
    691744      owl_function_activate_keymap("popless");
    692745    } else if (owl_global_is_typwin_active(&g)
    693                && owl_editwin_get_style(tw) == OWL_EDITWIN_STYLE_ONELINE) {
     746               && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_ONELINE) {
    694747      /*
    695748        owl_context_set_editline(owl_global_get_context(&g), tw);
     
    697750      */
    698751    } else if (owl_global_is_typwin_active(&g)
    699                && owl_editwin_get_style(tw) == OWL_EDITWIN_STYLE_MULTILINE) {
     752               && owl_editwin_get_style(tw)==OWL_EDITWIN_STYLE_MULTILINE) {
    700753      owl_context_set_editmulti(owl_global_get_context(&g), tw);
    701754      owl_function_activate_keymap("editmulti");
     
    706759    /* now actually handle the keypress */
    707760    ret = owl_keyhandler_process(owl_global_get_keyhandler(&g), j);
    708     if (ret != 0 && ret != 1) {
     761    if (ret!=0 && ret!=1) {
    709762      owl_function_makemsg("Unable to handle keypress");
    710763    }
  • owl.h

    r9c7a701 r5f3168a  
    5252#include <termios.h>
    5353#include <libfaim/aim.h>
     54#include <wchar.h>
    5455#include "config.h"
     56#include "glib.h"
    5557#ifdef HAVE_LIBZEPHYR
    5658#include <zephyr/zephyr.h>
     
    100102#define OWL_FMTEXT_ATTR_REVERSE   2
    101103#define OWL_FMTEXT_ATTR_UNDERLINE 4
     104
     105#define OWL_FMTEXT_UC_BASE 0x100000 /* Unicode Plane 16 - Supplementary Private Use Area-B*/
     106#define OWL_FMTEXT_UC_ATTR ( OWL_FMTEXT_UC_BASE | 0x800 )
     107#define OWL_FMTEXT_UC_ATTR_MASK 0x7
     108#define OWL_FMTEXT_UC_COLOR_BASE ( OWL_FMTEXT_UC_BASE | 0x400 )
     109#define OWL_FMTEXT_UC_FGCOLOR OWL_FMTEXT_UC_COLOR_BASE
     110#define OWL_FMTEXT_UC_BGCOLOR ( OWL_FMTEXT_UC_COLOR_BASE | 0x200 )
     111#define OWL_FMTEXT_UC_DEFAULT_COLOR 0x100
     112#define OWL_FMTEXT_UC_FGDEFAULT ( OWL_FMTEXT_UC_FGCOLOR | OWL_FMTEXT_UC_DEFAULT_COLOR )
     113#define OWL_FMTEXT_UC_BGDEFAULT ( OWL_FMTEXT_UC_BGCOLOR | OWL_FMTEXT_UC_DEFAULT_COLOR )
     114#define OWL_FMTEXT_UC_COLOR_MASK 0xFF
     115#define OWL_FMTEXT_UC_ALLCOLOR_MASK ( OWL_FMTEXT_UC_COLOR_MASK | OWL_FMTEXT_UC_DEFAULT_COLOR | 0x200)
     116#define OWL_FMTEXT_UC_STARTBYTE_UTF8 '\xf4'
     117
     118#define OWL_FMTEXT_UTF8_ATTR_NONE "\xf4\x80\xa0\x80"
     119#define OWL_FMTEXT_UTF8_FGDEFAULT "\xf4\x80\x94\x80"
     120#define OWL_FMTEXT_UTF8_BGDEFAULT "\xf4\x80\x9C\x80"
    102121
    103122#define OWL_COLOR_BLACK     0
     
    212231#endif
    213232
    214 #define OWL_META(key) ((key)|0200)
     233#define OWL_META(key) ((key)|010000)
    215234/* OWL_CTRL is definied in kepress.c */
    216235
     
    252271} owl_variable;
    253272
     273typedef struct _owl_input {
     274  int ch;
     275  gunichar uch;
     276} owl_input;
     277
    254278typedef struct _owl_fmtext {
    255279  int textlen;
    256280  int bufflen;
    257281  char *textbuff;
    258   char *fmbuff;
    259   short *fgcolorbuff;
    260   short *bgcolorbuff;
     282  char default_attrs;
     283  short default_fgcolor;
     284  short default_bgcolor;
    261285} owl_fmtext;
    262286
     
    491515  owl_list  bindings;           /* key bindings */
    492516  struct _owl_keymap *submap;   /* submap */
    493   void (*default_fn)(int j);    /* default action (takes a keypress) */
    494   void (*prealways_fn)(int j);  /* always called before a keypress is received */
    495   void (*postalways_fn)(int j); /* always called after keypress is processed */
     517  void (*default_fn)(owl_input j);      /* default action (takes a keypress) */
     518  void (*prealways_fn)(owl_input j);   /* always called before a keypress is received */
     519  void (*postalways_fn)(owl_input j);  /* always called after keypress is processed */
    496520} owl_keymap;
    497521
  • perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm

    r6b580b0 r5f3168a  
    2525use Net::DNS;
    2626use Getopt::Long;
     27
     28use utf8;
    2729
    2830our $VERSION = 0.1;
     
    377379                    $vars{jlogin_havepass} = 1;
    378380                    $conn->removeConnection($jidStr);
    379                     BarnOwl::start_password( "Password for $jidStr: ", \&do_login );
     381                    BarnOwl::start_password("Password for $jidStr: ", \&do_login );
    380382                    return "";
    381383                }
     
    486488    }
    487489    else {
    488         $to = shift @ARGV;
     490      $to = shift @ARGV;
    489491    }
    490492
     
    530532    $cmd .= " -t $jwrite_thread" if $jwrite_thread;
    531533    $cmd .= " -s $jwrite_subject" if $jwrite_subject;
    532     BarnOwl::start_edit_win( $cmd, \&process_owl_jwrite );
     534
     535    BarnOwl::start_edit_win($cmd, \&process_owl_jwrite );
    533536}
    534537
  • perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm

    r6b580b0 r5f3168a  
    11use warnings;
    22use strict;
     3use utf8;
    34
    45=head1 NAME
  • perl/modules/Jabber/lib/Net/XMPP/Debug.pm

    rc2bed55 rb7b2a76  
    189189                        {
    190190                            $self->{HANDLE}->autoflush(1);
     191                            binmode $self->{HANDLE}, ":utf8";
    191192                            $Net::XMPP::Debug::HANDLES{$args{file}} = $self->{HANDLE};
    192193                        }
  • perl/modules/Jabber/lib/Net/XMPP/Message.pm

    rc2bed55 r8574801  
    135135                            $Mess->SetMessage(TO=>"bob\@jabber.org",
    136136                                              Subject=>"Lunch",
    137                                               BoDy=>"Let's do lunch!");
     137                                              Body=>"Let's do lunch!");
    138138                            $Mess->SetMessage(to=>"bob\@jabber.org",
    139139                                              from=>"jabber.org",
  • perl/modules/Jabber/lib/XML/Stream.pm

    r5073972 ra8d5a39  
    16591659    {
    16601660        $self->debug(3,"Send: can_write");
    1661        
     1661
    16621662        $self->{SENDSTRING} = Encode::encode_utf8(join("",@_));
    16631663
  • perlconfig.c

    r9c7a701 r5f3168a  
    5555    j=owl_zephyr_get_num_fields(owl_message_get_notice(m));
    5656    for (i=0; i<j; i++) {
    57       ptr=owl_zephyr_get_field(owl_message_get_notice(m), i+1);
     57      ptr=owl_zephyr_get_field_as_utf8(owl_message_get_notice(m), i+1);
    5858      av_push(av_zfields, newSVpvn(ptr, strlen(ptr)));
    5959      owl_free(ptr);
     
    454454  PUSHMARK(SP);
    455455  for(i=0;i<argc;i++) {
    456     XPUSHs(sv_2mortal(newSVpv(argv[i], 0)));
     456    SV *tmp = newSVpv(argv[i], 0);
     457    SvUTF8_on(tmp);
     458    XPUSHs(sv_2mortal(tmp));
    457459  }
    458460  PUTBACK;
     
    493495{
    494496  SV *cb = (SV*)(e->cbdata);
     497  SV *text;
    495498  unsigned int n_a;
    496499  dSP;
     
    499502    owl_function_error("Perl callback is NULL!");
    500503  }
     504  text = newSVpv(owl_editwin_get_text(e), 0);
     505  SvUTF8_on(text);
    501506
    502507  ENTER;
     
    504509
    505510  PUSHMARK(SP);
    506   XPUSHs(sv_2mortal(newSVpv(owl_editwin_get_text(e), 0)));
     511  XPUSHs(sv_2mortal(text));
    507512  PUTBACK;
    508513 
  • text.c

    r72db971 r47519e1b  
    5050void owl_text_truncate_cols(char *out, char *in, int acol, int bcol)
    5151{
    52   char *ptr1, *ptr2, *tmpbuff, *last;
    53   int len;
    54 
     52  char *ptr_s, *ptr_e, *ptr_c, *tmpbuff, *last;
     53  int col, cnt, padding;
     54 
    5555  tmpbuff=owl_malloc(strlen(in)+20);
    5656
    5757  strcpy(tmpbuff, "");
    5858  last=in+strlen(in)-1;
    59   ptr1=in;
    60   while (ptr1<last) {
    61     ptr2=strchr(ptr1, '\n');
    62     if (!ptr2) {
     59  ptr_s=in;
     60  while (ptr_s<last) {
     61    ptr_e=strchr(ptr_s, '\n');
     62    if (!ptr_e) {
    6363      /* but this shouldn't happen if we end in a \n */
    6464      break;
    6565    }
    6666   
    67     if (ptr2==ptr1) {
     67    if (ptr_e==ptr_s) {
    6868      strcat(tmpbuff, "\n");
    69       ptr1++;
    70       continue;
    71     }
    72 
     69      ptr_s++;
     70      continue;
     71    }
     72
     73    col = 0;
     74    cnt = 0;
     75    padding = 0;
     76    ptr_c = ptr_s;
     77    while(col < bcol && ptr_c < ptr_e) {
     78      gunichar c = g_utf8_get_char(ptr_c);
     79      if (col + mk_wcwidth(c) > bcol) break;
     80      col += mk_wcwidth(c);
     81      ptr_c = g_utf8_next_char(ptr_c);
     82      if (col >= acol) {
     83        if (cnt == 0) {
     84          ptr_s = ptr_c;
     85          padding = col - acol;
     86        }
     87        ++cnt;
     88      }
     89    }
     90    if (cnt) {
     91      while(padding-- > 0) {
     92        strcat(tmpbuff, " ");
     93      }
     94      strncat(tmpbuff, ptr_s, ptr_c - ptr_s - 1);
     95    }
     96    strcat(tmpbuff, "\n");
     97    ptr_s = ptr_e + 1;
     98#if 0
    7399    /* we need to check that we won't run over here */
    74     if ( (ptr2-ptr1) < (bcol-acol) ) {
    75       len=ptr2-(ptr1+acol);
     100    if ( (ptr_e-ptr_s) < (bcol-acol) ) {
     101      len=ptr_e-(ptr_s+acol);
    76102    } else {
    77103      len=bcol-acol;
    78104    }
    79     if ((ptr1+len)>=last) {
    80       len-=last-(ptr1+len);
    81     }
    82 
    83     strncat(tmpbuff, ptr1+acol, len);
     105    if ((ptr_s+len)>=last) {
     106      len-=last-(ptr_s+len);
     107    }
     108
     109    strncat(tmpbuff, ptr_s+acol, len);
    84110    strcat(tmpbuff, "\n");
    85111
    86     ptr1=ptr2+1;
     112    ptr_s=ptr_e+1;
     113#endif
    87114  }
    88115  strcpy(out, tmpbuff);
     
    275302char *stristr(char *a, char *b)
    276303{
    277   char *x, *y, *ret;
    278 
    279   if ((x=owl_strdup(a))==NULL) return(NULL);
    280   if ((y=owl_strdup(b))==NULL) return(NULL);
    281   downstr(x);
    282   downstr(y);
    283   ret=strstr(x, y);
    284   if (ret==NULL) {
    285     owl_free(x);
    286     owl_free(y);
    287     return(NULL);
    288   }
    289   ret=ret-x+a;
    290   owl_free(x);
    291   owl_free(y);
     304  char *x, *y;
     305  char *ret = NULL;
     306  if ((x = g_utf8_casefold(a, -1)) != NULL) {
     307    if ((y = g_utf8_casefold(b, -1)) != NULL) {
     308      ret = strstr(x, y);
     309      if (ret != NULL) {
     310        ret = ret - x + a;
     311      }
     312      g_free(y);
     313    }
     314    g_free(x);
     315  }
    292316  return(ret);
    293317}
     
    296320int only_whitespace(char *s)
    297321{
    298   int i;
    299   for (i=0; s[i]; i++) {
    300     if (!isspace((int) s[i])) return(0);
     322  if (g_utf8_validate(s,-1,NULL)) {
     323    char *p;
     324    for(p = s; p[0]; p=g_utf8_next_char(p)) {
     325      if (!g_unichar_isspace(g_utf8_get_char(p))) return 0;
     326    }
     327  }
     328  else {
     329    int i;
     330    for (i=0; s[i]; i++) {
     331      if (!isspace((int) s[i])) return(0);
     332    }
    301333  }
    302334  return(1);
     
    327359  tolen  = strlen(to);
    328360  fromlen  = strlen(from);
    329   out = malloc(outlen);
     361  out = owl_malloc(outlen);
    330362
    331363  while (in[inpos]) {
  • util.c

    raf1920fd ree310eb  
    399399}
    400400
    401 /* downcase the string 'foo' */
    402 void downstr(char *foo)
    403 {
    404   int i;
    405   for (i=0; foo[i]!='\0'; i++) {
    406     foo[i]=tolower(foo[i]);
    407   }
    408 }
    409 
    410401/* Caller must free response.
    411402 * Takes in strings which are space-separated lists of tokens
     
    446437void *owl_malloc(size_t size)
    447438{
    448   return(malloc(size));
     439  return(g_malloc(size));
    449440}
    450441
    451442void owl_free(void *ptr)
    452443{
    453   free(ptr);
     444  g_free(ptr);
    454445}
    455446
    456447char *owl_strdup(const char *s1)
    457448{
    458   return(strdup(s1));
     449  return(g_strdup(s1));
    459450}
    460451
    461452void *owl_realloc(void *ptr, size_t size)
    462453{
    463   return(realloc(ptr, size));
     454  return(g_realloc(ptr, size));
    464455}
    465456
    466457/* allocates memory and returns the string or null.
    467458 * caller must free the string.
    468  * from Linux sprintf man page.
    469459 */
    470460char *owl_sprintf(const char *fmt, ...)
    471461{
    472   int n, size = 100;
    473   char *p;
    474462  va_list ap;
    475   if ((p = owl_malloc (size)) == NULL) return (NULL);
    476   while (1) {
    477     /* Try to print in the allocated space. */
    478     va_start(ap, fmt);
    479     n = vsnprintf (p, size, fmt, ap);
    480     va_end(ap);
    481     /* If that worked, return the string. */
    482     if (n > -1 && n < size)
    483       return p;
    484     /* Else try again with more space. */
    485     if (n > -1)    /* glibc 2.1 */
    486       size = n+1; /* precisely what is needed */
    487     else           /* glibc 2.0 */
    488       size *= 2;  /* twice the old size */
    489     if ((p = owl_realloc (p, size)) == NULL)
    490       return NULL;
    491   }
    492 }
     463  char *ret = NULL;
     464  va_start(ap, fmt);
     465  ret = g_strdup_vprintf(fmt, ap);
     466  va_end(ap);
     467  return ret;
     468}
     469
    493470
    494471/* Return the owl color associated with the named color.  Return -1
     
    776753}
    777754
    778 char * owl_get_datadir() {
    779     char * datadir = getenv("BARNOWL_DATA_DIR");
    780     if(datadir != NULL)
    781         return strchr(datadir, '=') + 1;
    782     return DATADIR;
     755char * owl_get_datadir()
     756{
     757  char * datadir = getenv("BARNOWL_DATA_DIR");
     758  if(datadir != NULL)
     759    return strchr(datadir, '=') + 1;
     760  return DATADIR;
     761}
     762
     763/* Strips format characters from a valid utf-8 string. Returns the
     764   empty string if 'in' does not validate. */
     765char * owl_strip_format_chars(char *in)
     766{
     767  char *r;
     768  if (g_utf8_validate(in, -1, NULL)) {
     769    char *s, *p;
     770    r = owl_malloc(strlen(in)+1);
     771    r[0] = '\0';
     772    s = in;
     773    p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     774    while(p) {
     775      /* If it's a format character, copy up to it, and skip all
     776         immediately following format characters. */
     777      if (owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     778        strncat(r, s, p-s);
     779        p = g_utf8_next_char(p);
     780        while (p && owl_fmtext_is_format_char(g_utf8_get_char(p))) {
     781          p = g_utf8_next_char(p);
     782        }
     783        s = p;
     784        p = strchr(s, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     785      }
     786      else {
     787        p = strchr(p+1, OWL_FMTEXT_UC_STARTBYTE_UTF8);
     788      }
     789    }
     790    if (s) strcat(r,s);
     791  }
     792  else {
     793    r = owl_strdup("");
     794  }
     795  return r;
     796}
     797
     798/* If in is not UTF-8, convert from ISO-8859-1. We may want to allow
     799 * the caller to specify an alternative in the future. We also strip
     800 * out characters in Unicode Plane 16, as we use that plane internally
     801 * for formatting.
     802 */
     803char * owl_validate_or_convert(char *in)
     804{
     805  if (g_utf8_validate(in, -1, NULL)) {
     806    return owl_strip_format_chars(in);
     807  }
     808  else {
     809    return g_convert(in, -1,
     810                     "UTF-8", "ISO-8859-1",
     811                     NULL, NULL, NULL);
     812  }
     813}
     814/* Attempts to convert 'in' to ISO-8859-1. Returns that if possible,
     815   else returns UTF-8.
     816 */
     817char * owl_get_iso_8859_1_if_possible(char *in)
     818{
     819  char *out;
     820  if (g_utf8_validate(in, -1, NULL)) {
     821    out = g_convert(in, -1,
     822                    "ISO-8859-1", "UTF-8",
     823                    NULL, NULL, NULL);
     824    if (!out) {
     825      out = owl_strdup(in);
     826    }
     827  }
     828  else {
     829    out = owl_strdup("");
     830  }
     831  return out;
     832}
     833
     834/* This is based on _extract() and _isCJ() from perl's Text::WrapI18N */
     835int owl_util_can_break_after(gunichar c)
     836{
     837 
     838  if (c == ' ') return 1;
     839  if (c >= 0x3000 && c <= 0x312f) {
     840    /* CJK punctuations, Hiragana, Katakana, Bopomofo */
     841    if (c == 0x300a || c == 0x300c || c == 0x300e ||
     842        c == 0x3010 || c == 0x3014 || c == 0x3016 ||
     843        c == 0x3018 || c == 0x301a)
     844      return 0;
     845    return 1;
     846  }
     847  if (c >= 0x31a0 && c <= 0x31bf) {return 1;}  /* Bopomofo */
     848  if (c >= 0x31f0 && c <= 0x31ff) {return 1;}  /* Katakana extension */
     849  if (c >= 0x3400 && c <= 0x9fff) {return 1;}  /* Han Ideogram */
     850  if (c >= 0xf900 && c <= 0xfaff) {return 1;}  /* Han Ideogram */
     851  if (c >= 0x20000 && c <= 0x2ffff) {return 1;}  /* Han Ideogram */
     852  return 0;
    783853}
    784854
  • viewwin.c

    r8721756 r47519e1b  
    7373  owl_fmtext_truncate_cols(&fm1, v->rightshift, v->wincols-1+v->rightshift, &fm2);
    7474
    75   owl_fmtext_curs_waddstr(&fm2, v->curswin);
     75  owl_fmtext_curs_waddstr_without_search(&fm2, v->curswin);
    7676
    7777  /* print the message at the bottom */
  • zcrypt.c

    r9ceee9d r34509d5  
    385385
    386386/* Build a space-separated string from argv from elements between start  *
    387  * and end - 1.  malloc()'s the returned string. */
     387 * and end - 1.  owl_malloc()'s the returned string. */
    388388char *BuildArgString(char **argv, int start, int end) {
    389389  int len = 1;
     
    397397
    398398  /* Allocate memory */
    399   result = (char *)malloc(len);
     399  result = (char *)owl_malloc(len);
    400400  if (result) {
    401401    /* Build the string */
     
    482482      /* Prepare result to be returned */
    483483      char *temp = keyfile;
    484       keyfile = (char *)malloc(strlen(temp) + 1);
     484      keyfile = (char *)owl_malloc(strlen(temp) + 1);
    485485      if (keyfile) {
    486486        strcpy(keyfile, temp);
     
    611611      }
    612612      use_buffer = TRUE;
    613       if ((inptr = inbuff = (char *)malloc(MAX_RESULT)) == NULL) {
     613      if ((inptr = inbuff = (char *)owl_malloc(MAX_RESULT)) == NULL) {
    614614        printf("Memory allocation error\n");
    615615        return FALSE;
     
    639639      printf("Could not run zwrite\n");
    640640      if (freein && inbuff) {
    641         free(inbuff);
     641        owl_free(inbuff);
    642642      }
    643643      return(FALSE);
     
    685685
    686686  /* Free the input buffer, if necessary */
    687   if (freein && inbuff) free(inbuff);
     687  if (freein && inbuff) owl_free(inbuff);
    688688
    689689  return(!error);
  • zephyr.c

    r9c7a701 r5f3168a  
    353353  return(owl_strdup(""));
    354354}
     355
     356char *owl_zephyr_get_field_as_utf8(ZNotice_t *n, int j)
     357{
     358  int i, count, save;
     359
     360  /* If there's no message here, just run along now */
     361  if (n->z_message_len == 0)
     362    return(owl_strdup(""));
     363
     364  count=save=0;
     365  for (i = 0; i < n->z_message_len; i++) {
     366    if (n->z_message[i]=='\0') {
     367      count++;
     368      if (count == j) {
     369        /* just found the end of the field we're looking for */
     370        return(owl_validate_or_convert(n->z_message + save));
     371      } else {
     372        save = i + 1;
     373      }
     374    }
     375  }
     376  /* catch the last field, which might not be null terminated */
     377  if (count == j - 1) {
     378    char *tmp, *out;
     379    tmp = owl_malloc(n->z_message_len-save+5);
     380    memcpy(tmp, n->z_message+save, n->z_message_len-save);
     381    tmp[n->z_message_len-save]='\0';
     382    out = owl_validate_or_convert(tmp);
     383    owl_free(tmp);
     384    return out;
     385  }
     386
     387  return(owl_strdup(""));
     388}
    355389#else
    356390char *owl_zephyr_get_field(void *n, int j)
    357391{
    358392  return(owl_strdup(""));
     393}
     394char *owl_zephyr_get_field_as_utf8(ZNotice_t *n, int j)
     395{
     396  return owl_zephyr_get_field(n, j);
    359397}
    360398#endif
  • zwrite.c

    r1fe100c r7b1d048  
    4444        break;
    4545      }
    46       z->class=owl_strdup(myargv[1]);
     46      z->class=owl_get_iso_8859_1_if_possible(myargv[1]);
    4747      myargv+=2;
    4848      myargc-=2;
     
    5252        break;
    5353      }
    54       z->inst=owl_strdup(myargv[1]);
     54      z->inst=owl_get_iso_8859_1_if_possible(myargv[1]);
    5555      myargv+=2;
    5656      myargc-=2;
     
    6060        break;
    6161      }
    62       z->realm=owl_strdup(myargv[1]);
     62      z->realm=owl_get_iso_8859_1_if_possible(myargv[1]);
    6363      myargv+=2;
    6464      myargc-=2;
     
    6868        break;
    6969      }
    70       z->zsig=owl_strdup(myargv[1]);
     70      z->zsig=owl_get_iso_8859_1_if_possible(myargv[1]);
    7171      myargv+=2;
    7272      myargc-=2;
     
    7676        break;
    7777      }
    78       z->opcode=owl_strdup(myargv[1]);
     78      z->opcode=owl_get_iso_8859_1_if_possible(myargv[1]);
    7979      myargv+=2;
    8080      myargc-=2;
     
    9393      myargv++;
    9494      myargc--;
    95       z->message=owl_strdup("");
     95      z->message=owl_get_iso_8859_1_if_possible("");
    9696      while (myargc) {
    97         z->message=realloc(z->message, strlen(z->message)+strlen(myargv[0])+5);
     97        z->message=owl_realloc(z->message, strlen(z->message)+strlen(myargv[0])+5);
    9898        strcat(z->message, myargv[0]);
    9999        strcat(z->message, " ");
     
    113113    } else {
    114114      /* anything unattached is a recipient */
    115       owl_list_append_element(&(z->recips), strdup(myargv[0]));
     115      owl_list_append_element(&(z->recips), owl_get_iso_8859_1_if_possible(myargv[0]));
    116116      myargv++;
    117117      myargc--;
     
    146146
    147147    if (zsigowlvar && *zsigowlvar) {
    148       z->zsig=owl_strdup(zsigowlvar);
     148      z->zsig=owl_get_iso_8859_1_if_possible(zsigowlvar);
    149149    } else if (zsigproc && *zsigproc) {
    150150      FILE *file;
     
    161161      if (!file) {
    162162        if (zsigzvar && *zsigzvar) {
    163           z->zsig=owl_strdup(zsigzvar);
     163          z->zsig=owl_get_iso_8859_1_if_possible(zsigzvar);
    164164        }
    165165      } else {
     
    175175      }
    176176    } else if (zsigzvar) {
    177       z->zsig=owl_strdup(zsigzvar);
     177      z->zsig=owl_get_iso_8859_1_if_possible(zsigzvar);
    178178    } else if (((pw=getpwuid(getuid()))!=NULL) && (pw->pw_gecos)) {
    179       z->zsig=strdup(pw->pw_gecos);
     179      z->zsig=owl_get_iso_8859_1_if_possible(pw->pw_gecos);
    180180      ptr=strchr(z->zsig, ',');
    181181      if (ptr) {
     
    218218  int i, j;
    219219  char toline[LINE];
     220  char *tmp = NULL;
    220221
    221222  if (z->message) owl_free(z->message);
     
    231232      }
    232233    }
    233     z->message=owl_sprintf("%s\n%s", toline, msg);
     234    tmp = owl_get_iso_8859_1_if_possible(msg);
     235    z->message=owl_sprintf("%s\n%s", toline, tmp);
    234236  } else {
    235     z->message=owl_strdup(msg);
    236   }
     237    z->message=owl_get_iso_8859_1_if_possible(msg);
     238  }
     239  if (tmp) owl_free(tmp);
    237240}
    238241
     
    305308{
    306309  if (z->opcode) owl_free(z->opcode);
    307   z->opcode=owl_strdup(opcode);
     310  z->opcode=owl_get_iso_8859_1_if_possible(opcode);
    308311}
    309312
Note: See TracChangeset for help on using the changeset viewer.