Blob Blame History Raw
diff -up ./src/chewingio.c.phraseChoiceRearward ./src/chewingio.c
--- ./src/chewingio.c.phraseChoiceRearward	2008-12-02 00:29:20.000000000 +1000
+++ ./src/chewingio.c	2009-08-03 14:46:41.000000000 +1000
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 
 #include "chewing-utf8-util.h"
 #include "global.h"
@@ -50,6 +51,12 @@ void (*TerminateServices[ TerminateServi
 static int countTerminateService = 0;
 static int bTerminateCompleted = 0;
 
+/**
+ * This has to be global, as user might mixed space and down
+ * key as selection starter.
+ */
+static int cursor_orig=-1;
+
 char *kb_type_str[] = {
 	"KB_DEFAULT",
 	"KB_HSU",
@@ -75,14 +82,14 @@ CHEWING_API int chewing_KBStr2Num( char 
 	return KB_DEFAULT;
 }
 
-#ifdef ENABLE_DEBUG     
+#ifdef ENABLE_DEBUG
 static void TerminateDebug()
 {
 	DEBUG_OUT( "DEBUG: logging service is about to terminate.\n" );
 	if ( fp_g ) {
 		fclose( fp_g );
 	}
-}               
+}
 #endif
 
 int addTerminateService( void (*callback)() )
@@ -103,7 +110,7 @@ int addTerminateService( void (*callback
 CHEWING_API ChewingContext *chewing_new()
 {
 	ChewingContext *ctx;
-	
+
 	ChewingData *internal_data = ALC( ChewingData, 1 );
 	ChewingOutput *internal_output = ALC( ChewingOutput, 1 );
 	ctx = ALC( ChewingContext, 1 );
@@ -159,7 +166,7 @@ CHEWING_API int chewing_Init(
 		dbg_path = FAILSAFE_OUTPUT;
 	        fp_g = fopen( dbg_path, "w+" );
 		if ( ! fp_g ) {
-			fprintf( stderr, 
+			fprintf( stderr,
 				"Failed to record debug message in file.\n"
 				"--> Output to stderr\n" );
 		}
@@ -237,14 +244,14 @@ CHEWING_API void chewing_Terminate()
 		if ( TerminateServices[ i ] ) {
 #ifdef ENABLE_DEBUG
 			/* Can't output to debug file because it's about to close */
-			fprintf( stderr, 
+			fprintf( stderr,
 				EMPHASIZE( "Terminating service #%d / %d" ) ".\n",
 				i, countTerminateService );
 #endif
 			(*TerminateServices[ i ])();
 		}
 	}
-	
+
 	/* XXX: should check if the services are really completed. */
 	bTerminateCompleted = 1;
 	return;
@@ -403,7 +410,7 @@ CHEWING_API void chewing_set_ChiEngMode(
 	ctx->data->bChiSym = ( mode == CHINESE_MODE ? 1 : 0 );
 }
 
-CHEWING_API int chewing_get_ChiEngMode( ChewingContext *ctx ) 
+CHEWING_API int chewing_get_ChiEngMode( ChewingContext *ctx )
 {
 	return ctx->data->bChiSym;
 }
@@ -413,7 +420,7 @@ CHEWING_API void chewing_set_ShapeMode( 
 	ctx->data->bFullShape = (mode == FULLSHAPE_MODE ? 1 : 0);
 }
 
-CHEWING_API int chewing_get_ShapeMode( ChewingContext *ctx ) 
+CHEWING_API int chewing_get_ShapeMode( ChewingContext *ctx )
 {
 	return ctx->data->bFullShape;
 }
@@ -435,7 +442,7 @@ static int DoSelect( ChewingData *pgdata
 			if ( pgdata->choiceInfo.isSymbol ) {
 				SymbolChoice( pgdata, num );
 			}
-			else { 
+			else {
 				/* change the select interval & selectStr & nSelect */
 				AddSelect( pgdata, num );
 				/* second, call choice module */
@@ -472,13 +479,13 @@ CHEWING_API int chewing_handle_Space( Ch
 	CheckAndResetRange( pgdata );
 
 	if ( pgdata->bSelect ) {
-		if ( pgdata->choiceInfo.pageNo < ( pgdata->choiceInfo.nPage - 1 ) ) {
+	    if ( pgdata->choiceInfo.pageNo < ( pgdata->choiceInfo.nPage - 1 ) ) {
 			return chewing_handle_Right( ctx );
 		}
 	}
 
 	if ( ! ChewingIsEntering( pgdata ) ) {
-		if ( pgdata->bFullShape ) {
+	    if ( pgdata->bFullShape ) {
 			rtn = FullShapeSymbolInput( ' ', pgdata );
 		}
 		else {
@@ -489,9 +496,9 @@ CHEWING_API int chewing_handle_Space( Ch
 		pgdata->chiSymbolBufLen = 0;
 		pgdata->chiSymbolCursor = 0;
 		keystrokeRtn = KEYSTROKE_COMMIT;
-	} 
+	}
 	else if ( pgdata->bChiSym != CHINESE_MODE ) {
-		/* see if buffer contains nothing */
+	    /* see if buffer contains nothing */
 		if ( pgdata->chiSymbolBufLen == 0 ) {
 			bQuickCommit = 1;
 		}
@@ -507,11 +514,11 @@ CHEWING_API int chewing_handle_Space( Ch
 		if ( rtn == SYMBOL_KEY_ERROR ) {
 			keystrokeRtn = KEYSTROKE_IGNORE;
 			/*
-			 * If the key is not a printable symbol, 
+			 * If the key is not a printable symbol,
 			 * then it's wrong to commit it.
 			 */
 			bQuickCommit = 0;
-		} 
+		}
 		else {
 			keystrokeRtn = KEYSTROKE_ABSORB;
 		}
@@ -524,9 +531,9 @@ CHEWING_API int chewing_handle_Space( Ch
 		/* Quick commit */
 		else {
 			DEBUG_OUT(
-				"\t\tQuick commit buf[0]=%c\n", 
+				"\t\tQuick commit buf[0]=%c\n",
 				pgdata->chiSymbolBuf[ 0 ].s[ 0 ] );
-			pgo->commitStr[ 0 ] = pgdata->chiSymbolBuf[ 0 ]; 
+			pgo->commitStr[ 0 ] = pgdata->chiSymbolBuf[ 0 ];
 			pgo->nCommitStr = 1;
 			pgdata->chiSymbolBufLen = 0;
 			pgdata->chiSymbolCursor = 0;
@@ -534,10 +541,11 @@ CHEWING_API int chewing_handle_Space( Ch
 		}
 	}
 	else {
+
 		rtn = ZuinPhoInput( &( pgdata->zuinData ), ' ' );
 		switch ( rtn ) {
 			case ZUIN_ABSORB:
-				keystrokeRtn = KEYSTROKE_ABSORB;
+			    keystrokeRtn = KEYSTROKE_ABSORB;
 				break;
 			case ZUIN_COMMIT:
 				AddChi( pgdata->zuinData.phone, pgdata );
@@ -557,10 +565,21 @@ CHEWING_API int chewing_handle_Space( Ch
 					toSelect = 1;
 
 				if ( toSelect ) {
-					if ( ! pgdata->bSelect )
-						ChoiceFirstAvail( pgdata );
-					else
-						ChoiceNextAvail( pgdata );
+				    if( ! pgdata->bSelect ) {
+					cursor_orig=pgdata->chiSymbolCursor;
+					ChoiceFirstAvail( pgdata );
+				    }
+				    else {
+					if ( pgdata->config.bPhraseChoiceRearward ){
+					    int avail_willbe=(pgdata->availInfo.currentAvail>0)?
+						pgdata->availInfo.currentAvail-1: pgdata->availInfo.nAvail - 1;
+					    pgdata->chiSymbolCursor=cursor_orig - pgdata->availInfo.avail[avail_willbe].len;
+					    if (chewing_buffer_Len(ctx)>cursor_orig){
+						pgdata->chiSymbolCursor++;
+					    }
+					}
+					ChoiceNextAvail( pgdata );
+				    }
 				}
 				else if ( pgdata->symbolKeyBuf[ key_buf_cursor ] ) {
 					/* Open Symbol Choice List */
@@ -643,7 +662,7 @@ CHEWING_API int chewing_handle_Enter( Ch
 		keystrokeRtn = KEYSTROKE_COMMIT;
 		WriteChiSymbolToBuf( pgo->commitStr, nCommitStr, pgdata );
 		AutoLearnPhrase( pgdata );
-		CleanAllBuf( pgdata );  
+		CleanAllBuf( pgdata );
 		pgo->nCommitStr = nCommitStr;
 	}
 
@@ -664,12 +683,12 @@ CHEWING_API int chewing_handle_Del( Chew
 	}
 
 	if ( ! pgdata->bSelect ) {
-		if ( 
-			! ZuinIsEntering( &( pgdata->zuinData ) ) && 
+		if (
+			! ZuinIsEntering( &( pgdata->zuinData ) ) &&
 			pgdata->chiSymbolCursor < pgdata->chiSymbolBufLen ) {
 			ChewingKillChar(
-				pgdata, 
-				pgdata->chiSymbolCursor, 
+				pgdata,
+				pgdata->chiSymbolCursor,
 				NONDECREASE_CURSOR );
 		}
 		CallPhrasing( pgdata );
@@ -696,7 +715,7 @@ CHEWING_API int chewing_handle_Backspace
 		}
 		else if ( pgdata->chiSymbolCursor > 0 ) {
 			ChewingKillChar(
-				pgdata, 
+				pgdata,
 				pgdata->chiSymbolCursor - 1,
 				DECREASE_CURSOR );
 		}
@@ -735,7 +754,7 @@ CHEWING_API int chewing_handle_Up( Chewi
 
 CHEWING_API int chewing_handle_Down( ChewingContext *ctx )
 {
-	ChewingData *pgdata = ctx->data;
+        ChewingData *pgdata = ctx->data;
 	ChewingOutput *pgo = ctx->output;
 	int toSelect = 0;
 	int keystrokeRtn = KEYSTROKE_ABSORB;
@@ -756,13 +775,22 @@ CHEWING_API int chewing_handle_Down( Che
 			toSelect = 1;
 
 	if ( toSelect ) {
-		if( ! pgdata->bSelect ) {
+	    if( ! pgdata->bSelect ) {
+			cursor_orig=pgdata->chiSymbolCursor;
 			ChoiceFirstAvail( pgdata );
 		}
 		else {
+			if ( pgdata->config.bPhraseChoiceRearward ){
+				int avail_willbe=(pgdata->availInfo.currentAvail>0)?
+					pgdata->availInfo.currentAvail-1: pgdata->availInfo.nAvail - 1;
+				pgdata->chiSymbolCursor=cursor_orig - pgdata->availInfo.avail[avail_willbe].len;
+				if (chewing_buffer_Len(ctx)>cursor_orig){
+				    pgdata->chiSymbolCursor++;
+				}
+			}
 			ChoiceNextAvail( pgdata );
 		}
-	} 
+	}
 	else if ( pgdata->symbolKeyBuf[ key_buf_cursor ] ) {
 		/* Open Symbol Choice List */
 		if ( ! pgdata->choiceInfo.isSymbol )
@@ -782,11 +810,11 @@ CHEWING_API int chewing_handle_ShiftLeft
 
 	if ( ! ChewingIsEntering( pgdata ) ) {
 		keystrokeRtn = KEYSTROKE_IGNORE;
-	} 
+	}
 	if ( ! pgdata->bSelect ) {
 		/*  PointEnd locates (-9, +9) */
-		if ( 
-			! ZuinIsEntering( &( pgdata->zuinData ) ) && 
+		if (
+			! ZuinIsEntering( &( pgdata->zuinData ) ) &&
 			pgdata->chiSymbolCursor > 0 &&
 			pgdata->PointEnd > -9 ) {
 			if ( pgdata->PointStart == -1 )
@@ -797,7 +825,7 @@ CHEWING_API int chewing_handle_ShiftLeft
 				pgdata->PointEnd--;
 			}
 			if ( pgdata->PointEnd == 0 )
-				pgdata->PointStart = -1; 
+				pgdata->PointStart = -1;
 		}
 	}
 
@@ -822,8 +850,8 @@ CHEWING_API int chewing_handle_Left( Che
 			pgdata->choiceInfo.pageNo = pgdata->choiceInfo.nPage - 1;
 	}
 	else {
-		if ( 
-			! ZuinIsEntering( &( pgdata->zuinData ) ) && 
+		if (
+			! ZuinIsEntering( &( pgdata->zuinData ) ) &&
 			pgdata->chiSymbolCursor > 0 ) {
 			CheckAndResetRange( pgdata );
 			pgdata->chiSymbolCursor--;
@@ -842,13 +870,13 @@ CHEWING_API int chewing_handle_ShiftRigh
 
 	if ( ! ChewingIsEntering( pgdata ) ) {
 		keystrokeRtn = KEYSTROKE_IGNORE;
-	} 
+	}
 
 	if ( ! pgdata->bSelect ) {
 		/* PointEnd locates (-9, +9) */
-		if ( 
-			! ZuinIsEntering( &( pgdata->zuinData ) ) && 
-			pgdata->chiSymbolCursor < pgdata->chiSymbolBufLen && 
+		if (
+			! ZuinIsEntering( &( pgdata->zuinData ) ) &&
+			pgdata->chiSymbolCursor < pgdata->chiSymbolBufLen &&
 			pgdata->PointEnd < 9 ) {
 			if ( pgdata->PointStart == -1 )
 				pgdata->PointStart = pgdata->chiSymbolCursor;
@@ -858,7 +886,7 @@ CHEWING_API int chewing_handle_ShiftRigh
 			}
 			pgdata->chiSymbolCursor++;
 			if ( pgdata->PointEnd == 0 )
-				pgdata->PointStart = -1; 
+				pgdata->PointStart = -1;
 		}
 	}
 
@@ -883,9 +911,9 @@ CHEWING_API int chewing_handle_Right( Ch
 			pgdata->choiceInfo.pageNo = 0;
 	}
 	else {
-		if ( 
-			! ZuinIsEntering( &( pgdata->zuinData ) ) &&			
-			pgdata->chiSymbolCursor < pgdata->chiSymbolBufLen ) {			
+		if (
+			! ZuinIsEntering( &( pgdata->zuinData ) ) &&
+			pgdata->chiSymbolCursor < pgdata->chiSymbolBufLen ) {
 			CheckAndResetRange( pgdata );
 			pgdata->chiSymbolCursor++;
 		}
@@ -974,11 +1002,11 @@ CHEWING_API int chewing_handle_Home( Che
 
 	CheckAndResetRange( pgdata );
 
-	if ( ! ChewingIsEntering( pgdata ) ) { 
+	if ( ! ChewingIsEntering( pgdata ) ) {
 		keystrokeRtn = KEYSTROKE_IGNORE;
-	} 
+	}
 	else if ( ! pgdata->bSelect ) {
-		pgdata->chiSymbolCursor = 0; 
+		pgdata->chiSymbolCursor = 0;
 	}
 	MakeOutputWithRtn( pgo, pgdata, keystrokeRtn );
 	return 0;
@@ -993,12 +1021,12 @@ CHEWING_API int chewing_handle_End( Chew
 	CheckAndResetRange( pgdata );
 
 	if ( ! ChewingIsEntering( pgdata ) ) {
-		keystrokeRtn = KEYSTROKE_IGNORE; 
-	} 
+		keystrokeRtn = KEYSTROKE_IGNORE;
+	}
 	else if ( ! pgdata->bSelect ) {
-		pgdata->chiSymbolCursor = pgdata->chiSymbolBufLen; 
-	} 
-	MakeOutputWithRtn( pgo, pgdata, keystrokeRtn );       
+		pgdata->chiSymbolCursor = pgdata->chiSymbolBufLen;
+	}
+	MakeOutputWithRtn( pgo, pgdata, keystrokeRtn );
 	return 0;
 }
 
@@ -1013,9 +1041,9 @@ CHEWING_API int chewing_handle_PageUp( C
 	if ( ! ChewingIsEntering( pgdata ) ) {
 		keystrokeRtn = KEYSTROKE_IGNORE;
 	}
-	else if ( ! pgdata->bSelect ) { 
+	else if ( ! pgdata->bSelect ) {
 		pgdata->chiSymbolCursor = pgdata->chiSymbolBufLen;
-	} 
+	}
 	MakeOutputWithRtn( pgo, pgdata, keystrokeRtn );
 	return 0;
 }
@@ -1031,9 +1059,9 @@ CHEWING_API int chewing_handle_PageDown(
 	if ( ! ChewingIsEntering( pgdata ) ) {
 		keystrokeRtn = KEYSTROKE_IGNORE;
 	}
-	else if ( ! pgdata->bSelect ) { 
+	else if ( ! pgdata->bSelect ) {
 		pgdata->chiSymbolCursor = pgdata->chiSymbolBufLen;
-	} 
+	}
 	MakeOutputWithRtn( pgo, pgdata, keystrokeRtn );
 	return 0;
 }
@@ -1107,7 +1135,7 @@ CHEWING_API int chewing_handle_Default( 
 			DoSelect( pgdata, num );
 			goto End_keyproc;
 		}
-		
+
 		/* Otherwise, use 'j' and 'k' for paging in selection mode */
 		DEBUG_OUT(
 			"\t\tchecking paging key, got '%c'\n",
@@ -1163,10 +1191,10 @@ CHEWING_API int chewing_handle_Default( 
 			rtn = ZuinPhoInput( &( pgdata->zuinData ), key );
 			DEBUG_OUT(
 				"\t\tChinese mode key, "
-				"ZuinPhoInput return value = %d\n", 
+				"ZuinPhoInput return value = %d\n",
 				rtn );
 			DEBUG_FLUSH;
-			
+
 			if ( rtn == ZUIN_KEY_ERROR )
 				rtn = SpecialSymbolInput( key, pgdata );
 			switch ( rtn ) {
@@ -1182,14 +1210,14 @@ CHEWING_API int chewing_handle_Default( 
 				case ZUIN_KEY_ERROR:
 				case ZUIN_IGNORE:
 					DEBUG_OUT(
-						"\t\tbefore isupper(key),key=%d\n", 
+						"\t\tbefore isupper(key),key=%d\n",
 						key );
 					/* change upper case into lower case */
-					if ( isupper( key ) ) 
+					if ( isupper( key ) )
 						key = tolower( key );
 
 					DEBUG_OUT(
-						"\t\tafter isupper(key),key=%d\n", 
+						"\t\tafter isupper(key),key=%d\n",
 						key );
 
 					/* see if buffer contains nothing */
@@ -1207,7 +1235,7 @@ CHEWING_API int chewing_handle_Default( 
 					if ( rtn == SYMBOL_KEY_ERROR ) {
 						keystrokeRtn = KEYSTROKE_IGNORE;
 						/*
-						 * If the key is not a printable symbol, 
+						 * If the key is not a printable symbol,
 						 * then it's wrong to commit it.
 						 */
 						bQuickCommit = 0;
@@ -1248,9 +1276,9 @@ End_keyproc:
 	/* Quick commit */
 	else {
 		DEBUG_OUT(
-				"\t\tQuick commit buf[0]=%c\n", 
+				"\t\tQuick commit buf[0]=%c\n",
 				pgdata->chiSymbolBuf[ 0 ].s[ 0 ] );
-		pgo->commitStr[ 0 ] = pgdata->chiSymbolBuf[ 0 ]; 
+		pgo->commitStr[ 0 ] = pgdata->chiSymbolBuf[ 0 ];
 		pgo->nCommitStr = 1;
 		pgdata->chiSymbolBufLen = 0;
 		pgdata->chiSymbolCursor = 0;
@@ -1309,12 +1337,12 @@ CHEWING_API int chewing_handle_CtrlNum( 
 
 	cursor = PhoneSeqCursor( pgdata );
 	if ( ! pgdata->config.bAddPhraseForward ) {
-		if ( 
-			newPhraseLen >= 1 && 
+		if (
+			newPhraseLen >= 1 &&
 			cursor + newPhraseLen - 1 <= pgdata->nPhoneSeq ) {
-			if ( NoSymbolBetween( 
-				pgdata, 
-				cursor, 
+			if ( NoSymbolBetween(
+				pgdata,
+				cursor,
 				cursor + newPhraseLen - 1 ) ) {
 				/* Manually add phrase to the user phrase database. */
 				memcpy( addPhoneSeq,
@@ -1328,10 +1356,10 @@ CHEWING_API int chewing_handle_CtrlNum( 
 
 
 				phraseState = UserUpdatePhrase( addPhoneSeq, addWordSeq );
-				SetUpdatePhraseMsg( 
-					pgdata, 
-					addWordSeq, 
-					newPhraseLen, 
+				SetUpdatePhraseMsg(
+					pgdata,
+					addWordSeq,
+					newPhraseLen,
 					phraseState );
 
 				/* Clear the breakpoint between the New Phrase */
@@ -1341,11 +1369,11 @@ CHEWING_API int chewing_handle_CtrlNum( 
 		}
 	}
 	else {
-		if ( 
-			newPhraseLen >= 1 && 
+		if (
+			newPhraseLen >= 1 &&
 			cursor - newPhraseLen >= 0 ) {
-			if ( NoSymbolBetween( pgdata, 
-			                      cursor, 
+			if ( NoSymbolBetween( pgdata,
+			                      cursor,
 			                      cursor - newPhraseLen ) ) {
 				/* Manually add phrase to the user phrase database. */
 				memcpy( addPhoneSeq,
@@ -1358,10 +1386,10 @@ CHEWING_API int chewing_handle_CtrlNum( 
 				           newPhraseLen, 1);
 
 				phraseState = UserUpdatePhrase( addPhoneSeq, addWordSeq );
-				SetUpdatePhraseMsg( 
-					pgdata, 
-					addWordSeq, 
-					newPhraseLen, 
+				SetUpdatePhraseMsg(
+					pgdata,
+					addWordSeq,
+					newPhraseLen,
 					phraseState );
 
 				/* Clear the breakpoint between the New Phrase */
@@ -1414,10 +1442,10 @@ CHEWING_API int chewing_handle_Numlock( 
 	ChewingOutput *pgo = ctx->output;
 	int rtn, QuickCommit = 0;
 	int keystrokeRtn = KEYSTROKE_ABSORB;
-	
+
 	if ( ! pgdata->bSelect ) {
 		/* If we're not selecting words, we should send out numeric
-		 * characters at once. 
+		 * characters at once.
 		 */
 		if ( pgdata->chiSymbolBufLen == 0 ) {
 			QuickCommit = 1;
@@ -1428,7 +1456,7 @@ CHEWING_API int chewing_handle_Numlock( 
 			keystrokeRtn = KEYSTROKE_IGNORE ;
 		}
 		else if ( QuickCommit ) {
-			pgo->commitStr[ 0 ] = pgdata->chiSymbolBuf[ 0 ]; 
+			pgo->commitStr[ 0 ] = pgdata->chiSymbolBuf[ 0 ];
 			pgo->nCommitStr = 1;
 			pgdata->chiSymbolBufLen = 0;
 			pgdata->chiSymbolCursor = 0;
@@ -1443,7 +1471,7 @@ CHEWING_API int chewing_handle_Numlock( 
 	else {
 		/* Otherwise, if we are selecting words, we use numeric keys
 		 * as selkey
-		 * and submit the words. 
+		 * and submit the words.
 		 */
 		int num = -1;
 		if ( key > '0' && key < '9' )
diff -up ./src/choice.c.phraseChoiceRearward ./src/choice.c
--- ./src/choice.c.phraseChoiceRearward	2008-12-02 00:29:20.000000000 +1000
+++ ./src/choice.c	2009-08-03 14:35:28.000000000 +1000
@@ -71,22 +71,44 @@ static void ChangeSelectIntervalAndBreak
 }
 
 /** @brief Loading all possible phrases after the cursor from long to short into AvailInfo structure.*/
-static void SetAvailInfo( 
-		AvailInfo *pai, const uint16 phoneSeq[], 
-		int nPhoneSeq, int begin, const int bSymbolArrBrkpt[] )
+static void SetAvailInfo(
+		AvailInfo *pai, const uint16 phoneSeq[],
+		int nPhoneSeq, int begin, const int bSymbolArrBrkpt[],
+		ChewingData *pgdata,int end)
 {
-	int end, pho_id;
+	int pho_id;
 	int diff;
 	uint16 userPhoneSeq[ MAX_PHONE_SEQ_LEN ];
 
 	pai->nAvail = 0;
 
-	for ( end = begin; end < nPhoneSeq; end++ ) {
-		diff = end - begin;
-		if ( diff > 0 && bSymbolArrBrkpt[ end ] ) 
-			break;
+	int i,head,head_tmp;
+	if ( pgdata->config.bPhraseChoiceRearward ){
+	        for (i=end;i>=begin;i--){
+			head=i;
+			if(bSymbolArrBrkpt[i])
+				break;
+		}
+		head_tmp=end;
+	}else{
+		head_tmp=head=begin;
+	}
 
-		pho_id = TreeFindPhrase( begin, end, phoneSeq );
+	int tail,tail_tmp;
+	if ( pgdata->config.bPhraseChoiceRearward ){
+		tail_tmp=tail=end;
+	}else{
+		for (i=begin;i<nPhoneSeq;i++){
+			if(bSymbolArrBrkpt[i])
+				break;
+			tail=i;
+		}
+		tail_tmp=begin;
+	}
+
+	while(head<=head_tmp && tail_tmp<=tail){
+		diff = tail_tmp - head_tmp;
+		pho_id = TreeFindPhrase( head_tmp, tail_tmp, phoneSeq );
 		if ( pho_id != -1 ) {
 			/* save it! */
 			pai->avail[ pai->nAvail ].len = diff + 1;
@@ -95,8 +117,8 @@ static void SetAvailInfo( 
 		}
 		else {
 			memcpy(
-				userPhoneSeq, 
-				&phoneSeq[ begin ], 
+				userPhoneSeq,
+				&phoneSeq[ head_tmp ],
 				sizeof( uint16 ) * ( diff + 1 ) ) ;
 			userPhoneSeq[ diff + 1 ] = 0;
 			if ( UserGetPhraseFirst( userPhoneSeq ) ) {
@@ -109,6 +131,12 @@ static void SetAvailInfo( 
 				pai->avail[ pai->nAvail ].id = -1;
 			}
 		}
+
+		if ( pgdata->config.bPhraseChoiceRearward ){
+			head_tmp--;
+		}else{
+			tail_tmp++;
+		}
 	}
 }
 
@@ -118,7 +146,7 @@ static int ChoiceTheSame( ChoiceInfo *pc
 	int i;
 
 	for ( i = 0; i < pci->nTotalChoice; i++ )
-		if ( ! memcmp( pci->totalChoiceStr[ i ], str, len ) ) 
+		if ( ! memcmp( pci->totalChoiceStr[ i ], str, len ) )
 			return 1;
 	return 0;
 }
@@ -133,12 +161,12 @@ static void SetChoiceInfo(
 		ChoiceInfo *pci,AvailInfo *pai, uint16 *phoneSeq, int cursor,
 		int candPerPage )
 {
-	Word tempWord;
+        Word tempWord;
 	Phrase tempPhrase;
 	int len;
 	UserPhraseData *pUserPhraseData;
 	uint16 userPhoneSeq[ MAX_PHONE_SEQ_LEN ];
-	
+
 	/* Clears previous candidates. */
 	memset( pci->totalChoiceStr, '\0', sizeof(char) * MAX_CHOICE * MAX_PHRASE_LEN * MAX_UTF8_SIZE + 1);
 
@@ -150,9 +178,9 @@ static void SetChoiceInfo(
 	if ( len == 1 ) { /* single character */
 		GetCharFirst( &tempWord, phoneSeq[ cursor ] );
 		do {
-			if ( ChoiceTheSame( pci, tempWord.word, ueBytesFromChar( tempWord.word[0] ) * sizeof( char ) ) ) 
+			if ( ChoiceTheSame( pci, tempWord.word, ueBytesFromChar( tempWord.word[0] ) * sizeof( char ) ) )
 				continue;
-			memcpy( 
+			memcpy(
 				pci->totalChoiceStr[ pci->nTotalChoice ],
 				tempWord.word, ueBytesFromChar( tempWord.word[0] ) * sizeof( char ) );
 			assert(pci->nTotalChoice <= MAX_CHOICE);
@@ -165,9 +193,9 @@ static void SetChoiceInfo(
 		if ( pai->avail[ pai->currentAvail ].id != -1 ) {
 			GetPhraseFirst( &tempPhrase, pai->avail[ pai->currentAvail ].id );
 			do {
-				if ( ChoiceTheSame( 
-					pci, 
-					tempPhrase.phrase, 
+				if ( ChoiceTheSame(
+					pci,
+					tempPhrase.phrase,
 					len * ueBytesFromChar( tempPhrase.phrase[0] ) * sizeof( char ) ) ) {
 					continue;
 				}
@@ -183,9 +211,9 @@ static void SetChoiceInfo(
 		if ( pUserPhraseData ) {
 			do {
 				/* check if the phrase is already in the choice list */
-				if ( ChoiceTheSame( 
-					pci, 
-					pUserPhraseData->wordSeq, 
+				if ( ChoiceTheSame(
+					pci,
+					pUserPhraseData->wordSeq,
 					len * ueBytesFromChar( pUserPhraseData->wordSeq[0] ) * sizeof( char ) ) )
 					continue;
 				/* otherwise store it */
@@ -194,7 +222,7 @@ static void SetChoiceInfo(
 						pUserPhraseData->wordSeq,
 						len, 1);
 				pci->nTotalChoice++;
-			} while( ( pUserPhraseData = 
+			} while( ( pUserPhraseData =
 				UserGetPhraseNext( userPhoneSeq ) ) != NULL );
 		}
 
@@ -215,7 +243,9 @@ int ChoiceFirstAvail( ChewingData *pgdat
 	pgdata->choiceInfo.oldChiSymbolCursor = pgdata->chiSymbolCursor;
 
 	/* see if there is some word in the cursor position */
+	int end=pgdata->chiSymbolCursor;
 	if ( pgdata->chiSymbolBufLen == pgdata->chiSymbolCursor ) {
+		end--;
 		if ( pgdata->config.bPhraseChoiceRearward )
 			pgdata->chiSymbolCursor = pgdata->preferInterval[ pgdata->nPrefer - 1 ].from + CountSymbols( pgdata, pgdata->chiSymbolBufLen );
 		else
@@ -224,22 +254,23 @@ int ChoiceFirstAvail( ChewingData *pgdat
 
 	pgdata->bSelect = 1;
 
-	SetAvailInfo( 
-		&( pgdata->availInfo ), 
-		pgdata->phoneSeq, 
+	SetAvailInfo(
+		&( pgdata->availInfo ),
+		pgdata->phoneSeq,
 		pgdata->nPhoneSeq,
 		PhoneSeqCursor( pgdata ),
-		pgdata->bSymbolArrBrkpt );
+		pgdata->bSymbolArrBrkpt,
+		pgdata,end);
 
 	if ( ! pgdata->availInfo.nAvail )
 		return ChoiceEndChoice( pgdata );
 
 	pgdata->availInfo.currentAvail = pgdata->availInfo.nAvail - 1;
 	SetChoiceInfo(
-		&( pgdata->choiceInfo ), 
-		&( pgdata->availInfo ), 
-		pgdata->phoneSeq, 
-		PhoneSeqCursor( pgdata ), 
+		&( pgdata->choiceInfo ),
+		&( pgdata->availInfo ),
+		pgdata->phoneSeq,
+		PhoneSeqCursor( pgdata ),
 		pgdata->config.candPerPage );
 	return 0;
 }
@@ -249,24 +280,24 @@ int ChoicePrevAvail( ChewingData *pgdata
 	if (pgdata->choiceInfo.isSymbol) return 0;
 	if ( ++( pgdata->availInfo.currentAvail ) >= pgdata->availInfo.nAvail )
 		pgdata->availInfo.currentAvail = 0;
-	SetChoiceInfo( 
-		&( pgdata->choiceInfo ), 
-		&( pgdata->availInfo ), 
-		pgdata->phoneSeq, 
+	SetChoiceInfo(
+		&( pgdata->choiceInfo ),
+		&( pgdata->availInfo ),
+		pgdata->phoneSeq,
 		PhoneSeqCursor( pgdata ),
 		pgdata->config.candPerPage );
 	return 0;
 }
 
 /** @brief Return the next phrase not longer than the previous phrase. */
-int ChoiceNextAvail( ChewingData *pgdata ) 
+int ChoiceNextAvail( ChewingData *pgdata )
 {
 	if (pgdata->choiceInfo.isSymbol) return 0;
 	if ( --( pgdata->availInfo.currentAvail ) < 0 )
 		pgdata->availInfo.currentAvail = pgdata->availInfo.nAvail - 1;
 	SetChoiceInfo(
-		&( pgdata->choiceInfo ), 
-		&( pgdata->availInfo ), 
+		&( pgdata->choiceInfo ),
+		&( pgdata->availInfo ),
 		pgdata->phoneSeq,
 		PhoneSeqCursor( pgdata ),
 		pgdata->config.candPerPage );
@@ -292,17 +323,17 @@ static void ChangeUserData( ChewingData 
 	uint16 userPhoneSeq[ MAX_PHONE_SEQ_LEN ];
 	int len;
 
-	len = ueStrLen( pgdata->choiceInfo.totalChoiceStr[ selectNo ] ); 
+	len = ueStrLen( pgdata->choiceInfo.totalChoiceStr[ selectNo ] );
 	memcpy(
-		userPhoneSeq, 
-		&( pgdata->phoneSeq[ PhoneSeqCursor( pgdata ) ] ), 
+		userPhoneSeq,
+		&( pgdata->phoneSeq[ PhoneSeqCursor( pgdata ) ] ),
 		len * sizeof( uint16 ) );
 	userPhoneSeq[ len ] = 0;
 	UserUpdatePhrase( userPhoneSeq, pgdata->choiceInfo.totalChoiceStr[ selectNo ] );
 }
 
 /** @brief commit the selected phrase. */
-int ChoiceSelect( ChewingData *pgdata, int selectNo ) 
+int ChoiceSelect( ChewingData *pgdata, int selectNo )
 {
 	ChoiceInfo *pci = &( pgdata->choiceInfo );
 	AvailInfo *pai = &( pgdata->availInfo );