Index: pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c
===================================================================
--- pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c	(revision 4301)
+++ pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c	(revision 4302)
@@ -561,5 +561,6 @@
 	    } else if (!pj_stricmp2(&choice_attr->name, "desc")) {
 		pj_strassign(&choice_val->desc, &choice_attr->value);
-	    }				
+	    }
+	    choice_attr = choice_attr->next;
 	}			    
 	++(arg->stat_choice_cnt);
@@ -609,5 +610,5 @@
 	    } else if (!pj_stricmp2(&attr->value, "int")) {
 		arg->type = PJ_CLI_ARG_INT;
-	    } else if (!pj_stricmp2(&attr->value, "CHOICE")) {
+	    } else if (!pj_stricmp2(&attr->value, "choice")) {
 		/* Get choice value */
 		pj_cli_add_choice_node(cli, xml_node, arg, get_choice);
@@ -733,9 +734,16 @@
         cmd->arg = (pj_cli_arg_spec *)pj_pool_zalloc(cli->pool, cmd->arg_cnt *
                                                      sizeof(pj_cli_arg_spec));
+	
         for (i = 0; i < cmd->arg_cnt; i++) {
+	    unsigned j;
+
             pj_strdup(cli->pool, &cmd->arg[i].name, &args[i].name);
             pj_strdup(cli->pool, &cmd->arg[i].desc, &args[i].desc);
+	    cmd->arg[i].id = args[i].id;
             cmd->arg[i].type = args[i].type;
 	    cmd->arg[i].optional = args[i].optional;
+	    cmd->arg[i].get_dyn_choice = args[i].get_dyn_choice;
+	    cmd->arg[i].stat_choice_cnt = args[i].stat_choice_cnt;
+	    cmd->arg[i].stat_choice_val = args[i].stat_choice_val;
         }
     }
@@ -1064,6 +1072,5 @@
 	PJ_ASSERT_RETURN(arg, PJ_EINVAL);
 	if (arg->type == PJ_CLI_ARG_CHOICE) {	    
-	    unsigned j;	    
-	    pj_cli_dyn_choice_param dyn_choice_param;	    
+	    unsigned j;	    	    
 
 	    for (j=0; j < arg->stat_choice_cnt; ++j) {
@@ -1081,18 +1088,26 @@
 		}
 	    }
-	    /* Get the dynamic choice values */	    
-	    dyn_choice_param.sess = sess;
-	    dyn_choice_param.cmd = cmd;
-	    dyn_choice_param.arg_id = arg->id;
-	    dyn_choice_param.max_cnt = PJ_CLI_MAX_CHOICE_VAL;
-	    dyn_choice_param.pool = pool;
-	    dyn_choice_param.cnt = 0;	    
-
-	    (*arg->get_dyn_choice)(&dyn_choice_param);
-	    for (j=0; j < dyn_choice_param.cnt; ++j) {
-		pj_cli_arg_choice_val *choice = &dyn_choice_param.choice[j];
-		pj_strassign(&info->hint[info->hint_cnt].name, &choice->value);
-		pj_strassign(&info->hint[info->hint_cnt].desc, &choice->desc);
-		++info->hint_cnt;
+	    if (arg->get_dyn_choice) {
+		pj_cli_dyn_choice_param dyn_choice_param;
+		static const pj_str_t choice_str = {"choice", 6};
+
+		/* Get the dynamic choice values */	    
+		dyn_choice_param.sess = sess;
+		dyn_choice_param.cmd = cmd;
+		dyn_choice_param.arg_id = arg->id;
+		dyn_choice_param.max_cnt = PJ_CLI_MAX_CHOICE_VAL;
+		dyn_choice_param.pool = pool;
+		dyn_choice_param.cnt = 0;	    
+
+		(*arg->get_dyn_choice)(&dyn_choice_param);
+		for (j=0; j < dyn_choice_param.cnt; ++j) {
+		    pj_cli_arg_choice_val *choice = &dyn_choice_param.choice[j];
+		    if (!pj_strnicmp(&choice->value, cmd_val, cmd_val->slen)) {
+			pj_strassign(&info->hint[info->hint_cnt].name, &choice->value);
+			pj_strassign(&info->hint[info->hint_cnt].type, &choice_str);
+			pj_strassign(&info->hint[info->hint_cnt].desc, &choice->desc);
+			++info->hint_cnt;
+		    }
+		}
 	    }
 	} else {
Index: pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_console.c
===================================================================
--- pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_console.c	(revision 4301)
+++ pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_console.c	(revision 4302)
@@ -78,4 +78,15 @@
     ST_ARROWMODE
 } cmd_parse_state;
+
+/**
+ * This specify the state of output character parsing.
+ */
+typedef enum out_parse_state
+{
+    OP_NORMAL,
+    OP_TYPE,
+    OP_SHORTCUT,
+    OP_CHOICE
+} out_parse_state;
 
 /**
@@ -366,8 +377,8 @@
     console_recv_buf *recv_buf = &fe->input.recv_buf;
     const pj_cli_hint_info *hint = info->hint;
-    pj_bool_t is_process_sc = PJ_FALSE;
-    pj_bool_t valid_type = PJ_FALSE;
+    out_parse_state parse_state = OP_NORMAL;
     pj_ssize_t max_length = 0;
-    const pj_str_t sc_type = pj_str("SC");
+    static const pj_str_t sc_type = {"sc", 2};
+    static const pj_str_t choice_type = {"choice", 6};
     send_data.ptr = &data[0];
     send_data.slen = 0;
@@ -391,44 +402,44 @@
 
     for (i=0;i<info->hint_cnt;++i) {	
-	if ((&hint[i].type) && (hint[i].type.slen > 0)) {
-	    valid_type = PJ_TRUE;
+	pj_strcat2(&send_data, "\r\n  ");
+	
+	if ((&hint[i].type) && (hint[i].type.slen > 0)) {	    
 	    if (pj_stricmp(&hint[i].type, &sc_type) == 0) {
-		if (is_process_sc) {
-		    pj_strcat2(&send_data, ", ");
-		} else {
-		    pj_strcat2(&send_data, "\r\n\t Shorcut: ");
-		    is_process_sc = PJ_TRUE;
+		parse_state = OP_SHORTCUT;
+	    } else if (pj_stricmp(&hint[i].type, &choice_type) == 0) {
+		parse_state = OP_CHOICE;
+	    } else {
+		parse_state = OP_TYPE;
+	    }
+	} else {	    	    
+	    parse_state = OP_NORMAL;
+	}
+    
+	switch (parse_state) {
+	case OP_CHOICE:
+	    pj_strcat2(&send_data, "[");
+	    pj_strcat(&send_data, &hint[i].name);
+	    pj_strcat2(&send_data, "]");	
+	    break;
+	case OP_TYPE:
+	    pj_strcat2(&send_data, "<");
+	    pj_strcat(&send_data, &hint[i].type);
+	    pj_strcat2(&send_data, ">");	
+	    break;
+	default:
+	    pj_strcat(&send_data, &hint[i].name);	    
+	    break;
+	}
+    	
+	if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
+	    if (parse_state != OP_TYPE) {
+		for (j=0;j<(max_length-hint[i].name.slen);++j) {
+		    pj_strcat2(&send_data, " ");
 		}
-		pj_strcat(&send_data, &hint[i].name);
-	    } else {
-		is_process_sc = PJ_FALSE;
 	    }
-	} else {	    
-	    valid_type = PJ_FALSE;
-	    is_process_sc = PJ_FALSE;
-	}
-
-	if (!is_process_sc) {
-	    pj_strcat2(&send_data, "\r\n\t");
-
-	    if (valid_type) {
-		pj_strcat2(&send_data, "<");
-		pj_strcat(&send_data, &hint[i].type);
-		pj_strcat2(&send_data, ">");	
-	    } else {
-		pj_strcat(&send_data, &hint[i].name);	    
-	    }
-    	
-	    if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
-		if (!valid_type) {
-		    for (j=0;j<(max_length-hint[i].name.slen);++j) {
-			pj_strcat2(&send_data, " ");
-		    }
-		}
-		pj_strcat2(&send_data, "\t");
-		pj_strcat(&send_data, &hint[i].desc);	    
-	    }
-	}
-    }        
+	    pj_strcat2(&send_data, "  ");
+	    pj_strcat(&send_data, &hint[i].desc);	    
+	}
+    }  
     pj_strcat2(&send_data, "\r\n");
     pj_strcat(&send_data, &fe->cfg.prompt_str);
Index: pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_telnet.c
===================================================================
--- pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_telnet.c	(revision 4301)
+++ pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_telnet.c	(revision 4302)
@@ -198,4 +198,15 @@
 
 /**
+ * This specify the state of output character parsing.
+ */
+typedef enum out_parse_state
+{
+    OP_NORMAL,
+    OP_TYPE,
+    OP_SHORTCUT,
+    OP_CHOICE
+} out_parse_state;
+
+/**
  * This structure contains the command line shown to the user.  
  */
@@ -755,8 +766,8 @@
     struct cli_telnet_fe *fe = (struct cli_telnet_fe *)sess->base.fe;
     const pj_cli_hint_info *hint = info->hint;
-    pj_bool_t is_process_sc = PJ_FALSE;
-    pj_bool_t valid_type = PJ_FALSE;
+    out_parse_state parse_state = OP_NORMAL;
     pj_ssize_t max_length = 0;
-    const pj_str_t sc_type = pj_str("SC");    
+    static const pj_str_t sc_type = {"sc", 2};
+    static const pj_str_t choice_type = {"choice", 6};
     send_data.ptr = &data[0];
     send_data.slen = 0;
@@ -779,44 +790,44 @@
 
     for (i=0;i<info->hint_cnt;++i) {	
-	if ((&hint[i].type) && (hint[i].type.slen > 0)) {
-	    valid_type = PJ_TRUE;
+	pj_strcat2(&send_data, "\r\n  ");
+	
+	if ((&hint[i].type) && (hint[i].type.slen > 0)) {	    
 	    if (pj_stricmp(&hint[i].type, &sc_type) == 0) {
-		if (is_process_sc) {
-		    pj_strcat2(&send_data, ", ");
-		} else {
-		    pj_strcat2(&send_data, "\r\n\t Shorcut: ");
-		    is_process_sc = PJ_TRUE;
+		parse_state = OP_SHORTCUT;
+	    } else if (pj_stricmp(&hint[i].type, &choice_type) == 0) {
+		parse_state = OP_CHOICE;
+	    } else {
+		parse_state = OP_TYPE;
+	    }
+	} else {	    	    
+	    parse_state = OP_NORMAL;
+	}
+    
+	switch (parse_state) {
+	case OP_CHOICE:
+	    pj_strcat2(&send_data, "[");
+	    pj_strcat(&send_data, &hint[i].name);
+	    pj_strcat2(&send_data, "]");	
+	    break;
+	case OP_TYPE:
+	    pj_strcat2(&send_data, "<");
+	    pj_strcat(&send_data, &hint[i].name);
+	    pj_strcat2(&send_data, ">");	
+	    break;
+	default:
+	    pj_strcat(&send_data, &hint[i].name);	    
+	    break;
+	}
+    	
+	if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
+	    if (parse_state != OP_TYPE) {
+		for (j=0;j<(max_length-hint[i].name.slen);++j) {
+		    pj_strcat2(&send_data, " ");
 		}
-		pj_strcat(&send_data, &hint[i].name);
-	    } else {
-		is_process_sc = PJ_FALSE;
 	    }
-	} else {	    
-	    valid_type = PJ_FALSE;
-	    is_process_sc = PJ_FALSE;
+	    pj_strcat2(&send_data, "  ");
+	    pj_strcat(&send_data, &hint[i].desc);	    
 	}
-
-	if (!is_process_sc) {
-	    pj_strcat2(&send_data, "\r\n\t");
-
-	    if (valid_type) {
-		pj_strcat2(&send_data, "<");
-		pj_strcat(&send_data, &hint[i].type);
-		pj_strcat2(&send_data, ">");	
-	    } else {
-		pj_strcat(&send_data, &hint[i].name);	    
-	    }
-    	
-	    if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
-		if (!valid_type) {
-		    for (j=0;j<(max_length-hint[i].name.slen);++j) {
-			pj_strcat2(&send_data, " ");
-		    }
-		}
-		pj_strcat2(&send_data, "\t");
-		pj_strcat(&send_data, &hint[i].desc);	    
-	    }
-	}
-    }   
+    }  
     pj_strcat2(&send_data, "\r\n");       
     pj_strcat(&send_data, &fe->cfg.prompt_str);
@@ -1291,5 +1302,5 @@
 	    if (*cdata == IAC) {
 		sess->parse_state = ST_IAC;
-	    } else if (*cdata == '\b') {
+	    } else if (*cdata == 127) {
 		is_valid = handle_backspace(sess, cdata);
 	    } else if (*cdata == 27) {		    
Index: pjproject/branches/projects/cli/pjsip-apps/src/samples/clidemo.c
===================================================================
--- pjproject/branches/projects/cli/pjsip-apps/src/samples/clidemo.c	(revision 4301)
+++ pjproject/branches/projects/cli/pjsip-apps/src/samples/clidemo.c	(revision 4302)
@@ -90,4 +90,15 @@
 }
 
+static void get_codec_list(pj_cli_dyn_choice_param *param)
+{
+    if (param->arg_id == 3) {
+	param->cnt = 2;
+	pj_strdup2(param->pool, &param->choice[0].value, "iLbc");
+	pj_strdup2(param->pool, &param->choice[0].desc, "iLbc Codec");
+	pj_strdup2(param->pool, &param->choice[1].value, "g729");
+	pj_strdup2(param->pool, &param->choice[1].desc, "g729 Codec");
+    }
+}
+
 static struct cmd_xml_t cmd_xmls[] = {
     {"<CMD name='sayhello' id='1' sc='  ,h , ,, sh  ,' desc='Will say hello'>"
@@ -117,4 +128,11 @@
      "</CMD>",
      NULL},
+    {"<CMD name='disable_codec' id='8' desc='Disable codec'>"
+     "	<ARG name='codec_list' type='choice' id='3' desc='Codec list'>"
+     "	    <CHOICE value='g711' desc='G711 Codec'/>"
+     "	    <CHOICE value='g722' desc='G722 Codec'/>"
+     "	</ARG>"
+     "</CMD>",
+     NULL},
     {"<CMD name='quit_app' id='999' sc='qa' desc='Quit the application'>"
      "</CMD>",
@@ -159,5 +177,5 @@
         xml = pj_str(cmd_xmls[i].xml);	
         status = pj_cli_add_cmd_from_xml(cli, NULL, &xml, 
-                                         cmd_xmls[i].handler, NULL, NULL);
+	    cmd_xmls[i].handler, NULL, get_codec_list);
         if (status != PJ_SUCCESS)
 	    goto on_return;
Index: pjproject/branches/projects/cli/pjsip-apps/src/samples/debug.c
===================================================================
--- pjproject/branches/projects/cli/pjsip-apps/src/samples/debug.c	(revision 4301)
+++ pjproject/branches/projects/cli/pjsip-apps/src/samples/debug.c	(revision 4302)
@@ -29,4 +29,4 @@
  *  #include "playfile.c"
  */
-#include "clidemo.c"
+#include "icedemo.c"
 
