small change for highlihting flags, more busyboxes: indent, forward declaration, paste BSS
This commit was genuinely broken at the time (not related to our build system): scripts/config/mkconfigs.c (2005-08-01 - 2006-10-05 arasi) uretilen bbconfigopts.h icine .config satirlarini kacissiz, ham newline'larla gömüyordu - gecerli C degildi, busybox'un kendi bb_mkdep araci bile parse edemiyordu (7d219aab7 ile duzeltildi, mkconfigs shell scripte cevrildi)
No binary (build failed)
—
(log yok)
| @@ -23,7 +23,7 @@ | |
| * This program needs a lot of development, so consider it in a beta stage | |
| * at best. | |
| * | |
| - | * TODO: |
| + | * TODO: |
| * - Add more regular expression support - search modifiers, certain matches, etc. | |
| * - Add more complex bracket searching - currently, nested brackets are | |
| * not considered. | |
| @@ -47,10 +47,15 @@ | |
| #include <string.h> | |
| #include <termios.h> | |
| #include <unistd.h> | |
| - | #include <regex.h> |
| #include <ctype.h> | |
| + | |
| #include "busybox.h" | |
| + | #ifdef CONFIG_FEATURE_LESS_REGEXP |
| + | #include "xregex.h" |
| + | #endif |
| + | |
| + | |
| /* These are the escape sequences corresponding to special keys */ | |
| #define REAL_KEY_UP 'A' | |
| #define REAL_KEY_DOWN 'B' | |
| @@ -78,63 +83,7 @@ | |
| #define MAXLINES 10000 | |
| /* Get height and width of terminal */ | |
| - | #define tty_width_height() get_terminal_width_height(0, &width, &height) |
| - | |
| - | /* Function prototypes */ |
| - | static void set_tty_cooked(void); |
| - | static void set_tty_raw(void); |
| - | static void tless_exit(int code); |
| - | static int tless_getch(void); |
| - | static void move_cursor(int x, int y); |
| - | static void clear_line(void); |
| - | static void data_readlines(void); |
| - | static void free_flines(void); |
| - | #ifdef CONFIG_FEATURE_LESS_FLAGS |
| - | static int calc_percent(void); |
| - | #endif |
| - | static int reverse_percent(int percentage); |
| - | #ifdef CONFIG_FEATURE_LESS_FLAGS |
| - | static void m_status_print(void); |
| - | static void medium_status_print(void); |
| - | #endif |
| - | static void status_print(void); |
| - | static void buffer_print(void); |
| - | static void buffer_init(void); |
| - | static void buffer_down(int nlines); |
| - | static void buffer_up(int nlines); |
| - | static void buffer_line(int linenum); |
| - | static void keypress_process(int keypress); |
| - | static void colon_process(void); |
| - | static void number_process(int first_digit); |
| - | #ifdef CONFIG_FEATURE_LESS_FLAGCS |
| - | static void flag_change(void); |
| - | static void show_flag_status(void); |
| - | #endif |
| - | static void examine_file(void); |
| - | static void next_file(void); |
| - | static void previous_file(void); |
| - | static void first_file(void); |
| - | static void remove_current_file(void); |
| - | static void full_repaint(void); |
| - | static void add_linenumbers(void); |
| - | static void save_input_to_file(void); |
| - | #ifdef CONFIG_FEATURE_LESS_MARKS |
| - | static void add_mark(void); |
| - | static void goto_mark(void); |
| - | #endif |
| - | #ifdef CONFIG_FEATURE_LESS_REGEXP |
| - | static void regex_process(void); |
| - | char *process_regex_on_line(char *line, regex_t *pattern); |
| - | char *insert_highlights(char *line, int start, int end); |
| - | static void goto_match (int match); |
| - | static void search_backwards(void); |
| - | #endif |
| - | #ifdef CONFIG_FEATURE_LESS_BRACKETS |
| - | static char opp_bracket (char bracket); |
| - | static void match_right_bracket (char bracket); |
| - | static void match_left_bracket (char bracket); |
| - | #endif |
| - | int less_main(int argc, char *argv[]); |
| + | #define tty_width_height() get_terminal_width_height(0, &width, &height) |
| static int height; | |
| static int width; | |
| @@ -143,38 +92,38 @@ static char filename[256]; | |
| static char buffer[100][256]; | |
| static char *flines[MAXLINES]; | |
| static int current_file = 1; | |
| - | static int line_pos = 0; |
| + | static int line_pos; |
| static int num_flines; | |
| static int num_files = 1; | |
| - | static int past_eof = 0; |
| + | static int past_eof; |
| /* Command line options */ | |
| - | static int E_FLAG = 0; |
| - | static int M_FLAG = 0; |
| - | static int N_FLAG = 0; |
| - | static int m_FLAG = 0; |
| - | static int TILDE_FLAG = 0; |
| + | static int E_FLAG; |
| + | static int M_FLAG; |
| + | static int N_FLAG; |
| + | static int m_FLAG; |
| + | static int TILDE_FLAG; |
| /* This is needed so that program behaviour changes when input comes from | |
| stdin */ | |
| - | static int inp_stdin = 0; |
| + | static int inp_stdin; |
| /* This is required so that when a file is requested to be examined after | |
| - | input has come from stdin (e.g. dmesg | less), the input stream from |
| + | input has come from stdin (e.g. dmesg | less), the input stream from |
| the keyboard still stays the same. If it switched back to stdin, keyboard | |
| input wouldn't work. */ | |
| - | static int ea_inp_stdin = 0; |
| + | static int ea_inp_stdin; |
| #ifdef CONFIG_FEATURE_LESS_MARKS | |
| static int mark_lines[15][2]; | |
| - | static int num_marks = 0; |
| + | static int num_marks; |
| #endif | |
| #ifdef CONFIG_FEATURE_LESS_REGEXP | |
| - | static int match_found = 0; |
| + | static int match_found; |
| static int match_lines[100]; | |
| - | static int match_pos = 0; |
| - | static int num_matches = 0; |
| - | static int match_backwards = 0; |
| + | static int match_pos; |
| + | static int num_matches; |
| + | static int match_backwards; |
| static int num_back_match = 1; | |
| #endif | |
| @@ -185,47 +134,47 @@ static struct termios term_orig, term_vi; | |
| static FILE *inp; | |
| /* Reset terminal input to normal */ | |
| - | static void set_tty_cooked() { |
| - | fflush(stdout); |
| - | tcsetattr(0, TCSANOW, &term_orig); |
| + | static void set_tty_cooked(void) { |
| + | fflush(stdout); |
| + | tcsetattr(0, TCSANOW, &term_orig); |
| } | |
| /* Set terminal input to raw mode */ | |
| - | static void set_tty_raw() { |
| + | static void set_tty_raw(void) { |
| tcgetattr(0, &term_orig); | |
| - | term_vi = term_orig; |
| - | term_vi.c_lflag &= (~ICANON & ~ECHO); |
| - | term_vi.c_iflag &= (~IXON & ~ICRNL); |
| - | term_vi.c_oflag &= (~ONLCR); |
| - | term_vi.c_cc[VMIN] = 1; |
| - | term_vi.c_cc[VTIME] = 0; |
| - | tcsetattr(0, TCSANOW, &term_vi); |
| + | term_vi = term_orig; |
| + | term_vi.c_lflag &= (~ICANON & ~ECHO); |
| + | term_vi.c_iflag &= (~IXON & ~ICRNL); |
| + | term_vi.c_oflag &= (~ONLCR); |
| + | term_vi.c_cc[VMIN] = 1; |
| + | term_vi.c_cc[VTIME] = 0; |
| + | tcsetattr(0, TCSANOW, &term_vi); |
| } | |
| /* Exit the program gracefully */ | |
| static void tless_exit(int code) { | |
| - | |
| + | |
| /* TODO: We really should save the terminal state when we start, | |
| - | and restore it when we exit. Less does this with the |
| + | and restore it when we exit. Less does this with the |
| "ti" and "te" termcap commands; can this be done with | |
| only termios.h? */ | |
| - | |
| + | |
| putchar('\n'); | |
| exit(code); | |
| } | |
| /* Grab a character from input without requiring the return key. If the | |
| character is ASCII \033, get more characters and assign certain sequences | |
| - | special return codes. Note that this function works best with raw input. */ |
| - | int tless_getch() { |
| - | |
| + | special return codes. Note that this function works best with raw input. */ |
| + | static int tless_getch(void) { |
| + | |
| set_tty_raw(); | |
| char input_key[3]; | |
| - | |
| + | |
| input_key[0] = getc(inp); | |
| /* Detect escape sequences (i.e. arrow keys) and handle | |
| them accordingly */ | |
| - | |
| + | |
| if (input_key[0] == '\033') { | |
| input_key[1] = getc(inp); | |
| input_key[2] = getc(inp); | |
| @@ -253,25 +202,38 @@ int tless_getch() { | |
| return 0; | |
| } | |
| - | /* Move the cursor to a position (x,y), where (0,0) is the |
| + | /* Move the cursor to a position (x,y), where (0,0) is the |
| top-left corner of the console */ | |
| static void move_cursor(int x, int y) { | |
| printf("\033[%i;%iH", x, y); | |
| } | |
| - | static void clear_line() { |
| + | static void clear_line(void) { |
| move_cursor(height, 0); | |
| printf("\033[K"); | |
| } | |
| - | static void data_readlines() { |
| - | |
| + | /* This adds line numbers to every line, as the -N flag necessitates */ |
| + | static void add_linenumbers(void) { |
| + | |
| + | char current_line[256]; |
| + | int i; |
| + | |
| + | for (i = 0; i <= num_flines; i++) { |
| + | safe_strncpy(current_line, flines[i], 256); |
| + | flines[i] = xrealloc(flines[i], strlen(current_line) + 7 ); |
| + | sprintf(flines[i],"%5d %s", i+1, current_line); |
| + | } |
| + | } |
| + | |
| + | static void data_readlines(void) { |
| + | |
| int i; | |
| char current_line[256]; | |
| FILE *fp; | |
| - | |
| + | |
| fp = (inp_stdin) ? stdin : bb_xfopen(filename, "rt"); | |
| - | |
| + | |
| for (i = 0; (!feof(fp)) && (i <= MAXLINES); i++) { | |
| strcpy(current_line, ""); | |
| fgets(current_line, 256, fp); | |
| @@ -281,10 +243,10 @@ static void data_readlines() { | |
| num_flines = i - 2; | |
| /* Reset variables for a new file */ | |
| - | |
| + | |
| line_pos = 0; | |
| past_eof = 0; | |
| - | |
| + | |
| fclose(fp); | |
| if (inp_stdin) | |
| @@ -296,29 +258,29 @@ static void data_readlines() { | |
| fclose(inp); | |
| inp = fopen(CURRENT_TTY, "r"); | |
| } | |
| - | |
| + | |
| if (N_FLAG) | |
| add_linenumbers(); | |
| } | |
| /* Free the file data */ | |
| - | static void free_flines() { |
| - | |
| + | static void free_flines(void) { |
| + | |
| int i; | |
| - | |
| + | |
| for (i = 0; i <= num_flines; i++) | |
| free(flines[i]); | |
| } | |
| #ifdef CONFIG_FEATURE_LESS_FLAGS | |
| /* Calculate the percentage the current line position is through the file */ | |
| - | int calc_percent() { |
| + | static int calc_percent(void) { |
| return ((100 * (line_pos + height - 2) / num_flines) + 1); | |
| } | |
| #endif | |
| /* Turn a percentage into a line number */ | |
| - | int reverse_percent(int percentage) { |
| + | static int reverse_percent(int percentage) { |
| double linenum = percentage; | |
| linenum = ((linenum / 100) * num_flines) - 1; | |
| return(linenum); | |
| @@ -326,10 +288,10 @@ int reverse_percent(int percentage) { | |
| #ifdef CONFIG_FEATURE_LESS_FLAGS | |
| /* Print a status line if -M was specified */ | |
| - | static void m_status_print() { |
| + | static void m_status_print(void) { |
| int percentage; | |
| - | |
| + | |
| if (!past_eof) { | |
| if (!line_pos) { | |
| if (num_files > 1) | |
| @@ -341,7 +303,7 @@ static void m_status_print() { | |
| else { | |
| printf("%s %s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1); | |
| } | |
| - | |
| + | |
| if (line_pos == num_flines - height + 2) { | |
| printf("(END) %s", NORMAL); | |
| if ((num_files > 1) && (current_file != num_files)) | |
| @@ -361,11 +323,11 @@ static void m_status_print() { | |
| } | |
| /* Print a status line if -m was specified */ | |
| - | static void medium_status_print() { |
| + | static void medium_status_print(void) { |
| int percentage; | |
| percentage = calc_percent(); | |
| - | |
| + | |
| if (!line_pos) | |
| printf("%s%s %i%s%s", HIGHLIGHT, filename, percentage, "%", NORMAL); | |
| else if (line_pos == num_flines - height + 2) | |
| @@ -376,11 +338,11 @@ static void medium_status_print() { | |
| #endif | |
| /* Print the status line */ | |
| - | static void status_print() { |
| - | |
| + | static void status_print(void) { |
| + | |
| /* Change the status if flags have been set */ | |
| - | #ifdef CONFIG_FEATURE_LESS_FLAGS |
| - | if (M_FLAG) |
| + | #ifdef CONFIG_FEATURE_LESS_FLAGS |
| + | if (M_FLAG) |
| m_status_print(); | |
| else if (m_FLAG) | |
| medium_status_print(); | |
| @@ -406,10 +368,10 @@ static void status_print() { | |
| } | |
| /* Print the buffer */ | |
| - | static void buffer_print() { |
| - | |
| + | static void buffer_print(void) { |
| + | |
| int i; | |
| - | |
| + | |
| if (num_flines >= height - 2) { | |
| printf("%s", CLEAR); | |
| move_cursor(0,0); | |
| @@ -429,19 +391,19 @@ static void buffer_print() { | |
| } | |
| /* Initialise the buffer */ | |
| - | static void buffer_init() { |
| - | |
| + | static void buffer_init(void) { |
| + | |
| int i; | |
| - | |
| + | |
| for (i = 0; i < (height - 1); i++) | |
| memset(buffer[i], '\0', 256); | |
| - | |
| - | /* Fill the buffer until the end of the file or the |
| + | |
| + | /* Fill the buffer until the end of the file or the |
| end of the buffer is reached */ | |
| for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) { | |
| strcpy(buffer[i], flines[i]); | |
| } | |
| - | |
| + | |
| /* If the buffer still isn't full, fill it with blank lines */ | |
| for (; i < (height - 1); i++) { | |
| strcpy(buffer[i], ""); | |
| @@ -450,9 +412,9 @@ static void buffer_init() { | |
| /* Move the buffer up and down in the file in order to scroll */ | |
| static void buffer_down(int nlines) { | |
| - | |
| + | |
| int i; | |
| - | |
| + | |
| if (!past_eof) { | |
| if (line_pos + (height - 3) + nlines < num_flines) { | |
| line_pos += nlines; | |
| @@ -461,8 +423,8 @@ static void buffer_down(int nlines) { | |
| } | |
| else { | |
| /* As the number of lines requested was too large, we just move | |
| - | to the end of the file */ |
| - | while (line_pos + (height - 3) + 1 < num_flines) { |
| + | to the end of the file */ |
| + | while (line_pos + (height - 3) + 1 < num_flines) { |
| line_pos += 1; | |
| for (i = 0; i < (height - 1); i++) | |
| strcpy(buffer[i], flines[line_pos + i]); | |
| @@ -476,10 +438,10 @@ static void buffer_down(int nlines) { | |
| } | |
| static void buffer_up(int nlines) { | |
| - | |
| + | |
| int i; | |
| int tilde_line; | |
| - | |
| + | |
| if (!past_eof) { | |
| if (line_pos - nlines >= 0) { | |
| line_pos -= nlines; | |
| @@ -499,7 +461,7 @@ static void buffer_up(int nlines) { | |
| else { | |
| /* Work out where the tildes start */ | |
| tilde_line = num_flines - line_pos + 3; | |
| - | |
| + | |
| line_pos -= nlines; | |
| /* Going backwards nlines lines has taken us to a point where | |
| nothing is past the EOF, so we revert to normal. */ | |
| @@ -509,7 +471,7 @@ static void buffer_up(int nlines) { | |
| } | |
| else { | |
| /* We only move part of the buffer, as the rest | |
| - | is past the EOF */ |
| + | is past the EOF */ |
| for (i = 0; i < (height - 1); i++) { | |
| if (i < tilde_line - nlines + 1) | |
| strcpy(buffer[i], flines[line_pos + i]); | |
| @@ -518,12 +480,12 @@ static void buffer_up(int nlines) { | |
| strcpy(buffer[i], "~\n"); | |
| } | |
| } | |
| - | } |
| + | } |
| } | |
| } | |
| static void buffer_line(int linenum) { | |
| - | |
| + | |
| int i; | |
| past_eof = 0; | |
| @@ -550,125 +512,103 @@ static void buffer_line(int linenum) { | |
| } | |
| } | |
| - | static void keypress_process(int keypress) { |
| - | switch (keypress) { |
| - | case KEY_DOWN: case 'e': case 'j': case '\015': |
| - | buffer_down(1); |
| - | buffer_print(); |
| - | break; |
| - | case KEY_UP: case 'y': case 'k': |
| - | buffer_up(1); |
| - | buffer_print(); |
| - | break; |
| - | case PAGE_DOWN: case ' ': case 'z': |
| - | buffer_down(height - 1); |
| - | buffer_print(); |
| - | break; |
| - | case PAGE_UP: case 'w': case 'b': |
| - | buffer_up(height - 1); |
| - | buffer_print(); |
| - | break; |
| - | case 'd': |
| - | buffer_down((height - 1) / 2); |
| - | buffer_print(); |
| - | break; |
| - | case 'u': |
| - | buffer_up((height - 1) / 2); |
| - | buffer_print(); |
| - | break; |
| - | case 'g': case 'p': case '<': case '%': |
| - | buffer_up(num_flines + 1); |
| - | buffer_print(); |
| - | break; |
| - | case 'G': case '>': |
| - | buffer_down(num_flines + 1); |
| - | buffer_print(); |
| - | break; |
| - | case 'q': case 'Q': |
| - | tless_exit(0); |
| - | break; |
| - | #ifdef CONFIG_FEATURE_LESS_MARKS |
| - | case 'm': |
| - | add_mark(); |
| - | buffer_print(); |
| - | break; |
| - | case '\'': |
| - | goto_mark(); |
| - | buffer_print(); |
| - | break; |
| - | #endif |
| - | case 'r': |
| - | buffer_print(); |
| - | break; |
| - | case 'R': |
| - | full_repaint(); |
| - | break; |
| - | case 's': |
| - | if (inp_stdin) |
| - | save_input_to_file(); |
| - | break; |
| - | case 'E': |
| - | examine_file(); |
| - | break; |
| - | #ifdef CONFIG_FEATURE_LESS_FLAGS |
| - | case '=': |
| - | clear_line(); |
| - | m_status_print(); |
| - | break; |
| - | #endif |
| - | #ifdef CONFIG_FEATURE_LESS_REGEXP |
| - | case '/': |
| - | regex_process(); |
| - | buffer_print(); |
| - | break; |
| - | case 'n': |
| - | goto_match(match_pos + 1); |
| - | buffer_print(); |
| - | break; |
| - | case 'N': |
| - | goto_match(match_pos - 1); |
| - | buffer_print(); |
| - | break; |
| - | case '?': |
| - | search_backwards(); |
| - | buffer_print(); |
| - | break; |
| - | #endif |
| - | #ifdef CONFIG_FEATURE_LESS_FLAGCS |
| - | case '-': |
| - | flag_change(); |
| - | buffer_print(); |
| - | break; |
| - | case '_': |
| - | show_flag_status(); |
| - | break; |
| - | #endif |
| - | #ifdef CONFIG_FEATURE_LESS_BRACKETS |
| - | case '{': case '(': case '[': |
| - | match_right_bracket(keypress); |
| - | break; |
| - | case '}': case ')': case ']': |
| - | match_left_bracket(keypress); |
| - | break; |
| - | #endif |
| - | case ':': |
| - | colon_process(); |
| - | break; |
| - | default: |
| - | break; |
| + | static void examine_file(void) { |
| + | |
| + | int newline_offset; |
| + | |
| + | clear_line(); |
| + | printf("Examine: "); |
| + | fgets(filename, 256, inp); |
| + | |
| + | /* As fgets adds a newline to the end of an input string, we |
| + | need to remove it */ |
| + | newline_offset = strlen(filename) - 1; |
| + | filename[newline_offset] = '\0'; |
| + | |
| + | files[num_files] = bb_xstrndup(filename, (strlen(filename) + 1) * sizeof(char)); |
| + | current_file = num_files + 1; |
| + | num_files++; |
| + | |
| + | inp_stdin = 0; |
| + | ea_inp_stdin = 1; |
| + | free_flines(); |
| + | data_readlines(); |
| + | buffer_init(); |
| + | buffer_print(); |
| + | } |
| + | |
| + | |
| + | static void next_file(void) { |
| + | if (current_file != num_files) { |
| + | current_file++; |
| + | strcpy(filename, files[current_file - 1]); |
| + | free_flines(); |
| + | data_readlines(); |
| + | buffer_init(); |
| + | buffer_print(); |
| + | } |
| + | else { |
| + | clear_line(); |
| + | printf("%s%s%s", HIGHLIGHT, "No next file", NORMAL); |
| + | } |
| + | } |
| + | |
| + | static void previous_file(void) { |
| + | if (current_file != 1) { |
| + | current_file--; |
| + | strcpy(filename, files[current_file - 1]); |
| + | |
| + | free_flines(); |
| + | data_readlines(); |
| + | buffer_init(); |
| + | buffer_print(); |
| + | } |
| + | else { |
| + | clear_line(); |
| + | printf("%s%s%s", HIGHLIGHT, "No previous file", NORMAL); |
| + | } |
| + | } |
| + | |
| + | static void first_file(void) { |
| + | if (current_file != 1) { |
| + | current_file = 1; |
| + | strcpy(filename, files[current_file - 1]); |
| + | free_flines(); |
| + | data_readlines(); |
| + | buffer_init(); |
| + | buffer_print(); |
| + | } |
| + | } |
| + | |
| + | static void remove_current_file(void) { |
| + | |
| + | int i; |
| + | |
| + | if (current_file != 1) { |
| + | previous_file(); |
| + | for (i = 3; i <= num_files; i++) |
| + | files[i - 2] = files[i - 1]; |
| + | num_files--; |
| + | buffer_print(); |
| + | } |
| + | else { |
| + | next_file(); |
| + | for (i = 2; i <= num_files; i++) |
| + | files[i - 2] = files[i - 1]; |
| + | num_files--; |
| + | current_file--; |
| + | buffer_print(); |
| } | |
| - | if (isdigit(keypress)) |
| - | number_process(keypress); |
| } | |
| - | static void colon_process() { |
| - | |
| + | static void colon_process(void) { |
| + | |
| int keypress; | |
| - | |
| + | |
| /* Clear the current line and print a prompt */ | |
| clear_line(); | |
| printf(" :"); | |
| - | |
| + | |
| keypress = tless_getch(); | |
| switch (keypress) { | |
| case 'd': | |
| @@ -700,24 +640,158 @@ static void colon_process() { | |
| } | |
| } | |
| - | static void number_process(int first_digit) { |
| - | |
| - | int i = 1; |
| - | int num; |
| - | char num_input[80]; |
| - | char keypress; |
| - | num_input[0] = first_digit; |
| - | |
| - | /* Clear the current line, print a prompt, and then print the digit */ |
| + | #ifdef CONFIG_FEATURE_LESS_REGEXP |
| + | /* The below two regular expression handler functions NEED development. */ |
| + | |
| + | /* Get a regular expression from the user, and then go through the current |
| + | file line by line, running a processing regex function on each one. */ |
| + | |
| + | static char *insert_highlights (char *line, int start, int end) { |
| + | |
| + | char *new_line = (char *) malloc((sizeof(char) * (strlen(line) + 1)) + 10); |
| + | |
| + | memset(new_line, 0, ((sizeof(char) * (strlen(line) + 1)) + 10)); |
| + | strncat(new_line, line, start); |
| + | strcat(new_line, HIGHLIGHT); |
| + | strncat(new_line, line + start, end - start); |
| + | strcat(new_line, NORMAL); |
| + | strncat(new_line, line + end, strlen(line) - end); |
| + | |
| + | return new_line; |
| + | } |
| + | |
| + | static char *process_regex_on_line(char *line, regex_t *pattern) { |
| + | /* This function takes the regex and applies it to the line. |
| + | Each part of the line that matches has the HIGHLIGHT |
| + | and NORMAL escape sequences placed around it by |
| + | insert_highlights, and then the line is returned. */ |
| + | |
| + | int match_status; |
| + | char *line2 = (char *) malloc((sizeof(char) * (strlen(line) + 1)) + 64); |
| + | char sub_line[256]; |
| + | int prev_eo = 0; |
| + | memset(sub_line, 0, 256); |
| + | strcpy(line2, line); |
| + | regmatch_t match_structs; |
| + | |
| + | match_found = 0; |
| + | match_status = regexec(pattern, line2, 1, &match_structs, 0); |
| + | |
| + | while (match_status == 0) { |
| + | |
| + | memset(sub_line, 0, 256); |
| + | |
| + | if (match_found == 0) |
| + | match_found = 1; |
| + | |
| + | line2 = insert_highlights(line2, match_structs.rm_so + prev_eo, match_structs.rm_eo + prev_eo); |
| + | if (match_structs.rm_eo + 11 + prev_eo < strlen(line2)) |
| + | strcat(sub_line, line2 + match_structs.rm_eo + 11 + prev_eo); |
| + | |
| + | prev_eo += match_structs.rm_eo + 11; |
| + | match_status = regexec(pattern, sub_line, 1, &match_structs, REG_NOTBOL); |
| + | } |
| + | |
| + | return line2; |
| + | } |
| + | |
| + | static void regex_process(void) { |
| + | |
| + | char uncomp_regex[100]; |
| + | char current_line[256]; |
| + | int i; |
| + | int j = 0; |
| + | regex_t *pattern; |
| + | |
| + | /* Reset variables */ |
| + | match_lines[0] = -1; |
| + | match_pos = 0; |
| + | num_matches = 0; |
| + | match_found = 0; |
| + | |
| + | pattern = (regex_t *) malloc(sizeof(regex_t)); |
| + | memset(pattern, 0, sizeof(regex_t)); |
| + | |
| + | /* Get the uncompiled regular expression from the user */ |
| + | clear_line(); |
| + | if (match_backwards) |
| + | printf("?"); |
| + | else |
| + | printf("/"); |
| + | scanf("%s", uncomp_regex); |
| + | |
| + | /* Compile the regex and check for errors */ |
| + | xregcomp(pattern, uncomp_regex, 0); |
| + | |
| + | /* Run the regex on each line of the current file here */ |
| + | for (i = 0; i <= num_flines; i++) { |
| + | strcpy(current_line, process_regex_on_line(flines[i], pattern)); |
| + | flines[i] = (char *) bb_xstrndup(current_line, sizeof(char) * (strlen(current_line)+1)); |
| + | |
| + | if (match_found) { |
| + | match_lines[j] = i; |
| + | j++; |
| + | } |
| + | } |
| + | |
| + | num_matches = j; |
| + | |
| + | if ((match_lines[0] != -1) && (num_flines > height - 2)) |
| + | buffer_line(match_lines[0]); |
| + | else |
| + | buffer_init(); |
| + | } |
| + | |
| + | static void goto_match(int match) { |
| + | |
| + | /* This goes to a specific match - all line positions of matches are |
| + | stored within the match_lines[] array. */ |
| + | if ((match < num_matches) && (match >= 0)) { |
| + | buffer_line(match_lines[match]); |
| + | match_pos = match; |
| + | } |
| + | } |
| + | |
| + | static void search_backwards(void) { |
| + | |
| + | int current_linepos = line_pos; |
| + | int i; |
| + | |
| + | match_backwards = 1; |
| + | regex_process(); |
| + | |
| + | for (i = 0; i < num_matches; i++) { |
| + | if (match_lines[i] > current_linepos) { |
| + | buffer_line(match_lines[i - num_back_match]); |
| + | break; |
| + | } |
| + | } |
| + | |
| + | /* Reset variables */ |
| + | match_backwards = 0; |
| + | num_back_match = 1; |
| + | |
| + | } |
| + | #endif |
| + | |
| + | static void number_process(int first_digit) { |
| + | |
| + | int i = 1; |
| + | int num; |
| + | char num_input[80]; |
| + | char keypress; |
| + | num_input[0] = first_digit; |
| + | |
| + | /* Clear the current line, print a prompt, and then print the digit */ |
| clear_line(); | |
| printf(":%c", first_digit); | |
| - | |
| + | |
| /* Receive input until a letter is given */ | |
| while((num_input[i] = tless_getch()) && isdigit(num_input[i])) { | |
| printf("%c",num_input[i]); | |
| i++; | |
| } | |
| - | |
| + | |
| /* Take the final letter out of the digits string */ | |
| keypress = num_input[i]; | |
| num_input[i] = '\0'; | |
| @@ -765,14 +839,14 @@ static void number_process(int first_digit) { | |
| } | |
| #ifdef CONFIG_FEATURE_LESS_FLAGCS | |
| - | static void flag_change() { |
| - | |
| + | static void flag_change(void) { |
| + | |
| int keypress; | |
| - | |
| + | |
| clear_line(); | |
| printf("-"); | |
| keypress = tless_getch(); | |
| - | |
| + | |
| switch (keypress) { | |
| case 'M': | |
| M_FLAG = !M_FLAG; | |
| @@ -791,11 +865,11 @@ static void flag_change() { | |
| } | |
| } | |
| - | static void show_flag_status() { |
| - | |
| + | static void show_flag_status(void) { |
| + | |
| int keypress; | |
| int flag_val; | |
| - | |
| + | |
| clear_line(); | |
| printf("_"); | |
| keypress = tless_getch(); | |
| @@ -820,101 +894,13 @@ static void show_flag_status() { | |
| flag_val = 0; | |
| break; | |
| } | |
| - | |
| - | clear_line(); |
| - | printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val, NORMAL); |
| - | } |
| - | #endif |
| - | static void examine_file() { |
| - | |
| - | int newline_offset; |
| - | |
| clear_line(); | |
| - | printf("Examine: "); |
| - | fgets(filename, 256, inp); |
| - | |
| - | /* As fgets adds a newline to the end of an input string, we |
| - | need to remove it */ |
| - | newline_offset = strlen(filename) - 1; |
| - | filename[newline_offset] = '\0'; |
| - | |
| - | files[num_files] = bb_xstrndup(filename, (strlen(filename) + 1) * sizeof(char)); |
| - | current_file = num_files + 1; |
| - | num_files++; |
| - | |
| - | inp_stdin = 0; |
| - | ea_inp_stdin = 1; |
| - | free_flines(); |
| - | data_readlines(); |
| - | buffer_init(); |
| - | buffer_print(); |
| - | } |
| - | |
| - | static void next_file() { |
| - | if (current_file != num_files) { |
| - | current_file++; |
| - | strcpy(filename, files[current_file - 1]); |
| - | free_flines(); |
| - | data_readlines(); |
| - | buffer_init(); |
| - | buffer_print(); |
| - | } |
| - | else { |
| - | clear_line(); |
| - | printf("%s%s%s", HIGHLIGHT, "No next file", NORMAL); |
| - | } |
| - | } |
| - | |
| - | static void previous_file() { |
| - | if (current_file != 1) { |
| - | current_file--; |
| - | strcpy(filename, files[current_file - 1]); |
| - | |
| - | free_flines(); |
| - | data_readlines(); |
| - | buffer_init(); |
| - | buffer_print(); |
| - | } |
| - | else { |
| - | clear_line(); |
| - | printf("%s%s%s", HIGHLIGHT, "No previous file", NORMAL); |
| - | } |
| - | } |
| - | |
| - | static void first_file() { |
| - | if (current_file != 1) { |
| - | current_file = 1; |
| - | strcpy(filename, files[current_file - 1]); |
| - | free_flines(); |
| - | data_readlines(); |
| - | buffer_init(); |
| - | buffer_print(); |
| - | } |
| - | } |
| - | |
| - | static void remove_current_file() { |
| - | |
| - | int i; |
| - | |
| - | if (current_file != 1) { |
| - | previous_file(); |
| - | for (i = 3; i <= num_files; i++) |
| - | files[i - 2] = files[i - 1]; |
| - | num_files--; |
| - | buffer_print(); |
| - | } |
| - | else { |
| - | next_file(); |
| - | for (i = 2; i <= num_files; i++) |
| - | files[i - 2] = files[i - 1]; |
| - | num_files--; |
| - | current_file--; |
| - | buffer_print(); |
| - | } |
| + | printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val != 0, NORMAL); |
| } | |
| + | #endif |
| - | static void full_repaint() { |
| + | static void full_repaint(void) { |
| int temp_line_pos = line_pos; | |
| data_readlines(); | |
| @@ -923,25 +909,13 @@ static void full_repaint() { | |
| buffer_print(); | |
| } | |
| - | /* This adds line numbers to every line, as the -N flag necessitates */ |
| - | static void add_linenumbers() { |
| - | char current_line[256]; |
| - | int i; |
| - | |
| - | for (i = 0; i <= num_flines; i++) { |
| - | safe_strncpy(current_line, flines[i], 256); |
| - | flines[i] = xrealloc(flines[i], strlen(current_line) + 7 ); |
| - | sprintf(flines[i],"%5d %s", i+1, current_line); |
| - | } |
| - | } |
| + | static void save_input_to_file(void) { |
| - | static void save_input_to_file() { |
| - | |
| char current_line[256]; | |
| int i; | |
| FILE *fp; | |
| - | |
| + | |
| clear_line(); | |
| printf("Log file: "); | |
| fgets(current_line, 256, inp); | |
| @@ -958,18 +932,18 @@ static void save_input_to_file() { | |
| } | |
| #ifdef CONFIG_FEATURE_LESS_MARKS | |
| - | static void add_mark() { |
| + | static void add_mark(void) { |
| int letter; | |
| int mark_line; | |
| - | |
| + | |
| clear_line(); | |
| printf("Mark: "); | |
| letter = tless_getch(); | |
| - | |
| + | |
| if (isalpha(letter)) { | |
| mark_line = line_pos; | |
| - | |
| + | |
| /* If we exceed 15 marks, start overwriting previous ones */ | |
| if (num_marks == 14) | |
| num_marks = 0; | |
| @@ -984,11 +958,11 @@ static void add_mark() { | |
| } | |
| } | |
| - | static void goto_mark() { |
| + | static void goto_mark(void) { |
| int letter; | |
| int i; | |
| - | |
| + | |
| clear_line(); | |
| printf("Go to mark: "); | |
| letter = tless_getch(); | |
| @@ -1001,7 +975,7 @@ static void goto_mark() { | |
| if ((num_marks == 14) && (letter != mark_lines[14][0])) { | |
| clear_line(); | |
| printf("%s%s%s", HIGHLIGHT, "Mark not set", NORMAL); | |
| - | } |
| + | } |
| } | |
| else { | |
| clear_line(); | |
| @@ -1010,137 +984,6 @@ static void goto_mark() { | |
| } | |
| #endif | |
| - | #ifdef CONFIG_FEATURE_LESS_REGEXP |
| - | /* The below two regular expression handler functions NEED development. */ |
| - | |
| - | /* Get a regular expression from the user, and then go through the current |
| - | file line by line, running a processing regex function on each one. */ |
| - | static void regex_process() { |
| - | |
| - | char uncomp_regex[100]; |
| - | char current_line[256]; |
| - | int i; |
| - | int j = 0; |
| - | regex_t *pattern; |
| - | |
| - | /* Reset variables */ |
| - | match_lines[0] = -1; |
| - | match_pos = 0; |
| - | num_matches = 0; |
| - | match_found = 0; |
| - | |
| - | pattern = (regex_t *) malloc(sizeof(regex_t)); |
| - | memset(pattern, 0, sizeof(regex_t)); |
| - | |
| - | /* Get the uncompiled regular expression from the user */ |
| - | clear_line(); |
| - | if (match_backwards) |
| - | printf("?"); |
| - | else |
| - | printf("/"); |
| - | scanf("%s", uncomp_regex); |
| - | |
| - | /* Compile the regex and check for errors */ |
| - | xregcomp(pattern, uncomp_regex, 0); |
| - | |
| - | /* Run the regex on each line of the current file here */ |
| - | for (i = 0; i <= num_flines; i++) { |
| - | strcpy(current_line, process_regex_on_line(flines[i], pattern)); |
| - | flines[i] = (char *) bb_xstrndup(current_line, sizeof(char) * (strlen(current_line)+1)); |
| - | |
| - | if (match_found) { |
| - | match_lines[j] = i; |
| - | j++; |
| - | } |
| - | } |
| - | |
| - | num_matches = j; |
| - | |
| - | if ((match_lines[0] != -1) && (num_flines > height - 2)) |
| - | buffer_line(match_lines[0]); |
| - | else |
| - | buffer_init(); |
| - | } |
| - | |
| - | char *process_regex_on_line(char *line, regex_t *pattern) { |
| - | /* This function takes the regex and applies it to the line. |
| - | Each part of the line that matches has the HIGHLIGHT |
| - | and NORMAL escape sequences placed around it by |
| - | insert_highlights, and then the line is returned. */ |
| - | |
| - | int match_status; |
| - | char *line2 = (char *) malloc((sizeof(char) * (strlen(line) + 1)) + 64); |
| - | char sub_line[256]; |
| - | int prev_eo = 0; |
| - | memset(sub_line, 0, 256); |
| - | strcpy(line2, line); |
| - | regmatch_t match_structs; |
| - | |
| - | match_found = 0; |
| - | match_status = regexec(pattern, line2, 1, &match_structs, 0); |
| - | |
| - | while (match_status == 0) { |
| - | |
| - | memset(sub_line, 0, 256); |
| - | |
| - | if (match_found == 0) |
| - | match_found = 1; |
| - | |
| - | line2 = insert_highlights(line2, match_structs.rm_so + prev_eo, match_structs.rm_eo + prev_eo); |
| - | if (match_structs.rm_eo + 11 + prev_eo < strlen(line2)) |
| - | strcat(sub_line, line2 + match_structs.rm_eo + 11 + prev_eo); |
| - | |
| - | prev_eo += match_structs.rm_eo + 11; |
| - | match_status = regexec(pattern, sub_line, 1, &match_structs, REG_NOTBOL); |
| - | } |
| - | |
| - | return line2; |
| - | } |
| - | |
| - | char *insert_highlights (char *line, int start, int end) { |
| - | |
| - | char *new_line = (char *) malloc((sizeof(char) * (strlen(line) + 1)) + 10); |
| - | memset(new_line, 0, ((sizeof(char) * (strlen(line) + 1)) + 10)); |
| - | strncat(new_line, line, start); |
| - | strcat(new_line, HIGHLIGHT); |
| - | strncat(new_line, line + start, end - start); |
| - | strcat(new_line, NORMAL); |
| - | strncat(new_line, line + end, strlen(line) - end); |
| - | |
| - | return new_line; |
| - | } |
| - | |
| - | static void goto_match(int match) { |
| - | |
| - | /* This goes to a specific match - all line positions of matches are |
| - | stored within the match_lines[] array. */ |
| - | if ((match < num_matches) && (match >= 0)) { |
| - | buffer_line(match_lines[match]); |
| - | match_pos = match; |
| - | } |
| - | } |
| - | |
| - | static void search_backwards() { |
| - | |
| - | int current_linepos = line_pos; |
| - | int i; |
| - | |
| - | match_backwards = 1; |
| - | regex_process(); |
| - | |
| - | for (i = 0; i < num_matches; i++) { |
| - | if (match_lines[i] > current_linepos) { |
| - | buffer_line(match_lines[i - num_back_match]); |
| - | break; |
| - | } |
| - | } |
| - | |
| - | /* Reset variables */ |
| - | match_backwards = 0; |
| - | num_back_match = 1; |
| - | |
| - | } |
| - | #endif |
| #ifdef CONFIG_FEATURE_LESS_BRACKETS | |
| @@ -1166,10 +1009,10 @@ static char opp_bracket (char bracket) { | |
| } | |
| static void match_right_bracket(char bracket) { | |
| - | |
| + | |
| int bracket_line = -1; | |
| int i; | |
| - | |
| + | |
| if (strchr(flines[line_pos], bracket) == NULL) { | |
| clear_line(); | |
| printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL); | |
| @@ -1193,7 +1036,7 @@ static void match_right_bracket(char bracket) { | |
| } | |
| static void match_left_bracket (char bracket) { | |
| - | |
| + | |
| int bracket_line = -1; | |
| int i; | |
| @@ -1215,19 +1058,130 @@ static void match_left_bracket (char bracket) { | |
| clear_line(); | |
| printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | |
| } | |
| - | |
| + | |
| buffer_line(bracket_line); | |
| buffer_print(); | |
| } | |
| } | |
| + | #endif /* CONFIG_FEATURE_LESS_BRACKETS */ |
| + | |
| + | static void keypress_process(int keypress) { |
| + | switch (keypress) { |
| + | case KEY_DOWN: case 'e': case 'j': case '\015': |
| + | buffer_down(1); |
| + | buffer_print(); |
| + | break; |
| + | case KEY_UP: case 'y': case 'k': |
| + | buffer_up(1); |
| + | buffer_print(); |
| + | break; |
| + | case PAGE_DOWN: case ' ': case 'z': |
| + | buffer_down(height - 1); |
| + | buffer_print(); |
| + | break; |
| + | case PAGE_UP: case 'w': case 'b': |
| + | buffer_up(height - 1); |
| + | buffer_print(); |
| + | break; |
| + | case 'd': |
| + | buffer_down((height - 1) / 2); |
| + | buffer_print(); |
| + | break; |
| + | case 'u': |
| + | buffer_up((height - 1) / 2); |
| + | buffer_print(); |
| + | break; |
| + | case 'g': case 'p': case '<': case '%': |
| + | buffer_up(num_flines + 1); |
| + | buffer_print(); |
| + | break; |
| + | case 'G': case '>': |
| + | buffer_down(num_flines + 1); |
| + | buffer_print(); |
| + | break; |
| + | case 'q': case 'Q': |
| + | tless_exit(0); |
| + | break; |
| + | #ifdef CONFIG_FEATURE_LESS_MARKS |
| + | case 'm': |
| + | add_mark(); |
| + | buffer_print(); |
| + | break; |
| + | case '\'': |
| + | goto_mark(); |
| + | buffer_print(); |
| + | break; |
| #endif | |
| + | case 'r': |
| + | buffer_print(); |
| + | break; |
| + | case 'R': |
| + | full_repaint(); |
| + | break; |
| + | case 's': |
| + | if (inp_stdin) |
| + | save_input_to_file(); |
| + | break; |
| + | case 'E': |
| + | examine_file(); |
| + | break; |
| + | #ifdef CONFIG_FEATURE_LESS_FLAGS |
| + | case '=': |
| + | clear_line(); |
| + | m_status_print(); |
| + | break; |
| + | #endif |
| + | #ifdef CONFIG_FEATURE_LESS_REGEXP |
| + | case '/': |
| + | regex_process(); |
| + | buffer_print(); |
| + | break; |
| + | case 'n': |
| + | goto_match(match_pos + 1); |
| + | buffer_print(); |
| + | break; |
| + | case 'N': |
| + | goto_match(match_pos - 1); |
| + | buffer_print(); |
| + | break; |
| + | case '?': |
| + | search_backwards(); |
| + | buffer_print(); |
| + | break; |
| + | #endif |
| + | #ifdef CONFIG_FEATURE_LESS_FLAGCS |
| + | case '-': |
| + | flag_change(); |
| + | buffer_print(); |
| + | break; |
| + | case '_': |
| + | show_flag_status(); |
| + | break; |
| + | #endif |
| + | #ifdef CONFIG_FEATURE_LESS_BRACKETS |
| + | case '{': case '(': case '[': |
| + | match_right_bracket(keypress); |
| + | break; |
| + | case '}': case ')': case ']': |
| + | match_left_bracket(keypress); |
| + | break; |
| + | #endif |
| + | case ':': |
| + | colon_process(); |
| + | break; |
| + | default: |
| + | break; |
| + | } |
| + | if (isdigit(keypress)) |
| + | number_process(keypress); |
| + | } |
| int less_main(int argc, char **argv) { | |
| - | |
| + | |
| unsigned long flags; | |
| int keypress; | |
| - | |
| + | |
| flags = bb_getopt_ulflags(argc, argv, "EMNm~"); | |
| E_FLAG = (flags & 1); | |
| M_FLAG = (flags & 2); | |
| @@ -1239,7 +1193,7 @@ int less_main(int argc, char **argv) { | |
| argv += optind; | |
| files = argv; | |
| num_files = argc; | |
| - | |
| + | |
| if (!num_files) { | |
| if (ttyname(STDIN_FILENO) == NULL) | |
| inp_stdin = 1; | |
| @@ -1248,13 +1202,13 @@ int less_main(int argc, char **argv) { | |
| bb_show_usage(); | |
| } | |
| } | |
| - | |
| + | |
| strcpy(filename, (inp_stdin) ? "stdin" : files[0]); | |
| tty_width_height(); | |
| data_readlines(); | |
| buffer_init(); | |
| buffer_print(); | |
| - | |
| + | |
| while (1) { | |
| keypress = tless_getch(); | |
| keypress_process(keypress); | |