/*deal with normal character*/ static void handle_normal(char *out_cmd, char c) { int tmp_cursor = cmd_cursor; /*buffer full */ if (++cmd_strlen > (MATCH_BUF_MAX - 2)) return; /*append operation */ if (cmd_cursor == (cmd_strlen - 1)) { *(out_cmd + cmd_cursor) = c; *(out_cmd + cmd_cursor + 1) = 0; term_echo(); } else { /* Insert operation */ /*give position to new char */ memmove(out_cmd + tmp_cursor + 1, out_cmd + tmp_cursor, cmd_strlen - tmp_cursor); *(out_cmd + tmp_cursor) = c; /* re-print from cursor */ while (cmd_cursor < cmd_strlen) term_echo(); /* restore curor to insert position */ tmp_cursor = cmd_cursor - tmp_cursor - 1; while (tmp_cursor--) cursor_backward(); } }
/*delete one character in front of cursor */ static void handle_delete(void) { int cur_tmp = cmd_cursor; /*when cursour at the end of string */ if (cmd_cursor >= cmd_strlen) return; /*delete one character from string */ strcpy(cmd_strp + cur_tmp, cmd_strp + cur_tmp + 1); cmd_strlen--; /*clear characters after cursor */ printf("\033[J"); /*re-print from delete position */ while (cmd_cursor < cmd_strlen) term_echo(); /*move cursor back to delete position */ cur_tmp = cmd_cursor - cur_tmp; while (cur_tmp--) cursor_backward(); }
/*print current output command*/ static void out_cmd_print(void) { cmd_strlen = strlen(history_buf[history_cur]); putchar('\r'); prompt_print(); while (cmd_cursor < cmd_strlen) term_echo(); /*clear characters after cursor */ printf("\033[J"); }
/* * update_input: does varying amount of updating on the input line depending * upon the position of the cursor and the update flag. If the cursor has * move toward one of the edge boundaries on the screen, update_cursor() * flips the input line to the next (previous) line of text. The update flag * may be: * * NO_UPDATE - only do the above bounds checking. * * UPDATE_JUST_CURSOR - do bounds checking and position cursor where is should * be. * * UPDATE_FROM_CURSOR - does all of the above, and makes sure everything from * the cursor to the right edge of the screen is current (by redrawing it). * * UPDATE_ALL - redraws the entire line */ void update_input (int update) { int old_zone; char *ptr, *ptr_free; int len, free_it = 0, max; char *prompt; int do_echo = 1; Screen *os = last_input_screen; Screen *ns; Window *saved_current_window = current_window; /* * No input line in dumb or bg mode. */ if (dumb_mode || !foreground) return; for (ns = screen_list; ns; ns = ns->next) { if (!ns->alive) continue; /* It's dead, Jim! */ last_input_screen = ns; current_window = ns->current_window; /* * Make sure the client thinks the cursor is on the input line. */ cursor_to_input(); /* * See if we're in a add_wait_prompt() call. If we are, grab that * current prompt, otherwise use the default input prompt. */ if (last_input_screen->promptlist) prompt = last_input_screen->promptlist->prompt; else prompt = input_prompt; /* * * GET THE INPUT PROMPT * */ /* * If we have a prompt, and we're supposed to update the input * prompt, then we do need to expand the prompt. */ if (prompt && update != NO_UPDATE) { int af; /* * If the current window is query'ing an exec'd process, * then we just get the current prompt for that process. * Note that it is not malloced. */ if (is_valid_process(get_target_by_refnum(0)) != -1) ptr = get_prompt_by_refnum(0); /* * Otherwise, we just expand the prompt as normal. */ else { ptr = expand_alias(prompt, empty_string, &af, NULL); free_it = 1; } /* * If we're in an add_wait_prompt(), we see whether or not * this is an "invisible" prompt. If it is, we turn off the * echo so what the user types doesnt show up. */ if (last_input_screen->promptlist) term_echo(last_input_screen->promptlist->echo); /* * Mangle out any ansi chars or so forth. */ ptr_free = ptr; ptr = normalize_string(ptr, 0); /* This should be ok */ if (free_it) new_free(&ptr_free); free_it = 1; /* * If the prompt has changed, or if there is no prompt... */ if ( (ptr && !INPUT_PROMPT) || (!ptr && INPUT_PROMPT) || strcmp(ptr, INPUT_PROMPT) ) { if (last_input_screen->input_prompt_malloc) new_free(&INPUT_PROMPT); last_input_screen->input_prompt_malloc = free_it; INPUT_PROMPT = ptr; INPUT_PROMPT_LEN = output_with_count(INPUT_PROMPT, 0, 0); update = UPDATE_ALL; } /* * Prompt didnt change, so clean up our mess */ else { if (free_it) new_free(&ptr); } } /* * * HAS THE SCREEN CHANGED SIZE SINCE THE LAST TIME? * */ /* * If the screen has resized, then we need to re-compute the * side-to-side scrolling effect. */ if ((last_input_screen->li != last_input_screen->old_li) || (last_input_screen->co != last_input_screen->old_co)) { /* * The input line is always the bottom line */ INPUT_LINE = last_input_screen->li - 1; /* * The "zone" is the range in which when you type, the * input line does not scroll. It is WIDTH chars in from * either side of the display. */ ZONE = last_input_screen->co - (WIDTH * 2); if (ZONE < 10) ZONE = 10; /* Take that! */ START_ZONE = WIDTH; END_ZONE = last_input_screen->co - WIDTH; last_input_screen->old_co = last_input_screen->co; last_input_screen->old_li = last_input_screen->li; } /* * About zones: * The input line is divided into "zones". A "zone" is set above, * and is the width of the screen minus 20 (by default). The input * line, as displayed, is therefore composed of the current "zone", * plus 10 characters from the previous zone, plus 10 characters * from the next zone. When the cursor moves to an adjacent zone, * (by going into column 9 from the right or left of the edge), the * input line is redrawn. There is one catch. The first "zone" * includes the first ten characters of the input line. */ old_zone = START_ZONE; /* * The BEGINNING of the current "zone" is a calculated value: * The number of characters since the origin of the input buffer * is the number of printable chars in the input prompt plus the * current position in the input buffer. We subtract from that * the WIDTH delta to take off the first delta, which doesnt * count towards the width of the zone. Then we divide that by * the size of the zone, to get an integer, then we multiply it * back. This gives us the first character on the screen. We * add WIDTH to the result in order to get the start of the zone * itself. * The END of the current "zone" is just the beginning plus the width. * If we have moved to an different "zone" since last time, we want to * completely redraw the input line. */ START_ZONE = ((INPUT_PROMPT_LEN + THIS_POS - WIDTH) / ZONE) * ZONE + WIDTH; END_ZONE = START_ZONE + ZONE; if (old_zone != START_ZONE) update = UPDATE_ALL; /* * Now that we know where the "zone" is in the input buffer, we can * easily calculate where where we want to start displaying stuff * from the INPUT_BUFFER. If we're in the first "zone", then we will * output from the beginning of the buffer. If we're not in the first * "zone", then we will begin to output from 10 characters to the * left of the zone, after adjusting for the length of the prompt. */ if (START_ZONE == WIDTH) INPUT_ONSCREEN = 0; else { if ((INPUT_ONSCREEN = START_ZONE - WIDTH - INPUT_PROMPT_LEN) < 0) INPUT_ONSCREEN = 0; } /* * And the cursor is simply how many characters away THIS_POS is * from the first column on the screen. */ if (INPUT_ONSCREEN == 0) INPUT_CURSOR = INPUT_PROMPT_LEN + THIS_POS; else INPUT_CURSOR = THIS_POS - INPUT_ONSCREEN; /* * If the cursor moved, or if we're supposed to do a full update, * then redraw the entire input line. */ if (update == UPDATE_ALL) { /* * Move the cursor to the start of the input line */ term_move_cursor(0, INPUT_LINE); /* * If the input line is NOT empty, and we're starting the * display at the beginning of the input buffer, then we * output the prompt first. */ if (INPUT_ONSCREEN == 0 && INPUT_PROMPT && *INPUT_PROMPT) { /* * Forcibly turn on echo. */ do_echo = term_echo(1); /* * Crop back the input prompt so it does not extend * past the end of the zone. */ if (INPUT_PROMPT_LEN > (last_input_screen->co - WIDTH)) INPUT_PROMPT_LEN = last_input_screen->co - WIDTH - 1; /* * Output the prompt. */ output_with_count(INPUT_PROMPT, 0, 1); /* * Turn the echo back to what it was before, * and output the rest of the input buffer. */ term_echo(do_echo); safe_puts(INPUT_BUFFER, last_input_screen->co - INPUT_PROMPT_LEN, do_echo); } /* * Otherwise we just output whatever we have. */ else if (do_echo) safe_puts(&(INPUT_VISIBLE), last_input_screen->co, do_echo); /* * Clear the rest of the input line and reset the cursor * to the current input position. */ term_clear_to_eol(); term_move_cursor(INPUT_CURSOR, INPUT_LINE); cursor_not_in_display(last_input_screen); } /* * If we're just supposed to refresh whats to the right of the * current logical position... */ else if (update == UPDATE_FROM_CURSOR) { /* * Move the cursor to where its supposed to be, * Figure out how much we can output from here, * and then output it. */ term_move_cursor(INPUT_CURSOR, INPUT_LINE); max = last_input_screen->co - (THIS_POS - INPUT_ONSCREEN); if (INPUT_ONSCREEN == 0 && INPUT_PROMPT && *INPUT_PROMPT) max -= INPUT_PROMPT_LEN; if ((len = strlen(&(THIS_CHAR))) > max) len = max; safe_puts(&(THIS_CHAR), len, do_echo); term_clear_to_eol(); term_move_cursor(INPUT_CURSOR, INPUT_LINE); cursor_not_in_display(last_input_screen); } /* * If we're just supposed to move the cursor back to the input * line, then go ahead and do that. */ else if (update == UPDATE_JUST_CURSOR) { term_move_cursor(INPUT_CURSOR, INPUT_LINE); cursor_not_in_display(last_input_screen); } /* * Turn the terminal echo back on, and flush all of the output * we may have done here. */ term_echo(1); term_flush(); } last_input_screen = os; current_window = saved_current_window; }
/*print help info*/ static void handle_help(void) { int pmatch_id = GCMD_DESC_NO_MATCH, pmatch_sub_id = GCMD_DESC_NO_MATCH, pmatch_act_id = GCMD_DESC_NO_MATCH; int cmd_nr = 0, pmatch_nr = 0, pmatch_sub_nr = 0; char *tmp_str[3], *cmd_strp_cp = strdup(cmd_strp); /* split command string into temp array */ tmp_str[cmd_nr] = (void *) strtok(cmd_strp_cp, " "); while (tmp_str[cmd_nr]) { if (++cmd_nr == 3) break; tmp_str[cmd_nr] = (void *) strtok(NULL, " "); } /*echo input ? */ printf("?\n"); int is_print = 0; /* print matched command */ switch (cmd_nr) { case 3: pmatch_nr = search_cmd_type(tmp_str[0], &pmatch_id, is_print); if(FULL_MATCHED(pmatch_nr, pmatch_id)) pmatch_sub_nr = search_cmd_sub(pmatch_id, &pmatch_sub_id, tmp_str[1], is_print); if(FULL_MATCHED(pmatch_sub_nr, pmatch_sub_id)) { is_print = 1; search_cmd_action(pmatch_id, &pmatch_act_id, tmp_str[1], tmp_str[2], is_print); } break; case 2: pmatch_nr = search_cmd_type(tmp_str[0], &pmatch_id, is_print); if(FULL_MATCHED(pmatch_nr, pmatch_id)) { is_print = 1; search_cmd_sub(pmatch_id, &pmatch_sub_id, tmp_str[1], is_print); } break; case 1: is_print = 1; pmatch_nr = search_cmd_type(tmp_str[0], &pmatch_id, is_print); if(NONE_MATCHED(pmatch_nr, pmatch_id)) { print_cmd_all(); } else if(FULL_MATCHED(pmatch_nr, pmatch_id)) { print_sub_all(pmatch_id); } break; case 0: print_cmd_all(); break; default: break; } printf("\n"); /* re-print prompt */ prompt_print(); /* re-print from cursor */ while (cmd_cursor < cmd_strlen) term_echo(); if(cmd_strp_cp) free(cmd_strp_cp); }
/* cursor move forward one character */ static void cursor_forward(void) { if (cmd_cursor < cmd_strlen) term_echo(); }
/* * update_input: does varying amount of updating on the input line depending * upon the position of the cursor and the update flag. If the cursor has * move toward one of the edge boundaries on the screen, update_cursor() * flips the input line to the next (previous) line of text. The update flag * may be: * * NO_UPDATE - only do the above bounds checking. * * UPDATE_JUST_CURSOR - do bounds checking and position cursor where is should * be. * * UPDATE_FROM_CURSOR - does all of the above, and makes sure everything from * the cursor to the right edge of the screen is current (by redrawing it). * * UPDATE_ALL - redraws the entire line */ void update_input(int update) { int old_start; static int co = 0, li = 0; char *ptr; int len, free_it = 1, cnt, ansi_count, max; char *prompt; cursor_to_input(); if (current_screen->promptlist) prompt = current_screen->promptlist->prompt; else prompt = input_prompt; if (prompt) { if (update != NO_UPDATE) { char *inp_ptr = NULL; int args_used; if (is_process(get_target_by_refnum(0))) { ptr = (char *) get_prompt_by_refnum(0); free_it = 0; } else if (!get_int_var(DISPLAY_ANSI_VAR)) ptr = expand_alias(stripansicodes(prompt), empty_str, &args_used, NULL); else ptr = expand_alias(prompt, empty_str, &args_used, NULL); if (*ptr && ((my_strnicmp(ptr, "Password:"******"Operator Password:"******"Server Password:", 16) == 0))) term_echo(0); else term_echo(1); len = strlen(ptr); if (strncmp(ptr, current_screen->input_buffer, len) || !len) { malloc_strcpy(&inp_ptr, INPUT_BUFFER + MIN_POS); strmcpy(INPUT_BUFFER, ptr, INPUT_BUFFER_SIZE); THIS_POS += (len - MIN_POS); MIN_POS = strlen(ptr); ADD_TO_INPUT(inp_ptr); new_free(&inp_ptr); update = UPDATE_ALL; } if (free_it) new_free(&ptr); } } else term_echo(1); if ((li != term_rows) || (co != term_cols)) { /* resized? Keep it simple and reset everything */ input_line = term_rows - 1; zone = term_cols - (WIDTH * 2) + 4; lower_mark = WIDTH; upper_mark = term_cols - WIDTH; cursor = current_screen->buffer_min_pos; current_screen->buffer_pos = current_screen->buffer_min_pos; str_start = 0; li = term_rows; co = term_cols; } old_start = str_start; ansi_count = count_ansi(current_screen->input_buffer, zone); if (old_ansi != ansi_count || current_screen->buffer_pos - ansi_count > zone) { lower_mark = WIDTH; upper_mark = term_cols - WIDTH; str_start = 0; } ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); while ((current_screen->buffer_pos - ansi_count < lower_mark) && lower_mark > WIDTH) { upper_mark = lower_mark - ansi_count; lower_mark -= (zone + ansi_count); str_start -= (zone + ansi_count); if (str_start < zone) { str_start = 0; ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); lower_mark -= ansi_count; upper_mark -= ansi_count; } } while (current_screen->buffer_pos - ansi_count >= upper_mark) { lower_mark = upper_mark + ansi_count; upper_mark += zone + ansi_count; str_start += zone + ansi_count; if (ansi_count) ansi_count = 0; } /* we need to count ansi characters again, this time in the part of the string we are gonna display in a few moments */ ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); old_ansi = count_ansi(current_screen->input_buffer, zone); /* we need to substract number of ansi characters from cursor position since those are not visible, otherwise we'd display cursor * in wrong place */ cursor = current_screen->buffer_pos - str_start - ansi_count; if ((old_start != str_start) || (update == UPDATE_ALL)) { term_move_cursor(0, input_line); if ((str_start == 0) && (MIN_POS > 0)) { int echo; echo = term_echo(1); if (MIN_POS > (term_cols - WIDTH)) len = term_cols - WIDTH - 1 /* + ansi_count */ ; else len = MIN_POS; cnt = /* term_puts */ safe_puts(&(INPUT_BUFFER[str_start]), len); term_echo(echo); cnt += /* term_puts */ safe_puts(&(current_screen->input_buffer[ str_start + len]), term_cols - len + ansi_count); } else cnt = /* term_puts */ safe_puts(&(INPUT_BUFFER[str_start]), term_cols); term_clear_to_eol(); term_move_cursor(cursor, input_line); } else if (update == UPDATE_FROM_CURSOR) { term_move_cursor(cursor, input_line); cnt = cursor; max = term_cols - (current_screen->buffer_pos - str_start) + ansi_count; if ((len = strlen(&(THIS_CHAR))) > max) len = max; cnt += /* term_puts */ safe_puts(&(THIS_CHAR), len); term_clear_to_eol(); term_move_cursor(cursor, input_line); } else if (update == UPDATE_JUST_CURSOR) term_move_cursor(cursor, input_line); term_flush(); }