2023-08-04 13:12:06 -04:00
|
|
|
#include <stdio.h>
|
2023-08-01 13:36:53 -04:00
|
|
|
#include <readline/readline.h>
|
2023-08-15 04:56:04 -04:00
|
|
|
#include <readline/history.h>
|
2023-08-01 13:36:53 -04:00
|
|
|
#include "global.h"
|
2023-08-04 13:12:06 -04:00
|
|
|
#include "build.h"
|
2023-08-04 16:35:56 -04:00
|
|
|
#include <ncurses.h>
|
2023-08-01 13:36:53 -04:00
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
static int input_available = 0;
|
2023-08-15 04:56:04 -04:00
|
|
|
static int input_char;
|
2023-08-13 05:21:52 -04:00
|
|
|
char input_line[PATLEN + 1];
|
2023-08-15 13:03:32 -04:00
|
|
|
|
2023-08-15 04:56:04 -04:00
|
|
|
/* 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);
|
|
|
|
|
2023-08-04 13:12:06 -04:00
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
bool interpret(int c) {
|
2023-08-15 04:56:04 -04:00
|
|
|
/* 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 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 */
|
2023-08-04 13:12:06 -04:00
|
|
|
|
2023-08-15 04:56:04 -04:00
|
|
|
window_change |= CH_INPUT;
|
2023-08-13 05:21:52 -04:00
|
|
|
return 0;
|
2023-08-04 13:12:06 -04:00
|
|
|
}
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
static int getc_function(FILE *ignore) {
|
2023-08-09 07:49:11 -04:00
|
|
|
UNUSED(ignore);
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
input_available = 0;
|
2023-08-15 04:56:04 -04:00
|
|
|
return input_char;
|
2023-08-01 13:36:53 -04:00
|
|
|
}
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
static int input_available_hook() {
|
|
|
|
return input_available;
|
2023-08-01 13:36:53 -04:00
|
|
|
}
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
static void redisplay_function() {
|
|
|
|
window_change |= CH_INPUT;
|
2023-08-01 13:36:53 -04:00
|
|
|
}
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
static void callback_handler(char *line) {
|
2023-09-02 17:09:16 -04:00
|
|
|
if(!line) {
|
|
|
|
input_mode = INPUT_NORMAL;
|
|
|
|
return;
|
|
|
|
}
|
2023-08-08 14:34:15 -04:00
|
|
|
|
2023-08-15 04:56:04 -04:00
|
|
|
add_history(line);
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
switch(input_mode) {
|
2023-09-02 13:40:35 -04:00
|
|
|
case INPUT_NORMAL: {
|
2023-08-13 05:21:52 -04:00
|
|
|
strncpy(input_line, line, PATLEN);
|
2023-08-10 15:06:17 -04:00
|
|
|
search(input_line);
|
2023-08-16 06:14:09 -04:00
|
|
|
horswp_window();
|
2023-08-10 15:06:17 -04:00
|
|
|
curdispline = 0;
|
|
|
|
current_page = 0;
|
2023-08-13 15:22:44 -04:00
|
|
|
PCS_reset();
|
2023-09-02 13:40:35 -04:00
|
|
|
} break;
|
|
|
|
case INPUT_CHANGE_TO: {
|
2023-08-13 05:21:52 -04:00
|
|
|
strncpy(newpat, line, PATLEN);
|
|
|
|
change = calloc(totallines, sizeof(*change));
|
2023-08-10 15:06:17 -04:00
|
|
|
input_mode = INPUT_CHANGE;
|
2023-08-16 09:00:06 -04:00
|
|
|
force_window();
|
2023-09-02 13:40:35 -04:00
|
|
|
} return;
|
2023-08-16 06:14:09 -04:00
|
|
|
case INPUT_APPEND: {
|
|
|
|
char filename[PATHLEN + 1];
|
|
|
|
FILE* file;
|
|
|
|
char ch;
|
|
|
|
shellpath(filename, sizeof(filename), line);
|
|
|
|
file = fopen(filename, "a+");
|
|
|
|
seekpage(0);
|
|
|
|
while ((ch = getc(refsfound)) != EOF) {
|
|
|
|
putc(ch, file);
|
|
|
|
}
|
|
|
|
fclose(file);
|
|
|
|
input_mode = INPUT_NORMAL;
|
2023-09-02 13:40:35 -04:00
|
|
|
} return;
|
|
|
|
case INPUT_READ: {
|
|
|
|
char filename[PATHLEN + 1];
|
|
|
|
shellpath(filename, sizeof(filename), line);
|
|
|
|
if (!readrefs(filename)) {
|
|
|
|
postmsg("Ignoring an empty file");
|
|
|
|
}
|
|
|
|
window_change |= CH_INPUT | CH_RESULT;
|
|
|
|
input_mode = INPUT_NORMAL;
|
|
|
|
} return;
|
2023-08-10 08:36:16 -04:00
|
|
|
}
|
2023-08-09 07:49:11 -04:00
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
switch(field) {
|
2023-08-10 08:36:16 -04:00
|
|
|
case CHANGE:
|
2023-08-16 06:14:09 -04:00
|
|
|
if(totallines == 0){ return; }
|
2023-08-10 15:06:17 -04:00
|
|
|
input_mode = INPUT_CHANGE_TO;
|
2023-09-02 17:09:16 -04:00
|
|
|
force_window();
|
2023-08-10 08:36:16 -04:00
|
|
|
break;
|
|
|
|
case DEFINITION:
|
|
|
|
case FILENAME:
|
2023-08-13 05:21:52 -04:00
|
|
|
if(totallines == 1) { editref(0); }
|
2023-08-10 08:36:16 -04:00
|
|
|
break;
|
2023-08-09 07:49:11 -04:00
|
|
|
}
|
2023-08-01 13:36:53 -04:00
|
|
|
}
|
|
|
|
|
2023-08-15 04:56:04 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
void rlinit() {
|
2023-08-15 13:03:32 -04:00
|
|
|
rl_readline_name = PROGRAM_NAME;
|
|
|
|
|
2023-08-15 04:56:04 -04:00
|
|
|
using_history();
|
|
|
|
|
2023-08-13 05:21:52 -04:00
|
|
|
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);
|
2023-08-01 13:36:53 -04:00
|
|
|
}
|