csope/src/readline.c
2023-08-15 10:56:04 +02:00

180 lines
3.7 KiB
C

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "global.h"
#include "build.h"
#include <ncurses.h>
static int input_available = 0;
static int input_char;
char input_line[PATLEN + 1];
/* used for saving a line not [Enter]-ed yet,
* so its not lost if the user scrolls the history
*/
static struct PARTIAL_LINE {
bool is_active;
char* line;
int pos;
} partial_line = {
.line = NULL,
.is_active = true
};
static inline void previous_history_proxy(void);
static inline void next_history_proxy(void);
static inline int rebuild_reference(void);
bool interpret(int c) {
/* A switch is faster then binding Readline to a billion functions
* and since KEY_* values can't be bound anyways (values too large
* (because while the first argument of rl_bind_key() is an int,
* only unsigned chars are valid)), handling everything here
* creates consistency too.
*/
switch(c){
case KEY_BACKSPACE:
rl_rubout(1, 0);
break;
case KEY_UP:
previous_history_proxy();
break;
case KEY_DOWN:
next_history_proxy();
break;
case ctrl('R'):
rebuild_reference();
break;
case ESC:
case ctrl('X'):
process_mouse();
break;
default:
input_char = c;
input_available = 1;
rl_callback_read_char();
return 0;
}
//XXX:
// rl_bind_key(ctrl('\\'), /**/); /* bypass bindings */
window_change |= CH_INPUT;
return 0;
}
static int getc_function(FILE *ignore) {
UNUSED(ignore);
input_available = 0;
return input_char;
}
static int input_available_hook() {
return input_available;
}
static void redisplay_function() {
window_change |= CH_INPUT;
}
static void callback_handler(char *line) {
if(!line) { return; }
add_history(line);
switch(input_mode) {
case INPUT_NORMAL:
strncpy(input_line, line, PATLEN);
search(input_line);
horswp_field();
curdispline = 0;
current_page = 0;
PCS_reset();
break;
case INPUT_CHANGE_TO:
strncpy(newpat, line, PATLEN);
change = calloc(totallines, sizeof(*change));
input_mode = INPUT_CHANGE;
horswp_field();
return;
}
switch(field) {
case CHANGE:
input_mode = INPUT_CHANGE_TO;
break;
case DEFINITION:
case FILENAME:
if(totallines == 1) { editref(0); }
break;
}
}
static inline int rebuild_reference() {
if(isuptodate == true) {
postmsg("The -d option prevents rebuilding the symbol database");
return (false);
}
exitcurses();
freefilelist(); /* remake the source file list */
makefilelist();
rebuild();
if(errorsfound == true) {
errorsfound = false;
askforreturn();
}
entercurses();
postmsg(""); /* clear any previous message */
totallines = 0;
disprefs = 0;
return (true);
}
static inline void previous_history_proxy(){
HIST_ENTRY* i = previous_history();
if(i){
if(partial_line.is_active){
free(partial_line.line);
partial_line = (struct PARTIAL_LINE){
.line = rl_line_buffer,
.pos = rl_point,
.is_active = false
};
}else{
free(rl_line_buffer);
}
//
rl_line_buffer = strdup(i->line);
rl_point = strlen(rl_line_buffer);
}
}
static inline void next_history_proxy(){
HIST_ENTRY* i = next_history();
if(i){
free(rl_line_buffer);
rl_line_buffer = strdup(i->line);
rl_point = strlen(rl_line_buffer);
}else if(!partial_line.is_active){
rl_line_buffer = strdup(partial_line.line);
rl_point = partial_line.pos;
partial_line.is_active = true;
}
}
void rlinit() {
using_history();
rl_catch_signals = 0;
rl_catch_sigwinch = 0;
rl_prep_term_function = NULL;
rl_deprep_term_function = NULL;
rl_change_environment = 0;
rl_getc_function = getc_function;
rl_input_available_hook = input_available_hook;
rl_redisplay_function = redisplay_function;
rl_callback_handler_install("", callback_handler);
}