From 6d2c21c4eb53964be68892a738e103c85421cf89 Mon Sep 17 00:00:00 2001 From: piaip Date: Tue, 7 Jun 2005 04:13:59 +0000 Subject: DBCS Aware for getdata and edit. Thanks to Michael Hsin (mhsin) for his patching edit. git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@2781 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- include/modes.h | 6 +++ mbbsd/edit.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++- mbbsd/io.c | 66 ++++++++++++++++++++++++++++++--- sample/pttbbs.conf | 5 +++ 4 files changed, 174 insertions(+), 8 deletions(-) diff --git a/include/modes.h b/include/modes.h index 317effac..0ea53e19 100644 --- a/include/modes.h +++ b/include/modes.h @@ -148,6 +148,12 @@ #define AUTHOR_NEXT (RS_AUTHOR | RS_FORWARD) #define AUTHOR_PREV (RS_AUTHOR) +/* DBCS aware modes */ +enum { + DBCS_ASCII, + DBCS_LEADING, + DBCS_TRAILING, +} _DBCS_STATUS; enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; diff --git a/mbbsd/edit.c b/mbbsd/edit.c index 7b828631..dea2ffa7 100644 --- a/mbbsd/edit.c +++ b/mbbsd/edit.c @@ -76,7 +76,8 @@ enum { * ¯S®í²Å¸¹½s¿è * raw mode: * ignore Ctrl('S'), Ctrl('Q'), Ctrl('T') - * ÃÙ¤ê: ³o¦³¤°»ò¥Î? + * ÃÙ¤ê: ³o¦³¤°»ò¥Î? ¬Ý°_¨Ó¬O modem ¤W¶Ç¥Î (¨S¤H¦b¥Î³o­Ó¤F§a) + * ®³¨Ó·í dbcs option §a * * editor ¤ä´©¤F°Ï¶ô¿ï¾Üªº¥\¯à¡]¦h¦æ¿ï¨ú ©Î ³æ¦æ¤¤ªº¤ù¬q¡^¡A¹ï©ó¤@­Ó selected * block¡A¥i¥H cut, copy, cancel, ©ÎªÌ¦s¨ì¼È¨úÀÉ¡A¬Æ¦Ü¬O©¹¥ª/¥k shift¡C¸Ô¨£ @@ -159,7 +160,6 @@ static editor_internal_t *curr_buf = NULL; static const char fp_bak[] = "bak"; - static const char * const BIG5[13] = { "¡A¡F¡G¡B¡N¡C¡H¡I¡E¡T¡]¡^¡©¡ª¡«¡¬", "¢b¢c¢d¢e¢f¢g¢h¢i¢j¢k¢l¢m¢n¢o¢pùþ ", @@ -212,6 +212,42 @@ static const char *table_mode[6] = { "¢¦" }; +#ifdef DBCSAWARE_EDIT + +static char mbcs_mode =1; + +#define IS_BIG5_HI(x) (0x81 <= (x) && (x) <= 0xfe) +#define IS_BIG5_LOS(x) (0x40 <= (x) && (x) <= 0x7e) +#define IS_BIG5_LOE(x) (0x80 <= (x) && (x) <= 0xfe) +#define IS_BIG5_LO(x) (IS_BIG5_LOS(x) || IS_BIG5_LOE(x)) +#define IS_BIG5(hi,lo) (IS_BIG5_HI(hi) && IS_BIG5_LO(lo)) + +int mchar_len(unsigned char *str) +{ + return ((str[0] != '\0' && str[1] != '\0' && IS_BIG5(str[0], str[1])) ? + 2 : + 1); +} + +#define FC_RIGHT (0) +#define FC_LEFT (~FC_RIGHT) + +int fix_cursor(char *str, int pos, unsigned int dir) +{ + int newpos, w; + + for(newpos = 0; + *str != '\0' && + (w = mchar_len(str), + newpos + 1 + (dir & (w - 1))) <= pos; + str += w, newpos += w) + ; + + return newpos; +} + +#endif + /* °O¾ÐÅéºÞ²z»P½s¿è³B²z */ static void @@ -1846,6 +1882,28 @@ display_textline_internal(textline_t *p, int i, int min, int max) outs("\033[m"); (*output)(p->data + max); } else + +#ifdef DBCSAWARE_EDIT + if(mbcs_mode && curr_buf->edit_margin > 0) + { + if(curr_buf->edit_margin >= p->len) + { + (*output)(""); + } else { + int newpnt = curr_buf->edit_margin; + unsigned char *pdata = &p->data[0] + curr_buf->edit_margin; + if(mbcs_mode) + newpnt = fix_cursor(p->data, newpnt, FC_LEFT); + if(newpnt == curr_buf->edit_margin-1) + { + (*output)(" "); + pdata++; + } + (*output)(pdata); + } + + } else +#endif (*output)((curr_buf->edit_margin < p->len) ? &p->data[curr_buf->edit_margin] : ""); if (inblock) @@ -2652,6 +2710,10 @@ vedit(char *fpath, int saveheader, int *islocal) curr_buf->oldcurrline = curr_buf->currline; break; case 'R': +#ifdef DBCSAWARE_EDIT + case 'r': + mbcs_mode =! mbcs_mode; +#endif curr_buf->raw_mode ^= 1; break; case 'I': @@ -2767,6 +2829,10 @@ vedit(char *fpath, int saveheader, int *islocal) if (curr_buf->ansimode) curr_buf->currpnt = n2ansi(curr_buf->currpnt, curr_buf->currline); curr_buf->currpnt--; +#ifdef DBCSAWARE_EDIT + if(mbcs_mode) + curr_buf->currpnt = fix_cursor(curr_buf->currline->data, curr_buf->currpnt, FC_LEFT); +#endif if (curr_buf->ansimode) curr_buf->currpnt = ansi2n(curr_buf->currpnt, curr_buf->currline); } else if (curr_buf->currline->prev) { @@ -2781,6 +2847,10 @@ vedit(char *fpath, int saveheader, int *islocal) if (curr_buf->ansimode) curr_buf->currpnt = n2ansi(curr_buf->currpnt, curr_buf->currline); curr_buf->currpnt++; +#ifdef DBCSAWARE_EDIT + if(mbcs_mode) + curr_buf->currpnt = fix_cursor(curr_buf->currline->data, curr_buf->currpnt, FC_RIGHT); +#endif if (curr_buf->ansimode) curr_buf->currpnt = ansi2n(curr_buf->currpnt, curr_buf->currline); } else if (curr_buf->currline->next) { @@ -2898,8 +2968,23 @@ vedit(char *fpath, int saveheader, int *islocal) } break; } +#ifndef DBCSAWARE_EDIT curr_buf->currpnt--; delete_char(); +#else + { + int newpnt = curr_buf->currpnt - 1; + + if(mbcs_mode) + newpnt = fix_cursor(curr_buf->currline->data, newpnt, FC_LEFT); + + for(; curr_buf->currpnt > newpnt;) + { + curr_buf->currpnt --; + delete_char(); + } + } +#endif } break; case Ctrl('D'): @@ -2916,7 +3001,19 @@ vedit(char *fpath, int saveheader, int *islocal) } curr_buf->redraw_everything = YEA; } else { +#ifndef DBCSAWARE_EDIT delete_char(); +#else + { + int w = 1; + + if(mbcs_mode) + w = mchar_len(curr_buf->currline->data + curr_buf->currpnt); + + for(; w > 0; w --) + delete_char(); + } +#endif if (curr_buf->ansimode) curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, curr_buf->currline), curr_buf->currline); } @@ -2971,6 +3068,10 @@ vedit(char *fpath, int saveheader, int *islocal) window_scroll_down(); else if (cursor_at_bottom_line()) window_scroll_up(); +#ifdef DBCSAWARE_EDIT + if(mbcs_mode) + curr_buf->currpnt = fix_cursor(curr_buf->currline->data, curr_buf->currpnt, FC_LEFT); +#endif } if (curr_buf->ansimode) diff --git a/mbbsd/io.c b/mbbsd/io.c index 35130710..0b9a7f53 100644 --- a/mbbsd/io.c +++ b/mbbsd/io.c @@ -529,6 +529,32 @@ strip_nonebig5(unsigned char *str, int maxlen) str[len]='\0'; } +#ifdef DBCSAWARE_GETDATA + +int getDBCSstatus(unsigned char *s, int pos) +{ + int sts = DBCS_ASCII; + while(pos >= 0) + { + if(sts == DBCS_LEADING) + sts = DBCS_TRAILING; + else if (*s >= 0x80) + { + sts = DBCS_LEADING; + } else { + sts = DBCS_ASCII; + } + s++, pos--; + } + return sts; +} + +#else + +#define dbcs_off (1) + +#endif + int oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo) { @@ -604,22 +630,42 @@ oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo) clen = currchar = strlen(buf); break; case KEY_LEFT: - if (currchar) + if (currchar > 0) + { --currchar; +#ifdef DBCSAWARE_GETDATA + if(currchar > 0 && + getDBCSstatus(buf, currchar) == DBCS_TRAILING) + currchar --; +#endif + } break; case KEY_RIGHT: if (buf[currchar]) + { ++currchar; +#ifdef DBCSAWARE_GETDATA + if(buf[currchar] && + getDBCSstatus(buf, currchar) == DBCS_TRAILING) + currchar++; +#endif + } break; case '\177': case Ctrl('H'): if (currchar) { - currchar--; - clen--; +#ifdef DBCSAWARE_GETDATA + int dbcs_off = (getDBCSstatus(buf, currchar-1) == DBCS_TRAILING) ? 2 : 1; +#endif + currchar -= dbcs_off; + clen -= dbcs_off; for (i = currchar; i <= clen; i++) - buf[i] = buf[i + 1]; + buf[i] = buf[i + dbcs_off]; move(y, x + clen); outc(' '); +#ifdef DBCSAWARE_GETDATA + if(dbcs_off > 1) outc(' '); +#endif move(y, x); edit_outs(buf); } @@ -627,6 +673,7 @@ oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo) case Ctrl('Y'): currchar = 0; case Ctrl('K'): + /* we shoud be able to avoid DBCS issues in ^K mode */ buf[currchar] = '\0'; move(y, x + currchar); for (i = currchar; i < clen; i++) @@ -636,11 +683,18 @@ oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo) case Ctrl('D'): case KEY_DEL: if (buf[currchar]) { - clen--; +#ifdef DBCSAWARE_GETDATA + int dbcs_off = (buf[currchar+1] && + getDBCSstatus(buf, currchar+1) == DBCS_TRAILING) ? 2 : 1; +#endif + clen -= dbcs_off; for (i = currchar; i <= clen; i++) - buf[i] = buf[i + 1]; + buf[i] = buf[i + dbcs_off]; move(y, x + clen); outc(' '); +#ifdef DBCSAWARE_GETDATA + if(dbcs_off > 1) outc(' '); +#endif move(y, x); edit_outs(buf); } diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf index dabecad3..8e5cb552 100644 --- a/sample/pttbbs.conf +++ b/sample/pttbbs.conf @@ -118,6 +118,11 @@ /* ­Y©w¸q, ¦b¨Ï¥ÎªÌµù¥U¤§«e, ·|¥ýÅã¥Ü¥X¸ÓÀÉ®×, ¸g¨Ï¥ÎªÌ½T»{«á¤~¯àµù¥U */ //#define HAVE_USERAGREEMENT "etc/UserAgreement" +/* DBCS Aware: Åý´å¼Ð¤£·|¶]¨ì DBCS trailing bytes ¤W + * ¦ýª`·N³o·|¦Y¤£¤Ö CPU */ +//#define DBCSAWARE_GETDATA +//#define DBCSAWARE_EDIT + /* ¨Ï¥Î·s¦¡ªº pmore (piaip's more) ¥N´À¦¡ bug §ì¤£§¹ªº more */ #define USE_PIAIP_MORE -- cgit v1.2.3