Index: include/chewingio.h
===================================================================
--- include/chewingio.h	(revision 806)
+++ include/chewingio.h	(working copy)
@@ -46,6 +46,7 @@
 CHEWING_API int chewing_handle_ShiftSpace( ChewingContext * );
 CHEWING_API int chewing_handle_DblTab( ChewingContext * );
 CHEWING_API int chewing_handle_Numlock( ChewingContext *, int key);
+CHEWING_API int chewing_handle_CtrlOption( ChewingContext *ctx, int key );
 
 /**
  * @brief Set selectAreaLen, maxChiSymbolLen, selKey in pcd
Index: src/chewingio.c
===================================================================
--- src/chewingio.c	(revision 806)
+++ src/chewingio.c	(working copy)
@@ -453,15 +453,17 @@
 		keystrokeRtn = KEYSTROKE_IGNORE;
 	}
 	else if ( pgdata->bSelect ) {
-		if ( pgdata->choiceInfo.isSymbol != 0 ) {
-			/* TODO: this should be checked again. */
+		if (pgdata->choiceInfo.isSymbol==0)
+		  ;
+		else {
 			ChewingKillChar(
 				pgdata, 
 				pgdata->cursor - 1, 
 				pgdata->chiSymbolCursor - 1,
-				DECREASE_CURSOR );
+				DECREASE_CURSOR );		
 		}
-		ChoiceEndChoice( pgdata );
+		
+        ChoiceEndChoice( pgdata );
 	}
 	else if ( ZuinIsEntering( &( pgdata->zuinData ) ) ) {
 		ZuinRemoveAll( &( pgdata->zuinData ) );
@@ -1059,6 +1061,9 @@
 					&( pgdata->availInfo ),
 					pgdata->phoneSeq,
 					pgdata->config.candPerPage );
+					
+                PrepareHaninSymbolInputBuffer(pgdata, key);
+
 				goto End_Paging;
 			}
 
@@ -1204,6 +1209,8 @@
 				&( pgdata->availInfo ),
 				pgdata->phoneSeq,
 				pgdata->config.candPerPage );
+
+        PrepareHaninSymbolInputBuffer(pgdata, key);
 		goto make_output;
 	}
 
@@ -1276,7 +1283,6 @@
 	return 0;
 }
 
-#if 0
 CHEWING_API int chewing_handle_CtrlOption( ChewingContext *ctx, int key )
 {
 	ChewingData *pgdata = ctx->data;
@@ -1292,7 +1298,6 @@
 	MakeOutputWithRtn( pgo, pgdata, keystrokeRtn );
 	return 0;
 }
-#endif
 
 CHEWING_API int chewing_handle_ShiftSpace( ChewingContext *ctx )
 {
Index: src/chewingutil.c
===================================================================
--- src/chewingutil.c	(revision 806)
+++ src/chewingutil.c	(working copy)
@@ -172,6 +172,7 @@
 			sizeof( wch_t ) * ( pgdata->chiSymbolBufLen - pgdata->chiSymbolCursor ) );
 
 		pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ].wch = (wchar_t) 0;
+		
 		ueStrNCpy( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ].s,
 				chibuf, 1, 1);
 		/* Save Symbol Key */
@@ -283,7 +284,6 @@
 	return (rtn == ZUIN_IGNORE ? SYMBOL_KEY_ERROR : SYMBOL_KEY_OK);
 }
 
-#if 0
 int SpecialEtenSymbolInput( int key, ChewingData *pgdata )
 {
 	static char keybuf[] = {
@@ -300,7 +300,6 @@
 	static int nSpecial = 31;
 	return InternalSpecialSymbol( key, pgdata, nSpecial, keybuf, chibuf );
 }
-#endif
 
 int SymbolChoice( ChewingData *pgdata, int sel_i )
 {
@@ -344,10 +343,17 @@
 	else { /* level 2 symbol or OpenSymbolChoice */
 		/* TODO: FIXME, this part is buggy! */
 		if ( symbol_type == 2 ) {
-			memmove(
-				&( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor + 1 ] ),
-				&( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ] ),
-				sizeof( wch_t ) * ( pgdata->chiSymbolBufLen - pgdata->chiSymbolCursor ) );
+		  
+		  #ifdef OSX_STYLE_HANIN_SYMBOL_INPUT
+              // we already stuffed one char here, so we back one char
+              pgdata->chiSymbolCursor--;
+              pgdata->chiSymbolBufLen--;
+          #endif		  
+		
+          memmove(
+                &( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor + 1 ] ),
+                &( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ] ),
+                sizeof( wch_t ) * ( pgdata->chiSymbolBufLen - pgdata->chiSymbolCursor ) );
 		}
 		pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ].wch = (wchar_t) 0 ;
 		ueStrNCpy( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ].s,
@@ -355,7 +361,8 @@
 
 		/* This is very strange */
 		key = FindSymbolKey( pgdata->choiceInfo.totalChoiceStr[ sel_i ] );
-		pgdata->symbolKeyBuf[ pgdata->chiSymbolCursor ] = key ? key : '1';
+//		pgdata->symbolKeyBuf[ pgdata->chiSymbolCursor ] = key ? key : '1';
+		pgdata->symbolKeyBuf[ pgdata->chiSymbolCursor ] = key ? key : 0;
 
 		pgdata->bUserArrCnnct[ pgdata->cursor ] = 0;
 		ChoiceEndChoice(pgdata);
@@ -1006,7 +1013,7 @@
 	return 0;
 }
 
-static char *symbol_buf[][ 50 ] = {
+static char *symbol_buf[][50] = {
 	{ "0", "ø", 0 },
 	{ "[", "「", "『", "《", "〈", "【", "〔", 0 },
 	{ "]", "」", "』", "》", "〉", "】", "〕", 0 },
@@ -1025,8 +1032,7 @@
 	{ "*", "＊", "Ⅷ", "×", "※", "╳", "﹡", "☯", "☆", "★", 0 },
 	{ "(", "（", "Ⅸ", 0 },
 	{ ")", "）", "Ⅹ", 0 },
-	{ "_", "＿", "…", "‥", "←", "→", "﹍", "﹉", "ˍ", "￣", 
-	       "–", "—", "¯", "﹊", "﹎", "﹏", "﹣", "－", 0 },
+	{ "_", "＿", "…", "‥", "←", "→", "﹍", "﹉", "ˍ", "￣",  "–", "—", "¯", "﹊", "﹎", "﹏", "﹣", "－", 0 },
 	{ "+", "＋", "±", "﹢", 0 },
 	{ "=", "＝", "≒", "≠", "≡", "≦", "≧", "﹦", 0 },
 	{ "`", "』", "『", "′", "‵", 0 },
@@ -1035,14 +1041,12 @@
 	{ "\"", "；", 0 },
 	{ "\'", "、", "…", "‥", 0 },
 	{ "\\", "＼", "↖", "↘", "﹨", 0 },
-	{ "-", "－", "＿", "￣", "¯", "ˍ", "–", "—", "‥", "…",
-	       "←", "→", "╴", "﹉", "﹊", "﹍", "﹎", "﹏", "﹣", 0 },
+	{ "-", "－", "＿", "￣", "¯", "ˍ", "–", "—", "‥", "…", "←", "→", "╴", "﹉", "﹊", "﹍", "﹎", "﹏", "﹣", 0 },
 	{ "/", "／","÷","↗","↙","∕", 0 },
 	{ "|", "↑", "↓", "∣", "∥", "︱", "︳", "︴" ,0 },
 	{ "A", "Å","Α", "α", "├", "╠", "╟", "╞", 0 },
 	{ "B", "Β", "β","∵", 0 },
-	{ "C", "Χ", "χ", "┘", "╯", "╝", "╜", "╛",
-	       "㏄", "℃", "㎝", "♣", "©", 0 },
+	{ "C", "Χ", "χ", "┘", "╯", "╝", "╜", "╛", "㏄", "℃", "㎝", "♣", "©", 0 },
 	{ "D", "Δ", "δ", "◇", "◆", "┤", "╣", "╢", "╡","♦", 0 },
 	{ "E", "Ε", "ε", "┐", "╮", "╗", "╓", "╕", 0 },
 	{ "F", "Φ", "ψ", "│", "║", "♀", 0 },
@@ -1058,8 +1062,7 @@
 	{ "P", "Π", "π", 0 },
 	{ "Q", "Θ", "θ","Д","┌", "╭", "╔", "╓", "╒", 0 },
 	{ "R", "Ρ", "ρ", "─", "═" ,"®" , 0 },
-	{ "S", "Σ", "σ", "∴", "□", "■", "┼", "╬", "╪", "╫",
-	       "∫", "§", "♠", 0 },
+	{ "S", "Σ", "σ", "∴", "□", "■", "┼", "╬", "╪", "╫", "∫", "§", "♠", 0 },
 	{ "T", "Τ", "τ","θ","△","▲","▽","▼","™","⊿", "™", 0 },
 	{ "U", "Υ", "υ","μ","∪", "∩", 0 },
 	{ "V",  0 },
@@ -1073,7 +1076,7 @@
 {
 	int i;
 	char **buf;
-	for ( i = 0; i < sizeof( symbol_buf ) / sizeof( symbol_buf[ 0 ] ); ++i ) {
+	for ( i = 0; i < sizeof( symbol_buf ) / sizeof( symbol_buf[ 0 ] ) ; ++i ) {
 		for ( buf = symbol_buf[ i ]; *buf; ++buf )	{
 			if (  0 == strcmp( *buf, symbol ) )
 				return *symbol_buf[ i ][ 0 ];
@@ -1085,6 +1088,7 @@
 int OpenSymbolChoice( ChewingData *pgdata )
 {
 	int i, symbol_buf_len = sizeof( symbol_buf ) / sizeof( symbol_buf[ 0 ] );
+	
 	char **pBuf;
 	ChoiceInfo *pci = &( pgdata->choiceInfo );
 	pci->oldCursor = pgdata->cursor;
@@ -1099,6 +1103,7 @@
 				pgdata->phoneSeq, pgdata->config.candPerPage );
 		return 0;
 	}
+	
 	for ( i = 0; i < symbol_buf_len; i++ ) {
 		if ( symbol_buf[ i ][ 0 ][ 0 ] == 
 				pgdata->symbolKeyBuf[ pgdata->chiSymbolCursor ] ) {
@@ -1106,10 +1111,12 @@
 			break;
 		}
 	}
+	
 	if ( i == symbol_buf_len ) {
 		ChoiceEndChoice( pgdata );
 		return 0;
 	}
+	
 	pci->nTotalChoice = 0;
 	for ( i = 1; pBuf[ i ]; i++ ) {
 		ueStrNCpy( pci->totalChoiceStr[ pci->nTotalChoice ], 
@@ -1277,3 +1284,26 @@
 	}
 }
 
+void PrepareHaninSymbolInputBuffer(ChewingData *pgdata, int key)
+{
+    #ifdef OSX_STYLE_HANIN_SYMBOL_INPUT
+		ueStrNCpy( pgdata->chiSymbolBuf[ pgdata->chiSymbolCursor ].s, "符", 1, 1);
+    #endif
+    
+    // Save the symbol key
+    memmove(&(pgdata->symbolKeyBuf[ pgdata->chiSymbolCursor + 1 ]), &(pgdata->symbolKeyBuf[pgdata->chiSymbolCursor]), sizeof(pgdata->symbolKeyBuf[0]) * (pgdata->chiSymbolBufLen - pgdata->chiSymbolCursor));
+    pgdata->symbolKeyBuf[ pgdata->chiSymbolCursor ] = key;
+    
+    #ifdef OSX_STYLE_HANIN_SYMBOL_INPUT
+        pgdata->chiSymbolCursor++;
+        pgdata->chiSymbolBufLen++;
+    #endif
+		
+    pgdata->bUserArrCnnct[ pgdata->cursor ] = 0;
+    
+    // reset Zuin data, and put back kbtype
+    int kbtype = pgdata->zuinData.kbtype;
+    memset(&(pgdata->zuinData), 0, sizeof(ZuinData));
+    pgdata->zuinData.kbtype = kbtype;	
+
+}
Index: src/hash.c
===================================================================
--- src/hash.c	(revision 806)
+++ src/hash.c	(working copy)
@@ -115,32 +115,14 @@
 	return pItem;
 }
 
-static void HashItem2String( char *str, HASH_ITEM *pItem )
-{
-	int i, len;
-	char buf[ FIELD_SIZE ];
-
-	sprintf( str, "%s ", pItem->data.wordSeq );
-	len = ueStrLen( pItem->data.wordSeq );
-	for ( i = 0; i < len; i++ ) {
-		sprintf( buf, "%hu ", pItem->data.phoneSeq[ i ] );
-		strcat( str, buf );
-	}
-	sprintf(
-		buf, "%d %d %d %d",
-		pItem->data.userfreq, pItem->data.recentTime,
-		pItem->data.maxfreq, pItem->data.origfreq );
-	strcat( str, buf );
-}
-
 /* 
  * capacity of 'str' MUST bigger then FIELD_SIZE !
  */
-static void HashItem2Binary( char *str, HASH_ITEM *pItem )
+void HashItem2Binary( char *str, HASH_ITEM *pItem )
 {
 	int i, phraselen;
 	uint16 *pshort;
-	unsigned char buf[ FIELD_SIZE ], *puc;
+	unsigned char *puc;
 
 	memset(str, 0, FIELD_SIZE);
 	if ( sizeof(int) * 4 + ueStrLen( pItem->data.wordSeq ) * 2 +
@@ -167,7 +149,7 @@
 	/* phrase */
 	puc = (unsigned char *) pshort;
 	*puc = strlen( pItem->data.wordSeq );
-	strcpy( (char *) (puc + 1), pItem->data.wordSeq );
+	strcpy(puc+1, pItem->data.wordSeq);
 	pItem->data.wordSeq[ (int) *puc ] = '\0';
 }
 
@@ -181,13 +163,10 @@
 	/* update "lifetime" */
 	fseek( outfile, strlen( BIN_HASH_SIG ), SEEK_SET );
 	fwrite( &chewing_lifetime, 1, 4, outfile );
-#ifdef ENABLE_DEBUG
-	sprintf( str, "%d", chewing_lifetime );
 	DEBUG_OUT( 
 		"HashModify-1: formatstring='%s',printing '%s'\n", 
 		formatstring, str );
 	DEBUG_FLUSH;
-#endif
 
 	/* update record */
 	if ( pItem->item_index < 0 ) {
@@ -200,13 +179,7 @@
 			pItem->item_index * FIELD_SIZE + 4 + strlen( BIN_HASH_SIG ),
 			SEEK_SET );
 	}
-#ifdef ENABLE_DEBUG
-	HashItem2String( str, pItem );
-	DEBUG_OUT( 
-		"HashModify-2: formatstring='%s',printing '%s'\n",
-		formatstring, str );
-	DEBUG_FLUSH;
-#endif
+	/*HashItem2String( str, pItem );*/
 	HashItem2Binary( str, pItem );
 	fwrite( str, 1, FIELD_SIZE, outfile );
 	fflush( outfile );
@@ -215,8 +188,8 @@
 
 static int isValidChineseString( char *str )
 {
-	if ( strlen( str ) == 0 ) {
-		return  0;
+	if ( str==NULL || *str=='\0' ) {
+		return	0;
 	}
 	while ( *str != '\0' )  {
 		int len = ueBytesFromChar( (unsigned char) *str );
@@ -236,10 +209,9 @@
  */
 int ReadHashItem_bin( const char *srcbuf, HASH_ITEM *pItem, int item_index )
 {
-	int len, i, word_len, ptr;
+	int len, i;
 	uint16 *pshort;
-	char wordbuf[ 64 ];
-	unsigned char recbuf[ FIELD_SIZE ], *puc;
+	unsigned char recbuf[FIELD_SIZE], *puc;
 
 	memcpy( recbuf, srcbuf, FIELD_SIZE );
 	memset( pItem, 0, sizeof(HASH_ITEM) );
@@ -263,9 +235,8 @@
 	/* phrase, length in num of bytes */
 	puc = (unsigned char *) pshort;
 	pItem->data.wordSeq = ALC( char, (*puc) + 1 );
-	strcpy( pItem->data.wordSeq, (char *) (puc + 1) );
-	pItem->data.wordSeq[ (int) *puc ] = '\0';
-
+	strcpy(pItem->data.wordSeq, puc+1);
+	pItem->data.wordSeq[(int)*puc] = '\0';
 	/* Invalid UTF-8 Chinese characters found */
 	if ( ! isValidChineseString( pItem->data.wordSeq ) ) {
 		goto ignore_corrupted_record;
@@ -349,7 +320,7 @@
 	return tf;
 }
 
-static char *_load_hash_file( const char *filename, int *size )
+char *_load_hash_file( const char *filename, int *size )
 {
 	int flen;
 	char *pd = NULL;
@@ -383,8 +354,8 @@
 {
 	FILE *txtfile;
 	char oldname[ 256 ], *dump, *seekdump;
-	HASH_ITEM item, *pItem;
-	int item_index, hashvalue, iret, tflen;
+	HASH_ITEM item;
+	int item_index, iret, tflen;
 
 	/* allocate dump buffer */
 	txtfile = open_file_get_length( ofilename, "r", &tflen );
@@ -426,68 +397,28 @@
 	fclose( txtfile );
 
 	/* backup as *.old */
-	strncpy( oldname, ofilename, sizeof(oldname) );
-	strncat( oldname, ".old", sizeof(oldname) );
-	oldname[ sizeof(oldname) - 1 ] = '\0';
+	strncpy(oldname, ofilename, sizeof(oldname));
+	strncat(oldname, ".old", sizeof(oldname));
+	oldname[sizeof(oldname)-1] = '\0';
 	PLAT_UNLINK( oldname );
 	PLAT_RENAME( ofilename, oldname );
 
 	/* dump new file */
 	PLAT_UNLINK( ofilename );
-	txtfile = fopen( ofilename, "w+b" );
-	fwrite( dump, seekdump - dump, 1, txtfile );
-	fflush( txtfile );
-	fclose( txtfile );
-	free( dump );
+	txtfile = fopen(ofilename, "w+b");
+	fwrite(dump, seekdump-dump, 1, txtfile);
+	fflush(txtfile);
+	fclose(txtfile);
+	free(dump);
 
 	return  1;
 }
 
-#if 0
-/**
- * Attempt to re-compute lifetime
- */
-static int ComputeChewingLifeTime()
-{
-       HASH_ITEM *item;
-       int i, min;
-       
-       i = 0;
-
-       chewing_lifetime++;
-       min = chewing_lifetime;
-
-       while ( hashtable[ i ] ) {
-               item = hashtable[ i ];
-               while ( item ) {
-                       if ( item->data.recentTime < min )
-                               min = item->data.recentTime;
-                       item = item->next;
-               }
-               i++;
-       }
-
-       chewing_lifetime -= min;
-       i = 0;
-
-       while ( hashtable[ i ] ) {
-               item = hashtable[ i ];
-               while ( item ) {
-                       item->data.recentTime -= min;
-                       HashModify( item );
-                       item = item->next;
-               }
-               i++;
-       }
-       return 0;
-}
-#endif
-
 int ReadHash( const char *path )
 {
 	HASH_ITEM item, *pItem, *pPool = NULL;
-	int item_index, hashvalue, iret, fsize, hdrlen, oldest = INT_MAX;
-	char *dump, *seekdump;
+	int item_index, hashvalue, iret, fsize, hdrlen, oldest=INT_MAX;
+	char	*dump, *seekdump;
 
 	/* make sure of write permission */
 	if ( access( path, W_OK ) != 0 ) {
@@ -499,7 +430,11 @@
 		else {
 			sprintf(
 				hashfilename, "%s%s",
-				PLAT_TMPDIR, CHEWING_HASH_PATH );
+#ifndef WIN32
+				"/tmp", CHEWING_HASH_PATH );
+#else
+				"C:\\Windows\\TEM\\", CHEWING_HASH_PATH );
+#endif
 		}
 		PLAT_MKDIR( hashfilename );
 		strcat( hashfilename, PLAT_SEPARATOR );
@@ -529,12 +464,11 @@
 		fclose( outfile );
 	}
 	else {
-		char header[ 5 ];
-		if ( memcmp(dump, BIN_HASH_SIG, strlen(BIN_HASH_SIG)) != 0 ) {
-			/* perform migrate from text-based to binary form */
-			free( dump );
-			if ( ! migrate_hash_to_bin( hashfilename ) ) {
-				return  0;
+		if ( memcmp(dump, BIN_HASH_SIG, strlen(BIN_HASH_SIG))!=0 ) {
+			//  migrate it
+			free(dump);
+			if ( !migrate_hash_to_bin(hashfilename) ) {
+				return	0;
 			}
 			goto open_hash_file;
 		}
@@ -574,6 +508,8 @@
 
 			hashvalue = HashFunc( pItem->data.phoneSeq );
 			pItem->next = hashtable[ hashvalue ];
+			hashtable[ hashvalue ] = pItem;
+
 			pItem->data.recentTime -= oldest;
 		}
 		chewing_lifetime -= oldest;
Index: src/chewingutil.h
===================================================================
--- src/chewingutil.h	(revision 806)
+++ src/chewingutil.h	(working copy)
@@ -26,6 +26,7 @@
 int ChewingIsEntering( ChewingData *pgdata );
 void CleanAllBuf( ChewingData * );
 int SemiSymbolInput(int key, ChewingData *pgdata);
+int SpecialEtenSymbolInput( int key, ChewingData *pgdata );
 int SpecialSymbolInput( int key, ChewingData *pgdata );
 int FullShapeSymbolInput( int key, ChewingData *pgdata );
 int EasySymbolInput( int key, ChewingData *pgdata, ChewingOutput *pgo );
@@ -55,5 +56,8 @@
 int InitEasySymbolInput(const char *prefix);
 static int FindSymbolKey( const char* symbol );
 
+#define OSX_STYLE_HANIN_SYMBOL_INPUT
+void PrepareHaninSymbolInputBuffer(ChewingData *pgdata, int key);
+
 #endif
 
