about summary refs log tree commit diff stats
path: root/src/LYStrings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/LYStrings.c')
-rw-r--r--src/LYStrings.c586
1 files changed, 397 insertions, 189 deletions
diff --git a/src/LYStrings.c b/src/LYStrings.c
index f5c88ffd..153e7490 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -92,10 +92,13 @@ PRIVATE int set_clicked_link ARGS2(int,x,int,y)
 
 
 /*
- * LYstrncpy() terminates strings with a null byte.
- * Writes a null byte into the n+1 byte of dst.
+ *  LYstrncpy() terminates strings with a null byte.
+ *  Writes a null byte into the n+1 byte of dst.
  */
-PUBLIC char * LYstrncpy ARGS3(char *,dst, char *,src, int,n)
+PUBLIC char *LYstrncpy ARGS3(
+	char *,		dst,
+	char *,		src,
+	int,		n)
 {
     char *val;
     int len=strlen(src);
@@ -110,6 +113,10 @@ PUBLIC char * LYstrncpy ARGS3(char *,dst, char *,src, int,n)
         *(dst+n) = '\0';
     return val;
 }
+
+#define IS_NEW_GLYPH(ch) (utf_flag && ((unsigned char)(ch)&0xc0) != 0x80)
+#define IS_UTF_EXTRA(ch) (utf_flag && ((unsigned char)(ch)&0xc0) == 0x80)
+
 #ifdef EXP_CHARTRANS
 /*
  * LYmbcsstrncpy() terminates strings with a null byte.
@@ -118,7 +125,7 @@ PUBLIC char * LYstrncpy ARGS3(char *,dst, char *,src, int,n)
  * either bytes or glyphs (mbcs sequences) (currently only UTF8).
  */
 PUBLIC char * LYmbcsstrncpy ARGS5(char *,dst, char *,src, int,n_bytes,
-				  int,n_glyphs,	int,enc)
+				  int,n_glyphs,	int,utf_flag)
 {
     char *val = dst;
     int i_bytes = 0, i_glyphs = 0;
@@ -128,15 +135,13 @@ PUBLIC char * LYmbcsstrncpy ARGS5(char *,dst, char *,src, int,n_bytes,
     if (n_glyphs < 0)
         n_glyphs = 0;
 
-#define IS_NEW_GLYPH(ch) (enc && ((unsigned char)(ch)&0xc0) != 0x80)
-
-    for (; *src != '\0' && i_bytes < n_bytes;
-	 i_bytes++) {
-	if (IS_NEW_GLYPH(*src))
+    for (; *src != '\0' && i_bytes < n_bytes; i_bytes++) {
+	if (IS_NEW_GLYPH(*src)) {
 	    if (i_glyphs++ >= n_glyphs) {
 		*dst = '\0';
 		return val;
 	    }
+	}
 	*(dst++) = *(src++);
     }
     *dst = '\0';
@@ -145,8 +150,44 @@ PUBLIC char * LYmbcsstrncpy ARGS5(char *,dst, char *,src, int,n_bytes,
 }
 #endif /* EXP_CHARTRANS */
 
-#undef GetChar
+/*
+ *  LYmbcsstrlen() returns the printable length of a string
+ *  that might contain IsSpecial or multibyte (CJK or UTF8)
+ *  characters. - FM
+ */
+PUBLIC int LYmbcsstrlen ARGS2(
+	char *,		str,
+	BOOL,		utf_flag)
+{
+    int i, j, len = 0;
+
+    if (!str && *str)
+	return(len);
 
+    for (i = 0; str[i] != '\0'; i++) {
+	if (IsSpecialAttrChar(str[i])) {
+	    continue;
+	} else {
+	    len++;
+	}
+	if (IS_NEW_GLYPH(str[i])) {
+	    j = 0;
+	    while (str[(i + 1)] != '\0' && 
+	    	   !IsSpecialAttrChar(str[(i + 1)]) &&
+		   j < 5 &&
+		   IS_UTF_EXTRA(str[(i + 1)])) {
+		i++;
+		j++;
+	    }
+	} else if (!utf_flag && HTCJK != NOCJK && !isascii(str[i]) &&
+		    str[(i + 1)] != '\0' &&
+		    !IsSpecialAttrChar(str[(i + 1)])) {
+	    i++;
+	}
+    }
+
+    return(len);
+}
 #undef GetChar
 
 #ifdef USE_SLANG
@@ -233,9 +274,9 @@ PRIVATE int map_function_to_key ARGS1(char, keysym)
 #endif
 
 /*
- * LYgetch() translates some escape sequences and may fake noecho
+ *  LYgetch() translates some escape sequences and may fake noecho.
  */
-PUBLIC int LYgetch ()
+PUBLIC int LYgetch NOARGS
 {
     int a, b, c, d = -1;
 
@@ -456,10 +497,9 @@ re_read:
     }
 #if HAVE_KEYPAD
     else {
-
-	/* convert keypad() mode keys into Lynx defined keys
+	/*
+	 *  Convert keypad() mode keys into Lynx defined keys.
 	 */
-
 	switch(c) {
 	case KEY_DOWN:	           /* The four arrow keys ... */
 	   c=DNARROW;
@@ -563,35 +603,29 @@ re_read:
     }
 #endif /* defined(HAVE_KEYPAD) */
 
-    if (c > DO_NOTHING)
-    /* Don't return raw values for KEYPAD symbols which we may have missed
-     * in the switch above if they are obviously invalid when used as an
-     * index into (e.g.) keypad[]. - kw
-     */
-       return (0);
-    else
-    return(c);
+    if (c > DO_NOTHING) {
+	/*
+	 *  Don't return raw values for KEYPAD symbols which we may have
+	 *  missed in the switch above if they are obviously invalid when
+	 *  used as an index into (e.g.) keypad[]. - KW
+	 */
+	return (0);
+    } else {
+	return(c);
+    }
 }
 
 
 /*
- * display the current value of the string and allow the user
- * to edit it.
- */
-
-#ifdef USE_SLANG
-#define GetYX(y,x)   y = SLsmg_get_row(), x = SLsmg_get_column()
-#else
-#ifdef getyx
-#define GetYX(y,x)   getyx(stdscr,y,x)
-#else
-#define GetYX(y,x)   y = stdscr->_cury, x = stdscr->_curx
-#endif /* getyx */
-#endif /* USE_SLANG */
+**  Display the current value of the string and allow the user
+**  to edit it.
+*/
 
 #define EDREC    EditFieldData
 
-/* shorthand to get rid of all most of the "edit->suchandsos" */
+/*
+ *  Shorthand to get rid of all most of the "edit->suchandsos".
+ */
 #define Buf      edit->buffer
 #define Pos      edit->pos
 #define StrLen   edit->strlen
@@ -600,11 +634,16 @@ re_read:
 #define DspStart edit->xpan
 #define Margin   edit->margin
 
-PUBLIC void LYSetupEdit ARGS4(EDREC *,edit, char *,old, int,maxstr, int,maxdsp)
+PUBLIC void LYSetupEdit ARGS4(
+	EDREC *,	edit,
+	char *,		old,
+	int,		maxstr,
+	int,		maxdsp)
 {
-    /* Initialize edit record */
-
-    GetYX(edit->sy, edit->sx);
+    /*
+     *  Initialize edit record
+     */
+    LYGetYX(edit->sy, edit->sx);
     edit->pad   = ' ';
     edit->dirty = TRUE;
     edit->panon = FALSE;
@@ -620,22 +659,42 @@ PUBLIC void LYSetupEdit ARGS4(EDREC *,edit, char *,old, int,maxstr, int,maxdsp)
         if (DspWdth > 4)    /* Else "{}" take up precious screen space */
 	    edit->panon = TRUE;
 
-	/* Figure out margins. If too big we do a lot of unnecessary
-	 * scrolling. If too small user doesn't have sufficient look-ahead.
-	 * Let's say 25% for each margin, upper bound is 10 columns.
+	/*
+	 *  Figure out margins.  If too big, we do a lot of unnecessary
+	 *  scrolling.  If too small, user doesn't have sufficient
+	 *  look-ahead.  Let's say 25% for each margin, upper bound is
+	 *  10 columns.
 	 */
 	Margin = DspWdth/4;
 	if (Margin > 10)
 	    Margin = 10;
     }
-    strcpy(edit->buffer, old);
+
+    /*
+     *  We expect the called function to pass us a default (old) value
+     *  with a length that is less than or equal to maxstr, and to
+     *  handle any messaging associated with actions to achieve that
+     *  requirement.  However, in case the calling function screwed
+     *  up, we'll check it here, and ensure that no buffer overrun can
+     *  occur by loading only as much of the head as fits. - FM
+     */
+    if (strlen(old) >= maxstr) {
+	strncpy(edit->buffer, old, maxstr);
+	edit->buffer[maxstr] = '\0';
+	StrLen = maxstr;
+    } else {
+	strcpy(edit->buffer, old);
+    }
 }
 
-PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
+PUBLIC int LYEdit1 ARGS4(
+	EDREC *,	edit,
+	int,		ch,
+	int,		action,
+	BOOL,		maxMessage)
 {   /* returns 0    character processed
      *         ch   otherwise
      */
-
     int i;
     int length;
 
@@ -648,15 +707,15 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
     switch (action) {
     case LYE_AIX:
         /*
-	 * Hex 97.
-	 * Fall through as a character for CJK.
-	 * Otherwise, we treat this as LYE_ENTER.
+	 *  Hex 97.
+	 *  Fall through as a character for CJK.
+	 *  Otherwise, we treat this as LYE_ENTER.
 	 */
 	 if (HTCJK == NOCJK)
 	     return(ch);
     case LYE_CHAR:
         /*
-	 * ch is printable or ISO-8859-1 escape character.
+	 *  ch is printable or ISO-8859-1 escape character.
 	 */
 	if (Pos <= (MaxLen) && StrLen < (MaxLen)) {
 	    for(i = length; i >= Pos; i--)    /* Make room */
@@ -671,8 +730,8 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_BACKW:
         /*
-	 * Backword.
-	 * Definition of word is very naive: 1 or more a/n characters.
+	 *  Backword.
+	 *  Definition of word is very naive: 1 or more a/n characters.
 	 */
 	while (Pos && !isalnum(Buf[Pos-1]))
 	    Pos--;
@@ -682,7 +741,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_FORWW:
         /*
-	 * Word forward.
+	 *  Word forward.
 	 */
 	while (isalnum(Buf[Pos]))
 	    Pos++;   /* '\0' is not a/n */
@@ -692,28 +751,28 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_ERASE:
         /*
-	 * Erase the line to start fresh.
+	 *  Erase the line to start fresh.
 	 */
 	 Buf[0] = '\0';
 	 /* fall through */
 
     case LYE_BOL:
         /*
-	 * Go to first column.
+	 *  Go to first column.
 	 */
 	Pos = 0;
 	break;
 
     case LYE_EOL:
         /*
-	 * Go to last column.
+	 *  Go to last column.
 	 */
 	Pos = length;
 	break;
 
     case LYE_DELNW:
         /*
-	 * Delete next word.
+	 *  Delete next word.
 	 */
 	{
 	    int pos0 = Pos;
@@ -725,7 +784,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_DELPW:
         /*
-	 * Delete previous word.
+	 *  Delete previous word.
 	 */
 	{
 	    int pos0 = Pos;
@@ -738,7 +797,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_DELN:
         /*
-	 * Delete next character
+	 *  Delete next character
 	 */
 	if (Pos >= length)
 	    break;
@@ -747,7 +806,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_DELP:
         /*
-	 * Delete preceding character.
+	 *  Delete preceding character.
 	 */
 	if (length == 0 || Pos == 0)
 	    break;
@@ -760,7 +819,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_DELC:
         /*
-	 * Delete current character.
+	 *  Delete current character.
 	 */
 	if (length == 0)
 	    break;
@@ -772,7 +831,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_FORW:
         /*
-	 * Move cursor to the right.
+	 *  Move cursor to the right.
 	 */
 	if (Pos < length)
 	    Pos++;
@@ -780,7 +839,7 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 
     case LYE_BACK:
         /*
-	 * Left-arrow move cursor to the left.
+	 *  Left-arrow move cursor to the left.
 	 */
 	if (Pos > 0)
 	    Pos--;
@@ -805,7 +864,8 @@ PUBLIC int LYEdit1 ARGS4(EDREC *,edit, int,ch, int,action, BOOL,maxMessage)
 }
 
 
-PUBLIC void LYRefreshEdit ARGS1(EDREC *,edit)
+PUBLIC void LYRefreshEdit ARGS1(
+	EDREC *,	edit)
 {
     int i;
     int length;
@@ -876,14 +936,14 @@ PUBLIC void LYRefreshEdit ARGS1(EDREC *,edit)
     }
 
     /*
-     * Erase rest of input area.
+     *  Erase rest of input area.
      */
-    padsize= DspWdth-nrdisplayed;
+    padsize = DspWdth-nrdisplayed;
     while (padsize--)
         addch((unsigned char)edit->pad);
 
     /*
-     * Scrolling indicators.
+     *  Scrolling indicators.
      */
     if (edit->panon) {
         if ((DspStart + nrdisplayed) < length) {
@@ -901,9 +961,14 @@ PUBLIC void LYRefreshEdit ARGS1(EDREC *,edit)
 }
 
 
-PUBLIC int LYgetstr ARGS4(char *,inputline, int,hidden,
-			  int,bufsize, int,recall)
+PUBLIC int LYgetstr ARGS4(
+	char *,		inputline,
+	int,		hidden,
+	int,		bufsize,
+	int,		recall)
 {
+    extern BOOLEAN term_letter;     /* Flag from terminate_letter() AST  */
+    extern BOOLEAN term_options;    /* Flag from terminate_options() AST */
     extern BOOLEAN term_message;    /* Flag from terminate_message() AST */
 #ifdef VMS
     extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST       */
@@ -912,7 +977,7 @@ PUBLIC int LYgetstr ARGS4(char *,inputline, int,hidden,
     int ch;
     EditFieldData MyEdit;
 
-    GetYX(y,x);                 /* Use screen from cursor position to eol */
+    LYGetYX(y, x);		/* Use screen from cursor position to eol */
     MaxStringSize = (bufsize < sizeof(MyEdit.buffer)) ?
     		    (bufsize - 1) : (sizeof(MyEdit.buffer) - 1);
     LYSetupEdit(&MyEdit, inputline, MaxStringSize, (LYcols-1)-x);
@@ -943,9 +1008,9 @@ again:
 	    /* fall through */
 	case LYE_AIX:
 	    /*
-	     * Hex 97.
-	     * Treat as a character for CJK.
-	     * Otherwise, we treat this as LYE_ENTER.
+	     *  Hex 97.
+	     *  Treat as a character for CJK.
+	     *  Otherwise, we treat this as LYE_ENTER.
 	     */
 	    if (HTCJK != NOCJK && ch != '\t') {
 	        LYLineEdit(&MyEdit,ch, FALSE);
@@ -953,7 +1018,7 @@ again:
 	    }
 	case LYE_ENTER:
 	    /*
-	     * Terminate the string and return.
+	     *  Terminate the string and return.
 	     */
 	    strcpy(inputline, MyEdit.buffer);
             return(ch);
@@ -961,7 +1026,7 @@ again:
 
         case LYE_ABORT:
 	    /*
-	     * Control-C or Control-G aborts.
+	     *  Control-C or Control-G aborts.
 	     */
 	    inputline[0] = '\0';		   
 	    return(-1);
@@ -974,11 +1039,13 @@ again:
 }
 
 /*
- * LYstrstr will find the first occurence of the string pointed to by tarptr
- * in the string pointed to by chptr.  
- * It is a case insensitive search.
+ *  LYstrstr will find the first occurence of the string
+ *  pointed to by tarptr in the string pointed to by chptr.  
+ *  It is a case insensitive search.
  */
-PUBLIC char * LYstrstr ARGS2(char *,chptr, char *,tarptr)
+PUBLIC char * LYstrstr ARGS2(
+	char *,		chptr,
+	char *,		tarptr)
 {
     register char *tmpchptr, *tmptarptr;
 
@@ -999,16 +1066,19 @@ PUBLIC char * LYstrstr ARGS2(char *,chptr, char *,tarptr)
 }	
 
 /*
- * LYno_attr_char_case_strstr will find the first occurence of the string 
- * pointed to by tarptr in the string pointed to by chptr.
- * It ignores the characters: LY_UNDERLINE_START_CHAR and
- * 			      LY_UNDERLINE_END_CHAR
- * 			      LY_BOLD_START_CHAR
- * 			      LY_BOLD_END_CHAR
- *			      if present in chptr.
- * It is a case insensitive search.
+ *  LYno_attr_char_case_strstr will find the first occurence of the
+ *  string pointed to by tarptr in the string pointed to by chptr.
+ *  It ignores the characters: LY_UNDERLINE_START_CHAR and
+ * 			       LY_UNDERLINE_END_CHAR
+ * 			       LY_BOLD_START_CHAR
+ * 			       LY_BOLD_END_CHAR
+ *				LY_SOFT_HYPHEN
+ *			       if present in chptr.
+ *  It is a case insensitive search.
  */
-PUBLIC char * LYno_attr_char_case_strstr ARGS2(char *,chptr, char *,tarptr)
+PUBLIC char * LYno_attr_char_case_strstr ARGS2(
+	char *,		chptr,
+	char *,		tarptr)
 {
     register char *tmpchptr, *tmptarptr;
 
@@ -1019,10 +1089,10 @@ PUBLIC char * LYno_attr_char_case_strstr ARGS2(char *,chptr, char *,tarptr)
         chptr++;
 
     for (; *chptr != '\0'; chptr++) {
-
         if (TOUPPER(*chptr) == TOUPPER(*tarptr)) {
-
-            /* see if they line up */
+            /*
+	     *  See if they line up.
+	     */
 	    tmpchptr = chptr+1;
 	    tmptarptr = tarptr+1;
 
@@ -1031,20 +1101,15 @@ PUBLIC char * LYno_attr_char_case_strstr ARGS2(char *,chptr, char *,tarptr)
 
 	    while (1) {
 		 if (!IsSpecialAttrChar(*tmpchptr)) {
-
                     if (TOUPPER(*tmpchptr) != TOUPPER(*tmptarptr))
 			break;
-
 		    tmpchptr++;
 		    tmptarptr++;
-
 		 } else {
 		    tmpchptr++;
 		 }
-
                  if (*tmptarptr == '\0')
 		     return(chptr);
-
 		 if (*tmpchptr == '\0')
 		     break;
 	    }
@@ -1055,16 +1120,19 @@ PUBLIC char * LYno_attr_char_case_strstr ARGS2(char *,chptr, char *,tarptr)
 }
 
 /*
- * LYno_attr_char_strstr will find the first occurence of the string
- * pointed to by tarptr in the string pointed to by chptr.
- * It ignores the characters: LY_UNDERLINE_START_CHAR and
- *                            LY_UNDERLINE_END_CHAR
- *                            LY_BOLD_START_CHAR
- *                            LY_BOLD_END_CHAR
- *			      if present in chptr.
- * It is a case sensitive search.
+ *  LYno_attr_char_strstr will find the first occurence of the
+ *  string pointed to by tarptr in the string pointed to by chptr.
+ *  It ignores the characters: LY_UNDERLINE_START_CHAR and
+ *                             LY_UNDERLINE_END_CHAR
+ *                             LY_BOLD_START_CHAR
+ *                             LY_BOLD_END_CHAR
+ *				LY_SOFT_HYPHEN
+ *			       if present in chptr.
+ *  It is a case sensitive search.
  */
-PUBLIC char * LYno_attr_char_strstr ARGS2(char *,chptr, char *,tarptr)
+PUBLIC char * LYno_attr_char_strstr ARGS2(
+	char *,		chptr,
+	char *,		tarptr)
 {
     register char *tmpchptr, *tmptarptr;
 
@@ -1075,32 +1143,27 @@ PUBLIC char * LYno_attr_char_strstr ARGS2(char *,chptr, char *,tarptr)
         chptr++;
 
     for (; *chptr != '\0'; chptr++) {
-
         if ((*chptr) == (*tarptr)) {
-
-            /* see if they line up */
-            tmpchptr = chptr+1;
-            tmptarptr = tarptr+1;
+            /*
+	     *  See if they line up.
+	     */
+            tmpchptr = chptr + 1;
+            tmptarptr = tarptr + 1;
 
 	    if (*tmptarptr == '\0')  /* one char target */
 		 return(chptr);
 
             while (1) {
 		 if (!IsSpecialAttrChar(*tmpchptr)) {
-
                     if ((*tmpchptr) != (*tmptarptr))
                         break;
-
                     tmpchptr++;
                     tmptarptr++;
-
                  } else {
                     tmpchptr++;
                  }
-
                  if (*tmptarptr == '\0')
                      return(chptr);
-
                  if (*tmpchptr == '\0')
                      break;
             }
@@ -1110,9 +1173,6 @@ PUBLIC char * LYno_attr_char_strstr ARGS2(char *,chptr, char *,tarptr)
     return(NULL);
 }
 
-#ifdef EXP_CHARTRANS
-
-#define IS_UTFEXTRA(ch) (utf_flag && ((unsigned char)(ch)&0xc0) == 0x80)
 /*
  * LYno_attr_mbcs_case_strstr will find the first occurence of the string 
  * pointed to by tarptr in the string pointed to by chptr.
@@ -1122,45 +1182,111 @@ PUBLIC char * LYno_attr_char_strstr ARGS2(char *,chptr, char *,tarptr)
  * It ignores the characters: LY_UNDERLINE_START_CHAR and
  * 			      LY_UNDERLINE_END_CHAR
  * 			      LY_BOLD_START_CHAR
- * 			      LY_BOLD_END_CHAR[B
+ *				LY_BOLD_END_CHAR
+ *				LY_SOFT_HYPHEN
  *			      if present in chptr.
  * It assumes UTF8 if utf_flag is set.
- * It is a case insensitive search.
+ *  It is a case insensitive search. - KW & FM
  */
-PUBLIC char * LYno_attr_mbcs_case_strstr ARGS4(char *,chptr, char *,tarptr,
-					       BOOL, utf_flag, int *,nendp)
+PUBLIC char * LYno_attr_mbcs_case_strstr ARGS5(
+	char *,		chptr,
+	char *,		tarptr,
+	BOOL,		utf_flag,
+	int *,		nstartp,
+	int *,		nendp)
 {
     register char *tmpchptr, *tmptarptr;
     int len = 0;
+    int offset;
 
-    if (!chptr)
+    if (!(chptr && tarptr))
         return(NULL);
 
+    /*
+     *  Skip initial IsSpecial chars. - FM
+     */
     while (IsSpecialAttrChar(*chptr) && *chptr != '\0')
         chptr++;
 
+    /*
+     *  Seek a first target match. - FM
+     */
     for (; *chptr != '\0'; chptr++) {
-	    
-        if (TOUPPER(*chptr) == TOUPPER(*tarptr)) {
+	if ((!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+	     *chptr == *tarptr &&
+	     *(chptr + 1) != '\0' &&
+	     !IsSpecialAttrChar(*(chptr + 1))) ||
+	    TOUPPER(*chptr) == TOUPPER(*tarptr)) {
 	    int tarlen = 0;
+	    offset = len;
 	    len++;
 
-            /* see if they line up */
-	    tmpchptr = chptr+1;
-	    tmptarptr = tarptr+1;
-
-	    if (*tmptarptr == '\0') { /* one char target */
+            /*
+	     *  See if they line up.
+	     */
+	    tmpchptr = (chptr + 1);
+	    tmptarptr = (tarptr + 1);
+
+	    if (*tmptarptr == '\0') {
+		/*
+		 *  One char target.
+		 */
+		*nstartp = offset;
 		*nendp = len;
 		 return(chptr);
 	    }
+	    if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+		 *chptr == *tarptr &&
+		 *tmpchptr != '\0' &&
+		 !IsSpecialAttrChar(*tmpchptr)) {
+		/*
+		 *  Check the CJK mutibyte. - FM
+		 */
+		if (*tmpchptr == *tmptarptr) {
+		    /*
+		     *  It's a match.  Advance to next char. - FM
+		     */
+		    tmpchptr++;
+		    tmptarptr++;
+		    if (*tmptarptr == '\0') {
+		        /*
+			 *  One character match. - FM
+			 */
+			*nstartp = offset;
+			*nendp = len + tarlen;
+			return(chptr);
+		    }
+		    tarlen++;
+		} else {
+		    /*
+		     *  It's not a match, so go back to
+		     *  seeking a first target match. - FM
+		     */
+		    chptr++;
+		    continue;
+		}
+	    }
+	    /*
+	     *  See if the rest of the target matches. - FM
+	     */
 	    while (1) {
 		 if (!IsSpecialAttrChar(*tmpchptr)) {
-
-                    if (TOUPPER(*tmpchptr) != TOUPPER(*tmptarptr))
+		    if (!utf_flag && HTCJK != NOCJK && !isascii(*tmpchptr)) {
+			if (*tmpchptr == *tmptarptr &&
+			    *(tmpchptr + 1) == *(tmptarptr + 1) &&
+			    !IsSpecialAttrChar(*(tmpchptr + 1))) {
+			    tmpchptr++;
+			    tmptarptr++;
+			} else {
 			break;
+			}
+		    } else if (TOUPPER(*tmpchptr) != TOUPPER(*tmptarptr)) {
+			break;
+		    }
 
-		    if (!IS_UTFEXTRA(*tmptarptr))
+		    if (!IS_UTF_EXTRA(*tmptarptr)) {
 			tarlen++;
+		    }
 		    tmpchptr++;
 		    tmptarptr++;
 
@@ -1169,17 +1295,23 @@ PUBLIC char * LYno_attr_mbcs_case_strstr ARGS4(char *,chptr, char *,tarptr,
 		 }
 
                  if (*tmptarptr == '\0') {
+		    *nstartp = offset;
 		     *nendp = len + tarlen;
 		     return(chptr);
 		 }
-		 if (*tmpchptr == '\0')
+		if (*tmpchptr == '\0') {
 		     break;
 	    }
-        } else if (!( IS_UTFEXTRA(*chptr) ||
+	    }
+        } else if (!(IS_UTF_EXTRA(*chptr) ||
 		      IsSpecialAttrChar(*chptr))) {
+	    if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+		*(chptr + 1) != '\0' &&
+		!IsSpecialAttrChar(*(chptr + 1))) {
+		chptr++;
+	    }
 	    len++;
 	}
-		       
     } /* end for */
 
     return(NULL);
@@ -1188,51 +1320,114 @@ PUBLIC char * LYno_attr_mbcs_case_strstr ARGS4(char *,chptr, char *,tarptr,
 /*
  * LYno_attr_mbcs_strstr will find the first occurence of the string
  * pointed to by tarptr in the string pointed to by chptr.
- * It takes account of MultiByte Character Sequences (UTF8).
- * The physical lenght of the displayed string up to the end of the target
- * string is returned in *nendp if the search is successful.
+ *  It takes account of CJK and MultiByte Character Sequences (UTF8).
+ *  The physical lengths of the displayed string up to the start and
+ *  end of the target string are returned in *nstartp and *nendp if
+ *  the search is successful.
  * It ignores the characters: LY_UNDERLINE_START_CHAR and
  *                            LY_UNDERLINE_END_CHAR
  *                            LY_BOLD_START_CHAR
  *                            LY_BOLD_END_CHAR
+ *				LY_SOFT_HYPHEN
  *			      if present in chptr.
  * It assumes UTF8 if utf_flag is set.
- * It is a case sensitive search.
+ *  It is a case sensitive search. - KW & FM
  */
-PUBLIC char * LYno_attr_mbcs_strstr ARGS4(char *,chptr, char *,tarptr,
-					       BOOL, utf_flag, int *,nendp)
+PUBLIC char * LYno_attr_mbcs_strstr ARGS5(
+	char *,		chptr,
+	char *,		tarptr,
+	BOOL,		utf_flag,
+	int *,		nstartp,
+	int *,		nendp)
 {
     register char *tmpchptr, *tmptarptr;
     int len = 0;
+    int offset;
 
-    if (!chptr)
+    if (!(chptr && tarptr))
         return(NULL);
 
+    /*
+     *  Skip initial IsSpecial chars. - FM
+     */
     while (IsSpecialAttrChar(*chptr) && *chptr != '\0')
         chptr++;
 
+    /*
+     *  Seek a first target match. - FM
+     */
     for (; *chptr != '\0'; chptr++) {
 
         if ((*chptr) == (*tarptr)) {
 	    int tarlen = 0;
+	    offset = len;
 	    len++;
 
-            /* see if they line up */
-            tmpchptr = chptr+1;
-            tmptarptr = tarptr+1;
-
-	    if (*tmptarptr == '\0') { /* one char target */
+            /*
+	     *  See if they line up.
+	     */
+            tmpchptr = (chptr + 1);
+            tmptarptr = (tarptr + 1);
+
+	    if (*tmptarptr == '\0') {
+		/*
+		 *  One char target.
+		 */
+		*nstartp = offset;
 		*nendp = len + 1;
 		 return(chptr);
 	    }
+	    if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+		 *tmpchptr != '\0' &&
+		 !IsSpecialAttrChar(*tmpchptr)) {
+		/*
+		 *  Check the CJK mutibyte. - FM
+		 */
+		if (*tmpchptr == *tmptarptr) {
+		    /*
+		     *  It's a match.  Advance to next char. - FM
+		     */
+		    tmpchptr++;
+		    tmptarptr++;
+		    if (*tmptarptr == '\0') {
+		        /*
+			 *  One character match. - FM
+			 */
+			*nstartp = offset;
+			*nendp = len + tarlen;
+			return(chptr);
+		    }
+		    tarlen++;
+		} else {
+		    /*
+		     *  It's not a match, so go back to
+		     *  seeking a first target match. - FM
+		     */
+		    chptr++;
+		    continue;
+		}
+	    }
+	    /*
+	     *  See if the rest of the target matches. - FM
+	     */
             while (1) {
 		 if (!IsSpecialAttrChar(*tmpchptr)) {
-
-                    if ((*tmpchptr) != (*tmptarptr))
+		    if (!utf_flag && HTCJK != NOCJK && !isascii(*tmpchptr)) {
+			if (*tmpchptr == *tmptarptr &&
+			    *(tmpchptr + 1) == *(tmptarptr + 1) &&
+			    !IsSpecialAttrChar(*(tmpchptr + 1))) {
+			    tmpchptr++;
+			    tmptarptr++;
+			} else {
+			    break;
+			}
+		    } else if ((*tmpchptr) != (*tmptarptr)) {
                         break;
+		    }
 
-		    if (!IS_UTFEXTRA(*tmptarptr))
+		    if (!IS_UTF_EXTRA(*tmptarptr)) {
 			tarlen++;
+		    }
                     tmpchptr++;
                     tmptarptr++;
 
@@ -1241,60 +1436,73 @@ PUBLIC char * LYno_attr_mbcs_strstr ARGS4(char *,chptr, char *,tarptr,
                  }
 
                  if (*tmptarptr == '\0') {
+		    *nstartp = offset;
 		     *nendp = len + tarlen;
 		     return(chptr);
 		 }
-                 if (*tmpchptr == '\0')
+		if (*tmpchptr == '\0') {
                      break;
             }
-        } else if (!( IS_UTFEXTRA(*chptr) ||
+	    }
+        } else if (!(IS_UTF_EXTRA(*chptr) ||
 		      IsSpecialAttrChar(*chptr))) {
+	    if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+		*(chptr + 1) != '\0' &&
+		!IsSpecialAttrChar(*(chptr + 1))) {
+		chptr++;
+	    }
 	    len++;
         }
     } /* end for */
 
     return(NULL);
 }
-#endif /* EXP_CHARTRANS */
 
-/*      Allocate a new copy of a string, and returns it
-*/
-PUBLIC char * SNACopy ARGS3 (char **,dest, CONST char *,src, int,n)
+/*
+ *  Allocate a new copy of a string, and returns it.
+ */
+PUBLIC char * SNACopy ARGS3(
+	char **,	dest,
+	CONST char *,	src,
+	int,		n)
 {
-  FREE(*dest);
-  if (src) {
-    *dest = (char *) calloc (1, n + 1);
-    if (*dest == NULL) {
-	fprintf(stderr,"Tried to calloc %d bytes\n",n);
-	outofmem(__FILE__, "SNACopy");
+    FREE(*dest);
+    if (src) {
+	*dest = (char *)calloc(1, n + 1);
+	if (*dest == NULL) {
+	    if (TRACE)
+	        fprintf(stderr, "Tried to calloc %d bytes\n", n);
+	    outofmem(__FILE__, "SNACopy");
+	}
+	strncpy (*dest, src, n);
+	*(*dest + n) = '\0'; /* terminate */
     }
-    strncpy (*dest, src, n);
-    *(*dest + n) = '\0'; /* terminate */
-  }
-  return *dest;
+    return *dest;
 }
 
-/*      String Allocate and Concatenate
-*/
-PUBLIC char * SNACat ARGS3 (char **,dest, CONST char *,src, int,n)
+/*
+ *  String Allocate and Concatenate.
+ */
+PUBLIC char * SNACat ARGS3(
+	char **,	dest,
+	CONST char *,	src,
+	int,		n)
 {
-  if (src && *src) {
-    if (*dest) {
-      int length = strlen (*dest);
-      *dest = (char *) realloc (*dest, length + n + 1);
-      if (*dest == NULL)
-          outofmem(__FILE__, "SNACat");
-      strncpy (*dest + length, src, n);
-      *(*dest + length + n) = '\0'; /* terminate */
-    } else {
-      *dest = (char *) calloc (1, strlen(src) + 1);
-      if (*dest == NULL)
-          outofmem(__FILE__, "SNACat");
-      strncpy (*dest, src, n);
-      *dest[n] = '\0'; /* terminate */
+    if (src && *src) {
+	if (*dest) {
+	    int length = strlen(*dest);
+	    *dest = (char *)realloc(*dest, length + n + 1);
+	    if (*dest == NULL)
+		outofmem(__FILE__, "SNACat");
+	    strncpy(*dest + length, src, n);
+	    *(*dest + length + n) = '\0'; /* terminate */
+	} else {
+	    *dest = (char *)calloc(1, strlen(src) + 1);
+	    if (*dest == NULL)
+		outofmem(__FILE__, "SNACat");
+	    strncpy(*dest, src, n);
+	    *dest[n] = '\0'; /* terminate */
+	}
     }
-  }
-  return *dest;
+    return *dest;
 }
-
-