Changeset 4303


Ignore:
Timestamp:
Nov 30, 2012 8:57:18 AM (8 years ago)
Author:
riza
Message:

Re #1098: Modify input method for console, from character based to line based

Location:
pjproject/branches/projects/cli
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/cli/pjlib-util/include/pjlib-util/cli_console.h

    r4299 r4303  
    9898 * @return              PJ_SUCCESS if an input was read 
    9999 */ 
    100 PJ_DECL(pj_status_t) pj_cli_console_process(pj_cli_sess *sess); 
     100PJ_DECL(pj_status_t) pj_cli_console_process(pj_cli_sess *sess,  
     101                                            char *buf, 
     102                                            unsigned maxlen); 
    101103 
    102104/** 
  • pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c

    r4302 r4303  
    165165} pj_cli_arg_type; 
    166166 
    167 static const struct 
     167struct arg_type 
    168168{ 
    169169    const pj_str_t msg; 
    170 } arg_type[] =  
    171 { 
    172     {"Text", 4}, 
    173     {"Int", 3}, 
    174     {"Choice", 6} 
     170} arg_type[3] =  
     171{ 
     172    {{"Text", 4}}, 
     173    {{"Int", 3}}, 
     174    {{"Choice", 6}} 
    175175}; 
    176176 
     
    736736         
    737737        for (i = 0; i < cmd->arg_cnt; i++) { 
    738             unsigned j; 
    739  
    740738            pj_strdup(cli->pool, &cmd->arg[i].name, &args[i].name); 
    741739            pj_strdup(cli->pool, &cmd->arg[i].desc, &args[i].desc); 
     
    835833    /* Set the parse mode based on the latest char. */ 
    836834    len = pj_ansi_strlen(cmdline); 
    837     if (len > 0 && cmdline[len - 1] == '\r') { 
     835    if (len > 0 && ((cmdline[len - 1] == '\r')||(cmdline[len - 1] == '\n'))) { 
    838836        cmdline[--len] = 0; 
    839837        parse_mode = PARSE_EXEC; 
     
    921919        } 
    922920 
    923     } else if (parse_mode == PARSE_COMPLETION) { 
    924         if (info->hint[0].name.slen > str.slen) { 
    925             pj_str_t *hint_info = &info->hint[0].name; 
    926             pj_memmove(&hint_info->ptr[0], &hint_info->ptr[str.slen],  
    927                        info->hint[0].name.slen-str.slen); 
    928             hint_info->slen = info->hint[0].name.slen-str.slen;          
    929         } else { 
    930             info->hint[0].name.slen = 0; 
    931         } 
    932     }     
     921    }  
     922    
    933923    val->sess = sess; 
    934924    return status; 
     
    10901080            if (arg->get_dyn_choice) { 
    10911081                pj_cli_dyn_choice_param dyn_choice_param; 
    1092                 static const pj_str_t choice_str = {"choice", 6}; 
     1082                static pj_str_t choice_str = {"choice", 6}; 
    10931083 
    10941084                /* Get the dynamic choice values */          
  • pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_console.c

    r4302 r4303  
    2828#include <pjlib-util/errno.h> 
    2929 
    30 #if defined(PJ_LINUX) && PJ_LINUX != 0 || \ 
    31     defined(PJ_DARWINOS) && PJ_DARWINOS != 0 
    32 #include <termios.h> 
    33  
    34 static struct termios old, new; 
    35  
    36 /* Initialize new terminal i/o settings */ 
    37 void initTermios(int echo)  
    38 { 
    39     tcgetattr(0, &old);  
    40     new = old;  
    41     new.c_lflag &= ~ICANON;  
    42     new.c_lflag &= echo ? ECHO : ~ECHO;  
    43     tcsetattr(0, TCSANOW, &new);  
    44 } 
    45  
    46 /* Restore old terminal i/o settings */ 
    47 void resetTermios(void)  
    48 { 
    49     tcsetattr(0, TCSANOW, &old); 
    50 } 
    51  
    52 /* Read 1 character - echo defines echo mode */ 
    53 char getch_(int echo)  
    54 { 
    55     char ch; 
    56     initTermios(echo); 
    57     ch = getchar(); 
    58     resetTermios(); 
    59     return ch; 
    60 } 
    61  
    62 /* Read 1 character without echo */ 
    63 char getch(void)  
    64 { 
    65     return getch_(0); 
    66 } 
    67  
    68 #endif 
    69  
    70 /** 
    71  * This specify the state of input character parsing. 
    72  */ 
    73 typedef enum cmd_parse_state 
    74 { 
    75     ST_NORMAL, 
    76     ST_SCANMODE, 
    77     ST_ESC, 
    78     ST_ARROWMODE 
    79 } cmd_parse_state; 
    80  
    8130/** 
    8231 * This specify the state of output character parsing. 
     
    8938    OP_CHOICE 
    9039} out_parse_state; 
    91  
    92 /** 
    93  * This structure contains the command line shown to the user.   
    94  */ 
    95 typedef struct console_recv_buf { 
    96     /** 
    97      * Buffer containing the characters, NULL terminated. 
    98      */ 
    99     unsigned char           rbuf[PJ_CLI_MAX_CMDBUF]; 
    100  
    101     /** 
    102      * Current length of the command line. 
    103      */ 
    104     unsigned                len; 
    105  
    106     /** 
    107      * Current cursor position. 
    108      */ 
    109     unsigned                cur_pos; 
    110 } console_recv_buf; 
    111  
    112 typedef struct cmd_history 
    113 { 
    114     PJ_DECL_LIST_MEMBER(struct cmd_history); 
    115     pj_str_t command; 
    116 } cmd_history; 
    11740 
    11841struct cli_console_fe 
     
    12447    pj_bool_t           thread_quit; 
    12548    pj_sem_t           *thread_sem;    
    126     pj_cli_console_cfg  cfg; 
     49    pj_cli_console_cfg  cfg;     
    12750 
    12851    struct async_input_t 
    12952    {         
    130         console_recv_buf    recv_buf;         
    131         pj_sem_t           *sem; 
     53        char       *buf; 
     54        unsigned    maxlen;      
     55        pj_sem_t   *sem; 
    13256    } input; 
    133  
    134     cmd_history             *history; 
    135     cmd_history             *active_history; 
    13657}; 
    137  
    138 static unsigned recv_buf_right_len(console_recv_buf *recv_buf) 
    139 { 
    140     return (recv_buf->len - recv_buf->cur_pos); 
    141 } 
    142  
    143 static pj_bool_t recv_buf_insert(console_recv_buf *recv_buf,  
    144                                  unsigned char *data)  
    145 {     
    146     if (recv_buf->len+1 >= PJ_CLI_MAX_CMDBUF) { 
    147         return PJ_FALSE; 
    148     } else {     
    149         if (*data == '\t' || *data == '?' || *data == '\r') { 
    150             /* Always insert to the end of line */ 
    151             recv_buf->rbuf[recv_buf->len] = *data; 
    152         } else { 
    153             /* Insert based on the current cursor pos */ 
    154             unsigned cur_pos = recv_buf->cur_pos; 
    155             unsigned rlen = recv_buf_right_len(recv_buf);            
    156             if (rlen > 0) {                  
    157                 /* Shift right characters */ 
    158                 pj_memmove(&recv_buf->rbuf[cur_pos+1],  
    159                            &recv_buf->rbuf[cur_pos],  
    160                            rlen+1); 
    161             }  
    162             recv_buf->rbuf[cur_pos] = *data; 
    163         } 
    164         ++recv_buf->cur_pos; 
    165         ++recv_buf->len; 
    166         recv_buf->rbuf[recv_buf->len] = 0; 
    167     } 
    168     return PJ_TRUE; 
    169 } 
    170  
    171 static pj_bool_t recv_buf_backspace(console_recv_buf *recv_buf) 
    172 { 
    173     if ((recv_buf->cur_pos == 0) || (recv_buf->len == 0)) { 
    174         return PJ_FALSE; 
    175     } else { 
    176         unsigned rlen = recv_buf_right_len(recv_buf); 
    177         if (rlen) { 
    178             unsigned cur_pos = recv_buf->cur_pos; 
    179             pj_memmove(&recv_buf->rbuf[cur_pos-1], &recv_buf->rbuf[cur_pos],  
    180                        rlen); 
    181         } 
    182         --recv_buf->cur_pos; 
    183         --recv_buf->len; 
    184         recv_buf->rbuf[recv_buf->len] = 0; 
    185     }     
    186     return PJ_TRUE; 
    187 } 
    18858 
    18959static void cli_console_write_log(pj_cli_front_end *fe, int level, 
     
    19565        printf("%.*s", len, data); 
    19666} 
    197  
    19867 
    19968static void cli_console_quit(pj_cli_front_end *fe, pj_cli_sess *req) 
     
    22998    pj_assert(param); 
    23099 
    231     param->log_level = PJ_CLI_CONSOLE_LOG_LEVEL;     
     100    param->log_level = PJ_CLI_CONSOLE_LOG_LEVEL; 
     101    param->prompt_str.slen = 0; 
    232102} 
    233103 
     
    251121    sess = PJ_POOL_ZALLOC_T(pool, pj_cli_sess); 
    252122    fe = PJ_POOL_ZALLOC_T(pool, struct cli_console_fe); 
    253     fe->history = PJ_POOL_ZALLOC_T(pool, struct cmd_history); 
    254     pj_list_init(fe->history); 
    255     fe->active_history = fe->history; 
    256123 
    257124    if (!param) { 
     
    260127    } 
    261128    sess->fe = &fe->base; 
    262     sess->log_level = param->log_level; 
     129    sess->log_level = param->log_level;     
    263130    sess->op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_sess_op); 
    264131    fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op); 
     
    274141    pj_cli_register_front_end(cli, &fe->base); 
    275142 
    276     if (fe->cfg.prompt_str.slen == 0) {  
     143    if (param->prompt_str.slen == 0) {   
    277144        pj_str_t prompt_sign = pj_str(">>> "); 
    278         char *prompt_data = pj_pool_alloc(fe->pool, 5);  
    279         fe->cfg.prompt_str.ptr = prompt_data;    
    280  
    281         pj_strcpy(&fe->cfg.prompt_str, &prompt_sign); 
    282         prompt_data[4] = 0; 
    283     } 
     145        fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, prompt_sign.slen+1); 
     146        pj_strcpy(&fe->cfg.prompt_str, &prompt_sign);    
     147    } else { 
     148        fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool,  
     149                                               param->prompt_str.slen+1); 
     150        pj_strcpy(&fe->cfg.prompt_str, &param->prompt_str); 
     151    }     
     152    fe->cfg.prompt_str.ptr[fe->cfg.prompt_str.slen] = 0;     
    284153 
    285154    *p_sess = sess; 
     
    308177                         const pj_cli_exec_info *info,  
    309178                         const pj_str_t *msg, 
    310                          pj_bool_t with_return, 
    311                          pj_bool_t with_last_cmd) 
     179                         pj_bool_t with_return) 
    312180{ 
    313181    pj_str_t send_data; 
     
    316184    unsigned i; 
    317185    struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    318     console_recv_buf *recv_buf = &fe->input.recv_buf; 
    319186 
    320187    send_data.ptr = &data_str[0]; 
     
    333200    pj_strcat(&send_data, msg); 
    334201    pj_strcat(&send_data, &fe->cfg.prompt_str); 
    335     if (with_last_cmd) 
    336         pj_strcat2(&send_data, (char *)&recv_buf->rbuf[0]); 
    337202 
    338203    send_data.ptr[send_data.slen] = 0; 
    339     printf("%s", send_data.ptr); 
    340 } 
    341  
    342 static void send_return_key(pj_cli_sess *sess)  
    343 {     
    344     PJ_UNUSED_ARG(sess); 
    345     printf("\r\n");     
     204    printf("%s", send_data.ptr);     
    346205} 
    347206 
    348207static void send_inv_arg(pj_cli_sess *sess,  
    349208                         const pj_cli_exec_info *info, 
    350                          pj_bool_t with_return, 
    351                          pj_bool_t with_last_cmd) 
     209                         pj_bool_t with_return) 
    352210{ 
    353211    static const pj_str_t ERR_MSG = {"%Error : Invalid Arguments\r\n", 28}; 
    354     send_err_arg(sess, info, &ERR_MSG, with_return, with_last_cmd); 
     212    send_err_arg(sess, info, &ERR_MSG, with_return); 
    355213} 
    356214 
    357215static void send_too_many_arg(pj_cli_sess *sess,  
    358216                              const pj_cli_exec_info *info, 
    359                               pj_bool_t with_return, 
    360                               pj_bool_t with_last_cmd) 
     217                              pj_bool_t with_return) 
    361218{ 
    362219    static const pj_str_t ERR_MSG = {"%Error : Too Many Arguments\r\n", 29}; 
    363     send_err_arg(sess, info, &ERR_MSG, with_return, with_last_cmd); 
     220    send_err_arg(sess, info, &ERR_MSG, with_return); 
    364221} 
    365222 
    366223static void send_ambi_arg(pj_cli_sess *sess,  
    367224                          const pj_cli_exec_info *info, 
    368                           pj_bool_t with_return, 
    369                           pj_bool_t with_last_cmd) 
     225                          pj_bool_t with_return) 
    370226{ 
    371227    unsigned i; 
     
    375231    char data[1028]; 
    376232    struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    377     console_recv_buf *recv_buf = &fe->input.recv_buf; 
    378233    const pj_cli_hint_info *hint = info->hint; 
    379234    out_parse_state parse_state = OP_NORMAL; 
     
    444299    pj_strcat2(&send_data, "\r\n"); 
    445300    pj_strcat(&send_data, &fe->cfg.prompt_str); 
    446     if (with_last_cmd) 
    447         pj_strcat2(&send_data, (char *)&recv_buf->rbuf[0]); 
    448301 
    449302    send_data.ptr[send_data.slen] = 0; 
    450     printf("%s", send_data.ptr); 
    451 } 
    452  
    453 static void send_comp_arg(pj_cli_exec_info *info) 
    454 { 
    455     pj_str_t send_data; 
    456     char data[128]; 
    457  
    458     pj_strcat2(&info->hint[0].name, " "); 
    459  
    460     send_data.ptr = &data[0]; 
    461     send_data.slen = 0; 
    462  
    463     pj_strcat(&send_data, &info->hint[0].name);         
    464  
    465     send_data.ptr[send_data.slen] = 0; 
    466     printf("%s", send_data.ptr); 
    467 } 
    468  
    469 static int compare_str(void *value, const pj_list_type *nd) 
    470 { 
    471     cmd_history *node = (cmd_history*)nd; 
    472     return (pj_strcmp((pj_str_t *)value, &node->command)); 
    473 } 
    474  
    475 static pj_status_t insert_history(pj_cli_sess *sess,                              
    476                                   char *cmd_val) 
    477 { 
    478     cmd_history *in_history; 
    479     pj_str_t cmd; 
    480     struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;     
    481     cmd.ptr = cmd_val; 
    482     cmd.slen = pj_ansi_strlen(cmd_val)-1; 
    483  
    484     if (cmd.slen == 0) 
    485         return PJ_SUCCESS; 
    486  
    487     PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
    488  
    489     /* Find matching history */ 
    490     in_history = pj_list_search(fe->history, (void*)&cmd, compare_str); 
    491     if (!in_history) { 
    492         if (pj_list_size(fe->history) < PJ_CLI_MAX_CMD_HISTORY) {            
    493             char *data_history; 
    494             in_history = PJ_POOL_ZALLOC_T(fe->pool, cmd_history); 
    495             pj_list_init(in_history); 
    496             data_history = (char *)pj_pool_calloc(fe->pool,  
    497                            sizeof(char), PJ_CLI_MAX_CMDBUF); 
    498             in_history->command.ptr = data_history; 
    499             in_history->command.slen = 0; 
    500         } else { 
    501             /* Get the oldest history */ 
    502             in_history = fe->history->prev; 
    503         }            
    504     } else { 
    505         pj_list_insert_nodes_after(in_history->prev, in_history->next); 
    506     } 
    507     pj_strcpy(&in_history->command, pj_strtrim(&cmd)); 
    508     pj_list_push_front(fe->history, in_history); 
    509     fe->active_history = fe->history; 
    510  
    511     return PJ_SUCCESS; 
    512 } 
    513  
    514 static pj_str_t* get_prev_history(pj_cli_sess *sess, pj_bool_t is_forward) 
    515 { 
    516     pj_str_t *retval; 
    517     pj_size_t history_size; 
    518     cmd_history *node; 
    519     cmd_history *root; 
    520     struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    521  
    522     PJ_ASSERT_RETURN(sess && fe, NULL); 
    523  
    524     node = fe->active_history; 
    525     root = fe->history; 
    526     history_size = pj_list_size(fe->history); 
    527  
    528     if (history_size == 0) { 
    529         return NULL; 
    530     } else { 
    531         if (is_forward) {            
    532             node = (node->next==root)?node->next->next:node->next;           
    533         } else { 
    534             node = (node->prev==root)?node->prev->prev:node->prev;           
    535         } 
    536         retval = &node->command; 
    537         fe->active_history = node; 
    538     } 
    539     return retval; 
    540 } 
    541  
    542 static pj_bool_t handle_alfa_num(console_recv_buf *recv_buf,  
    543                                  unsigned char *cdata) 
    544 {         
    545     if (recv_buf_right_len(recv_buf) > 0) { 
    546         char out_str[255];       
    547         pj_memset(&out_str[0], 0, 255); 
    548         out_str[0] = *cdata; 
    549         pj_memcpy(&out_str[1], &recv_buf->rbuf[recv_buf->cur_pos],  
    550                   recv_buf_right_len(recv_buf)); 
    551         pj_memset(&out_str[recv_buf_right_len(recv_buf)+1], '\b',  
    552                   recv_buf_right_len(recv_buf));         
    553         printf("%s", out_str);  
    554     } else {     
    555         printf("%c", *cdata); 
    556     }     
    557     return PJ_TRUE; 
    558 } 
    559  
    560 static pj_bool_t handle_backspace(console_recv_buf *recv_buf) 
    561 {     
    562     if (recv_buf_backspace(recv_buf)) { 
    563         if(recv_buf_right_len(recv_buf) > 0) { 
    564             char out_str[255]; 
    565             pj_memset(&out_str[0], 0, 255); 
    566             out_str[0] = '\b'; 
    567             pj_memcpy(&out_str[1], &recv_buf->rbuf[recv_buf->cur_pos],  
    568                 recv_buf_right_len(recv_buf)); 
    569             out_str[recv_buf_right_len(recv_buf)+1] = ' ';  
    570             pj_memset(&out_str[recv_buf_right_len(recv_buf)+2], '\b',  
    571                 recv_buf_right_len(recv_buf)+1); 
    572             printf("%s", out_str); 
    573         } else { 
    574             char out_str[4]; 
    575             out_str[0] = '\b'; 
    576             out_str[1] = ' '; 
    577             out_str[2] = '\b'; 
    578             out_str[3] = 0; 
    579             printf("%s", out_str); 
    580         } 
    581         return PJ_TRUE; 
    582     } 
    583     return PJ_FALSE; 
    584 } 
    585  
    586 static pj_bool_t handle_tab(pj_cli_sess *sess) 
     303    printf("%s", send_data.ptr);     
     304} 
     305 
     306static pj_bool_t handle_hint(pj_cli_sess *sess) 
    587307{ 
    588308    pj_status_t status; 
    589309    pj_bool_t retval = PJ_TRUE; 
    590     unsigned len; 
    591310     
    592311    pj_pool_t *pool; 
     
    594313    pj_cli_exec_info info; 
    595314    struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    596     console_recv_buf *recv_buf = &fe->input.recv_buf; 
     315    char *recv_buf = fe->input.buf; 
    597316    pj_cli_t *cli = sess->fe->cli; 
    598317 
    599     pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_tab", 
     318    pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_hint", 
    600319                          PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC, 
    601320                          NULL); 
     
    603322    cmd_val = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_val); 
    604323     
    605     status = pj_cli_sess_parse(sess, (char *)recv_buf->rbuf, cmd_val,  
    606                                pool, &info);     
    607  
    608     len = pj_ansi_strlen((char *)recv_buf->rbuf); 
     324    status = pj_cli_sess_parse(sess, recv_buf, cmd_val,  
     325                               pool, &info); 
    609326 
    610327    switch (status) { 
    611328    case PJ_CLI_EINVARG: 
    612         send_inv_arg(sess, &info, PJ_TRUE, PJ_TRUE);             
     329        send_inv_arg(sess, &info, PJ_TRUE);              
    613330        break; 
    614331    case PJ_CLI_ETOOMANYARGS: 
    615         send_too_many_arg(sess, &info, PJ_TRUE, PJ_TRUE); 
     332        send_too_many_arg(sess, &info, PJ_TRUE); 
    616333        break; 
    617334    case PJ_CLI_EMISSINGARG: 
    618335    case PJ_CLI_EAMBIGUOUS: 
    619         send_ambi_arg(sess, &info, PJ_TRUE, PJ_TRUE); 
    620         break; 
    621     case PJ_SUCCESS: 
    622         if (len > recv_buf->cur_pos) 
    623         { 
    624             /* Send the cursor to EOL */ 
    625             unsigned char *data_sent = &recv_buf->rbuf[recv_buf->cur_pos-1]; 
    626             printf("%s", data_sent);         
    627         } 
     336        send_ambi_arg(sess, &info, PJ_TRUE); 
     337        break; 
     338    case PJ_SUCCESS:     
    628339        if (info.hint_cnt > 0) {         
    629             /* Compelete command */ 
    630             send_comp_arg(&info); 
    631  
    632             pj_memcpy(&recv_buf->rbuf[len],   
    633                       &info.hint[0].name.ptr[0], info.hint[0].name.slen); 
    634  
    635             len += info.hint[0].name.slen; 
    636             recv_buf->rbuf[len] = 0;                 
     340            /* Compelete command */          
     341            send_ambi_arg(sess, &info, PJ_TRUE);                         
    637342        } else { 
    638343            retval = PJ_FALSE; 
    639         } 
    640         break; 
    641     } 
    642     recv_buf->len = len; 
    643     recv_buf->cur_pos = len; 
     344        }        
     345        break; 
     346    } 
    644347 
    645348    pj_pool_release(pool);       
     
    647350} 
    648351 
    649 static pj_bool_t handle_return(pj_cli_sess *sess) 
     352static pj_bool_t handle_exec(pj_cli_sess *sess) 
    650353{ 
    651354    pj_status_t status; 
     
    656359    pj_cli_t *cli = sess->fe->cli; 
    657360    struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    658     console_recv_buf *recv_buf = &fe->input.recv_buf; 
    659      
    660     send_return_key(sess);     
    661     insert_history(sess, (char *)&recv_buf->rbuf[0]); 
    662  
    663     pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_return", 
     361    char *recv_buf = fe->input.buf; 
     362         
     363    printf("\r\n"); 
     364 
     365    pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_exec", 
    664366                          PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC, 
    665367                          NULL);     
    666368     
    667     status = pj_cli_sess_exec(sess, (char *)&recv_buf->rbuf[0],  
     369    status = pj_cli_sess_exec(sess, recv_buf,  
    668370                              pool, &info); 
    669371 
    670372    switch (status) { 
    671373    case PJ_CLI_EINVARG: 
    672         send_inv_arg(sess, &info, PJ_FALSE, PJ_FALSE);   
     374        send_inv_arg(sess, &info, PJ_FALSE);     
    673375        break; 
    674376    case PJ_CLI_ETOOMANYARGS: 
    675         send_too_many_arg(sess, &info, PJ_FALSE, PJ_FALSE); 
     377        send_too_many_arg(sess, &info, PJ_FALSE); 
    676378        break; 
    677379    case PJ_CLI_EAMBIGUOUS: 
    678380    case PJ_CLI_EMISSINGARG: 
    679         send_ambi_arg(sess, &info, PJ_FALSE, PJ_FALSE); 
     381        send_ambi_arg(sess, &info, PJ_FALSE); 
    680382        break; 
    681383    case PJ_CLI_EEXIT: 
     
    683385        break; 
    684386    case PJ_SUCCESS: 
    685         send_prompt_str(sess); 
     387        send_prompt_str(sess);   
    686388        break; 
    687389    }     
    688     if (retval) { 
    689         recv_buf->rbuf[0] = 0; 
    690         recv_buf->len = 0; 
    691         recv_buf->cur_pos = 0; 
    692     } 
    693390 
    694391    pj_pool_release(pool);       
     
    696393} 
    697394 
    698 static pj_bool_t handle_up_down(pj_cli_sess *sess, pj_bool_t is_up) 
    699 { 
    700     pj_str_t *history; 
    701     struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    702     console_recv_buf *recv_buf = &fe->input.recv_buf; 
    703  
    704     PJ_ASSERT_RETURN(sess && fe, PJ_FALSE); 
    705  
    706     history = get_prev_history(sess, is_up); 
    707     if (history) { 
    708         pj_str_t send_data; 
    709         char str[PJ_CLI_MAX_CMDBUF]; 
    710         send_data.ptr = &str[0]; 
    711         send_data.slen = 0; 
    712  
    713         if (recv_buf->cur_pos > 0) { 
    714             pj_memset(send_data.ptr, 0x08, recv_buf->cur_pos); 
    715             send_data.slen = recv_buf->cur_pos; 
    716         } 
    717  
    718         if (recv_buf->len > (unsigned)history->slen) { 
    719             unsigned buf_len = recv_buf->len; 
    720             pj_memset(&send_data.ptr[send_data.slen], 0x20, buf_len); 
    721             send_data.slen += buf_len; 
    722             pj_memset(&send_data.ptr[send_data.slen], 0x08, buf_len); 
    723             send_data.slen += buf_len; 
    724         }  
    725         /* Send data */ 
    726         pj_strcat(&send_data, history);  
    727         send_data.ptr[send_data.slen] = 0; 
    728         printf("%s", send_data.ptr); 
    729         pj_ansi_strncpy((char*)&recv_buf->rbuf, history->ptr, history->slen); 
    730         recv_buf->rbuf[history->slen] = 0; 
    731         recv_buf->len = history->slen; 
    732         recv_buf->cur_pos = recv_buf->len; 
    733         return PJ_TRUE; 
    734     } 
    735     return PJ_FALSE; 
    736 } 
    737  
    738 static pj_bool_t handle_left_key(console_recv_buf *recv_buf) 
    739 { 
    740     const static unsigned char BACK_SPACE = 0x08; 
    741     if (recv_buf->cur_pos) { 
    742         printf("%c", BACK_SPACE); 
    743         --recv_buf->cur_pos; 
    744         return PJ_TRUE; 
    745     } 
    746     return PJ_FALSE; 
    747 } 
    748  
    749 static pj_bool_t handle_right_key(console_recv_buf *recv_buf) 
    750 { 
    751     if (recv_buf_right_len(recv_buf)) { 
    752         unsigned char *data = &recv_buf->rbuf[recv_buf->cur_pos++]; 
    753         printf("%c", *data); 
    754         return PJ_TRUE; 
    755     } 
    756     return PJ_FALSE; 
    757 } 
    758  
    759 static int readchar_thread(void * p) 
     395static int readline_thread(void * p) 
    760396{     
    761397    struct cli_console_fe * fe = (struct cli_console_fe *)p; 
    762     cmd_parse_state parse_state = ST_NORMAL; 
    763398 
    764399    printf("%s", fe->cfg.prompt_str.ptr); 
    765400 
    766401    while (!fe->thread_quit) { 
    767         unsigned char cdata; 
    768         console_recv_buf *recv_buf = &fe->input.recv_buf; 
     402        unsigned input_len = 0; 
     403        char *recv_buf = fe->input.buf; 
    769404        pj_bool_t is_valid = PJ_TRUE; 
    770405 
    771         cdata = (unsigned char)getch(); 
    772  
    773         switch (parse_state) { 
    774         case ST_NORMAL: 
    775             if (cdata == '\b') { 
    776                 is_valid = handle_backspace(recv_buf); 
    777             } else if (cdata == 224) {       
    778                 parse_state = ST_SCANMODE; 
    779             } else if (cdata == 27) {        
    780                 parse_state = ST_ESC; 
    781             } else { 
    782                 if (cdata == '\n') 
    783                     cdata = '\r'; 
    784                 if (recv_buf_insert(recv_buf, &cdata)) { 
    785                     if (cdata == '\r') { 
    786                         is_valid = handle_return(fe->sess); 
    787                     } else if ((cdata == '\t') || (cdata == '?')) { 
    788                         is_valid = handle_tab(fe->sess); 
    789                     } else if (cdata > 31 && cdata < 127) { 
    790                         is_valid = handle_alfa_num(recv_buf, &cdata);                    
    791                     } 
    792                 } else { 
    793                     is_valid = PJ_FALSE; 
    794                 } 
    795             }        
    796             break; 
    797         case ST_SCANMODE: 
    798             switch (cdata) { 
    799             case 72: 
    800                 //UP 
    801             case 80: 
    802                 //DOwN 
    803                 is_valid = handle_up_down(fe->sess, (cdata==72)); 
    804                 break; 
    805             case 75: 
    806                 is_valid = handle_left_key(recv_buf); 
    807                 //LEFT 
    808                 break; 
    809             case 77: 
    810                 is_valid = handle_right_key(recv_buf); 
    811                 //RIGHT 
    812                 break; 
    813             }; 
    814             parse_state = ST_NORMAL; 
    815             break; 
    816         case ST_ESC: 
    817             parse_state = (cdata == 91)?ST_ARROWMODE:ST_NORMAL; 
    818             break; 
    819         case ST_ARROWMODE: 
    820             switch (cdata) { 
    821             case 65: 
    822                 //UP 
    823             case 66: 
    824                 //DOwN 
    825                 is_valid = handle_up_down(fe->sess, (cdata==65)); 
    826                 break; 
    827             case 68: 
    828                 is_valid = handle_left_key(recv_buf); 
    829                 //LEFT 
    830                 break; 
    831             case 67: 
    832                 is_valid = handle_right_key(recv_buf); 
    833                 //RIGHT 
    834                 break; 
    835             }; 
    836             parse_state = ST_NORMAL;         
    837             break; 
    838         }; 
     406        fgets(recv_buf, fe->input.maxlen, stdin);        
     407        input_len = pj_ansi_strlen(fe->input.buf);       
     408        if ((input_len > 1) && (fe->input.buf[input_len-2] == '?')) { 
     409            fe->input.buf[input_len-1] = 0; 
     410            is_valid = handle_hint(fe->sess); 
     411        } else { 
     412            is_valid = handle_exec(fe->sess); 
     413        } 
    839414 
    840415        pj_sem_post(fe->input.sem);         
     
    846421} 
    847422 
    848 PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess) 
     423PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess,  
     424                                           char *buf, 
     425                                           unsigned maxlen) 
    849426{ 
    850427    struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 
    851428 
    852429    PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
     430 
     431    fe->input.buf = buf; 
     432    fe->input.maxlen = maxlen; 
    853433 
    854434    if (!fe->input_thread) { 
    855435        pj_status_t status; 
    856436 
    857         status = pj_thread_create(fe->pool, NULL, &readchar_thread, fe, 
     437        status = pj_thread_create(fe->pool, NULL, &readline_thread, fe, 
    858438                                  0, 0, &fe->input_thread); 
    859439        if (status != PJ_SUCCESS) 
  • pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_telnet.c

    r4302 r4303  
    2727#include <pj/pool.h> 
    2828#include <pj/string.h> 
     29#include <pj/except.h> 
    2930#include <pjlib-util/errno.h> 
     31#include <pjlib-util/scanner.h> 
    3032 
    3133#define CLI_TELNET_BUF_SIZE 256 
     
    889891} 
    890892 
     893/* Syntax error handler for parser. */ 
     894static void on_syntax_error(pj_scanner *scanner) 
     895{ 
     896    PJ_UNUSED_ARG(scanner); 
     897    PJ_THROW(PJ_EINVAL); 
     898} 
     899 
     900static pj_status_t get_last_token(pj_str_t *cmd, pj_str_t *str) 
     901{ 
     902    pj_scanner scanner; 
     903    PJ_USE_EXCEPTION; 
     904    pj_scan_init(&scanner, cmd->ptr, cmd->slen, PJ_SCAN_AUTOSKIP_WS,  
     905                 &on_syntax_error); 
     906    PJ_TRY { 
     907        while (!pj_scan_is_eof(&scanner)) { 
     908            pj_scan_get_until_chr(&scanner, " \t\r\n", str); 
     909        } 
     910    } 
     911    PJ_CATCH_ANY { 
     912        pj_scan_fini(&scanner);  
     913        return PJ_GET_EXCEPTION(); 
     914    } 
     915    PJ_END; 
     916    return PJ_SUCCESS; 
     917} 
     918 
    891919static pj_bool_t handle_tab(cli_telnet_sess *sess) 
    892920{ 
     
    930958        if (info.hint_cnt > 0) {         
    931959            /* Complete command */ 
    932             send_comp_arg(sess, &info); 
    933  
    934             pj_memcpy(&sess->rcmd->rbuf[len],  
    935                       &info.hint[0].name.ptr[0], info.hint[0].name.slen); 
    936  
    937             len += info.hint[0].name.slen; 
    938             sess->rcmd->rbuf[len] = 0;               
     960            pj_str_t cmd = pj_str((char *)&sess->rcmd->rbuf[0]); 
     961            pj_str_t last_token; 
     962 
     963            if (get_last_token(&cmd, &last_token) == PJ_SUCCESS) { 
     964                pj_str_t *hint_info = &info.hint[0].name; 
     965                pj_strtrim(&last_token); 
     966                if (hint_info->slen > last_token.slen) { 
     967                    hint_info->slen -= last_token.slen; 
     968                    pj_memmove(&hint_info->ptr[0], &hint_info->ptr[last_token.slen],  
     969                               hint_info->slen);                     
     970                }  
     971                send_comp_arg(sess, &info); 
     972 
     973                pj_memcpy(&sess->rcmd->rbuf[len], &info.hint[0].name.ptr[0],  
     974                          info.hint[0].name.slen); 
     975 
     976                len += info.hint[0].name.slen; 
     977                sess->rcmd->rbuf[len] = 0;                   
     978            } 
    939979        } else { 
    940980            retval = PJ_FALSE; 
  • pjproject/branches/projects/cli/pjsip-apps/src/samples/clidemo.c

    r4302 r4303  
    190190    tcfg.port = 0; 
    191191#endif 
     192    tcfg.port = 2233; 
     193    tcfg.prompt_str = pj_str("CoolWater% "); 
    192194    status = pj_cli_telnet_create(cli, &tcfg, NULL); 
    193195    if (status != PJ_SUCCESS) 
     
    221223    pj_status_t status; 
    222224    pj_cli_sess *sess; 
    223  
     225    pj_cli_console_cfg console_cfg; 
     226 
     227    pj_cli_console_cfg_default(&console_cfg); 
     228    console_cfg.prompt_str = pj_str("HotWater> "); 
     229     
    224230    /* 
    225231     * Create the console front end 
    226232     */ 
    227     status = pj_cli_console_create(cli, NULL, &sess, NULL); 
     233    status = pj_cli_console_create(cli, &console_cfg, &sess, NULL); 
    228234    if (status != PJ_SUCCESS) 
    229235        return status; 
     
    235241     */ 
    236242    for (;;) { 
     243        char cmdline[PJ_CLI_MAX_CMDBUF]; 
    237244        pj_status_t status; 
    238245 
    239         status = pj_cli_console_process(sess); 
     246        status = pj_cli_console_process(sess, &cmdline[0], sizeof(cmdline)); 
    240247        if (status != PJ_SUCCESS) 
    241248            break; 
  • pjproject/branches/projects/cli/third_party

    • Property svn:externals
      •  

        old new  
        1 portaudio -r 1433 https://subversion.assembla.com/svn/portaudio/portaudio/trunk 
         1portaudio       -r1433 https://subversion.assembla.com/svn/portaudio/portaudio/trunk 
Note: See TracChangeset for help on using the changeset viewer.