void handle_out_of_band(int tag, char *message) { int split_em_up = FALSE; switch (tag) { case TAG_ERROR: if (expected_tag == TAG_COMPLETION) /* start new line when completing (looks better) */ fprintf(stderr, "\n"); /* @@@ error reporting (still) uses bufered I/O */ myerror(FATAL|NOERRNO, message); case TAG_OUTPUT_OUT_OF_BAND: my_putstr(message); break; case TAG_ADD_TO_COMPLETION_LIST: case TAG_REMOVE_FROM_COMPLETION_LIST: split_em_up = TRUE; break; case TAG_IGNORE: break; default: myerror(FATAL|USE_ERRNO, "out-of-band message with unknown tag %d: <%20s>", tag, message); } if (split_em_up) { char **words = split_with(message, " \n\t"); char **plist, *word; for(plist = words; (word = *plist); plist++) if (tag == TAG_ADD_TO_COMPLETION_LIST) add_word_to_completions(word); else remove_word_from_completions(word); free_splitlist(words); } free(message); }
static int handle_hotkey2(int UNUSED(count), int hotkey, int ignore_history) { char *prefix, *postfix, *history, *histpos_as_string, *executing_keyseq; char *new_prefix, *new_postfix, *new_history, *new_histpos_as_string, *message; char *filter_food, *filtered, **fragments, *new_rl_line_buffer; int length, new_histpos; unsigned long int hash; static const unsigned int MAX_HISTPOS_DIGITS = 6; /* one million history items should suffice */ #ifdef HAVE_RL_EXECUTING_KEYSEQ /* i.e. if readline version is >= 6.3 */ executing_keyseq = mysavestring(rl_executing_keyseq); #else executing_keyseq = mysavestring("?"); *executing_keyseq = hotkey; /* The filter will only get the *last* byte of the key sequence that triggered rl_handle_hotkey */ #endif DPRINTF3(DEBUG_READLINE, "hotkey press (ignore_history == %d): %x (%s)", ignore_history, hotkey, mangle_string_for_debug_log(executing_keyseq, MANGLE_LENGTH)); if (hotkey == '\t') /* this would go horribly wrong with all the splitting on '\t' going on.... @@@ or pass key as a string e.g. "009" */ myerror(FATAL | NOERRNO, "Sorry, you cannot use TAB as an hotkey in rlwrap"); prefix = mysavestring(rl_line_buffer); prefix[rl_point] = '\0'; /* chop off just before cursor */ postfix = mysavestring(rl_line_buffer + rl_point); if (ignore_history) { histpos_as_string = mysavestring("0"); history = mysavestring(""); } else { histpos_as_string = as_string(where_history()); assert(strlen(histpos_as_string) <= MAX_HISTPOS_DIGITS); history = entire_history_as_one_string(); hash = hash_multiple(2, history, histpos_as_string); } /* filter_food = key + tab + prefix + tab + postfix + tab + history + tab + histpos + '\0' */ length = strlen(rl_line_buffer) + strlen(history) + MAX_HISTPOS_DIGITS + 5; filter_food = mymalloc(length); sprintf(filter_food, "%s\t%s\t%s\t%s\t%s", executing_keyseq, prefix, postfix, history, histpos_as_string); /* this is the format that the filter expects */ /* let the filter filter ...! */ filtered= pass_through_filter(TAG_HOTKEY, filter_food); /* OK, we now have to read back everything. There should be exactly 5 TAB-separated components*/ fragments = split_on_single_char(filtered, '\t', 5); message = fragments[0]; new_prefix = fragments[1]; new_postfix = fragments[2]; new_history = fragments[3]; new_histpos_as_string = fragments[4]; if (!ignore_history && hash_multiple(2, new_history, new_histpos_as_string) != hash) { /* history has been rewritten */ char **linep, **history_lines = split_on_single_char(new_history, '\n', 0); DPRINTF3(DEBUG_READLINE, "hash=%lx, new_history is %d bytes long, histpos <%s>", hash, (int) strlen(new_history), new_histpos_as_string); clear_history(); for (linep = history_lines; *linep; linep++) add_history(*linep); new_histpos = my_atoi(new_histpos_as_string); history_set_pos(new_histpos); free_splitlist(history_lines); } new_rl_line_buffer = add2strings(new_prefix, new_postfix); if ( (length = strlen(new_rl_line_buffer)) > 0 && new_rl_line_buffer[length - 1] == '\n') { new_rl_line_buffer[length - 1] = '\0'; rl_done = TRUE; return_key = (char) '\n'; assert(strchr(new_rl_line_buffer, '\n') == NULL); } rl_delete_text(0, strlen(rl_line_buffer)); rl_point = 0; rl_insert_text(new_rl_line_buffer); rl_point = strlen(new_rl_line_buffer); if (*message && *message != hotkey) { /* if message has been set (i.e. != hotkey) , and isn't empty: */ message = append_and_free_old(mysavestring(message), " "); /* put space (for readability) between the message and the input line .. */ message_in_echo_area(message); /* .. then write it to echo area */ } clear_line(); rl_on_new_line(); rl_redisplay(); free_splitlist(fragments); /* this will free all the fragments (and the list itself) in one go */ free_multiple(prefix, postfix, filter_food, executing_keyseq, filtered, new_rl_line_buffer, history, histpos_as_string, FMEND); return 0; }