small change for highlihting flags, more busyboxes: indent, forward declaration,...
author"Vladimir N. Oleynik" <dzo@simtreas.ru>
Fri, 16 Sep 2005 12:32:22 +0000 (12:32 -0000)
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>
Fri, 16 Sep 2005 12:32:22 +0000 (12:32 -0000)
miscutils/less.c

index 43bc6737e2cbc7558c8f79e9a60b7f1174ae3d51..99149a51d06faf8fc65336dc1d819716d51ef074 100644 (file)
@@ -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.
 #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'
 #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);