C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
View Engine

File mapping, user input, command processing, and display logic. More...

Macros

#define get_next_char()
 read the next characater from the virtual file
#define get_prev_char()
 read the previous characater from the virtual fileThere is no need to track line numbers when moving backwards as they are stored in the line table and accessed as needed. When reading in reverse, the Beginning of Data (BOD) flag is set when the file position is zero, and cleared when the position or reading direction changes. Carriage-returns are ignored as they should be.

Functions

void build_prompt (View *view)
 Build Prompt String.
void cat_file (View *view)
 Concatenate File to Standard Output.
bool enter_file_spec (Init *init, char *file_spec)
 use form to enter a file specification
int get_cmd_arg (View *view, char *prompt)
 Get Command Argument from User Input.
int get_cmd_char (View *view, off_t *n)
 Get Command Character and Numeric Argument.
void lp (char *PrintFile)
 Send File to Print Queue.
void remove_file (View *view)
 Remove File.
int view_cmd_processor (Init *init)
 Main Command Processing Loop for View.
int view_file (Init *init)
 Start view.
int write_view_buffer (Init *init, bool f_strip_ansi)
 Write buffer contents to files.

Detailed Description

File mapping, user input, command processing, and display logic.

Macro Definition Documentation

◆ get_next_char

#define get_next_char ( )
Value:
{ \
c = 0; \
do { \
if (view->file_pos == view->file_size) { \
view->f_eod = true; \
break; \
} else \
view->f_eod = false; \
c = view->buf[view->file_pos++]; \
} while (c == 0x0d); \
if (c == '\n') \
increment_ln(view); \
}
View * view
Definition mem.c:48

read the next characater from the virtual file

Line numbers are tracked when reading forward and stored in a line table for quick access when moving backwards. When reading forward, the End of Data (EOD) flag is set when the position is equal to the file size, and cleared when the position or reading direction changes. Carriage-returns are ignored as they should be. View uses the kernel's demand paged virtual address space to map files directly into memory. This allows for efficient access to file contents without the need for explicit buffering or read system calls, as the kernel handles loading the necessary pages into memory on demand.

Definition at line 44 of file view_engine.c.

44#define get_next_char() \
45 { \
46 c = 0; \
47 do { \
48 if (view->file_pos == view->file_size) { \
49 view->f_eod = true; \
50 break; \
51 } else \
52 view->f_eod = false; \
53 c = view->buf[view->file_pos++]; \
54 } while (c == 0x0d); \
55 if (c == '\n') \
56 increment_ln(view); \
57 }

◆ get_prev_char

#define get_prev_char ( )
Value:
{ \
c = 0; \
do { \
if (view->file_pos == 0) { \
view->f_bod = true; \
break; \
} else \
view->f_bod = false; \
c = view->buf[--view->file_pos]; \
} while (c == 0x0d); \
}

read the previous characater from the virtual fileThere is no need to track line numbers when moving backwards as they are stored in the line table and accessed as needed. When reading in reverse, the Beginning of Data (BOD) flag is set when the file position is zero, and cleared when the position or reading direction changes. Carriage-returns are ignored as they should be.

Definition at line 67 of file view_engine.c.

67#define get_prev_char() \
68 { \
69 c = 0; \
70 do { \
71 if (view->file_pos == 0) { \
72 view->f_bod = true; \
73 break; \
74 } else \
75 view->f_bod = false; \
76 c = view->buf[--view->file_pos]; \
77 } while (c == 0x0d); \
78 }

Function Documentation

◆ build_prompt()

void build_prompt ( View * view)

Build Prompt String.

Parameters
viewPointer to the View structure containing the state and parameters of the view application. This structure is used to access and modify the state of the application as needed.

Definition at line 830 of file view_engine.c.

830 {
831 char tmp_str[MAXLEN];
832 if (view->f_is_pipe)
833 strnz__cpy(view->prompt_str, "stdin", MAXLEN - 1);
834 else
835 strnz__cpy(view->prompt_str, view->file_name, MAXLEN - 1);
836 if (view->pmincol > 0) {
837 sprintf(tmp_str, "Col %d of %d", view->pmincol, view->maxcol);
838 if (view->prompt_str[0] != '\0')
839 strnz__cat(view->prompt_str, "|", MAXLEN - 1);
840 strnz__cat(view->prompt_str, tmp_str, MAXLEN - 1);
841 }
842 if (view->argc > 0) {
843 sprintf(tmp_str, "File %d of %d", view->curr_argc + 1, view->argc);
844 if (view->prompt_str[0] != '\0') {
845 strnz__cat(view->prompt_str, "|", MAXLEN - 1);
846 strnz__cat(view->prompt_str, tmp_str, MAXLEN - 1);
847 }
848 }
849 if (view->page_top_pos == NULL_POSITION)
850 view->page_top_pos = view->file_size;
851 sprintf(tmp_str, "Pos %zd-%zd", view->page_top_pos, view->page_bot_pos);
852 if (view->prompt_str[0] != '\0') {
853 strnz__cat(view->prompt_str, "|", MAXLEN - 1);
854 strnz__cat(view->prompt_str, tmp_str, MAXLEN - 1);
855 }
856 if (!view->f_is_pipe) {
857 if (view->file_size > 0) {
858 sprintf(tmp_str, " of %zd", view->file_size);
859 strnz__cat(view->prompt_str, tmp_str, MAXLEN - 1);
860 }
861 }
862 if (view->f_eod) {
863 if (view->prompt_str[0] != '\0')
864 strnz__cat(view->prompt_str, " ", MAXLEN - 1);
865 strnz__cat(view->prompt_str, "(End)", MAXLEN - 1);
866 if (view->curr_argc + 1 < view->argc) {
867 base_name(tmp_str, view->argv[view->curr_argc + 1]);
868 strnz__cpy(view->prompt_str, " Next File: ", MAXLEN - 1);
869 strnz__cat(view->prompt_str, tmp_str, MAXLEN - 1);
870 }
871 }
872}
#define NULL_POSITION
Definition view.h:27
#define MAXLEN
Definition curskeys.c:15
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:435
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:464
bool base_name(char *, char *)
Returns the base name of a file specification.
Definition futil.c:984

References View::argc, View::argv, base_name(), View::curr_argc, View::f_eod, View::f_is_pipe, View::file_name, View::file_size, View::maxcol, View::page_bot_pos, View::page_top_pos, View::pmincol, View::prompt_str, strnz__cat(), and strnz__cpy().

Referenced by view_cmd_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cat_file()

void cat_file ( View * view)

Concatenate File to Standard Output.

Definition at line 926 of file view_engine.c.

926 {
927 int c;
928 while (1) {
930 if (view->f_eod)
931 break;
932 putchar(c);
933 }
934}
#define get_next_char()
read the next characater from the virtual file
Definition view_engine.c:44

References View::f_eod.

◆ enter_file_spec()

bool enter_file_spec ( Init * init,
char * file_spec )

use form to enter a file specification

Parameters
initdata structure
file_spec- pointer to file specification the file_spec
Returns
true if successful

the user must provide a character array large enough to hold file_spec without overflowing

call form to get file_name write the name to a temporary file

Definition at line 2018 of file view_engine.c.

2018 {
2019 char earg_str[MAXLEN];
2020 char *eargv[MAXARGS];
2021 int eargc;
2022 char tmp_dir[MAXLEN];
2023 char tmp_str[MAXLEN];
2024 char tmp_spec[MAXLEN];
2025 int rc = false;
2026 FILE *tmp_fp;
2027 view = init->view;
2028 strnz__cpy(tmp_dir, init->mapp_home, MAXLEN - 1);
2029 strnz__cat(tmp_dir, "/tmp", MAXLEN - 1);
2030 expand_tilde(tmp_dir, MAXLEN - 1);
2031 if (!mk_dir(tmp_dir)) {
2032 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
2033 strnz__cpy(em1, "Unable to ", MAXLEN - 1);
2034 strnz__cat(em1, "mkdir", MAXLEN - 1);
2035 strnz__cat(em1, tmp_dir, MAXLEN - 1);
2036 strerror_r(errno, em2, MAXLEN - 1);
2037 display_error(em0, em1, em2, nullptr);
2038 return false;
2039 }
2040 while (rc == false) {
2041 strnz__cpy(tmp_spec, tmp_dir, MAXLEN - 1);
2042 strnz__cat(tmp_spec, "/tmp_XXXXXX", MAXLEN - 1);
2043 view->in_fd = mkstemp(tmp_spec);
2044 if (view->in_fd == -1) {
2045 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
2046 strnz__cpy(em1, "unable to ", MAXLEN - 1);
2047 strnz__cat(em1, "mkstemp ", MAXLEN - 1);
2048 strnz__cat(em1, tmp_spec, MAXLEN - 1);
2049 strerror_r(errno, em2, MAXLEN - 1);
2050 display_error(em0, em1, nullptr, nullptr);
2051 return false;
2052 }
2055
2056 strnz__cpy(earg_str, "form -d file_name.f -o ", MAXLEN - 1);
2057 strnz__cat(earg_str, tmp_spec, MAXLEN - 1);
2059 rc = popup_form(init, eargc, eargv, view->begy + view->lines - 7, 4);
2061 restore_wins();
2062 if (rc == FA_CANCEL || rc == 'q' || rc == 'Q' || rc == KEY_F(9))
2063 return false;
2064 close(view->in_fd);
2065 tmp_fp = fopen(tmp_spec, "r");
2066 if (tmp_fp == nullptr) {
2067 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
2068 strnz__cpy(em1, "unable to ", MAXLEN - 1);
2069 strnz__cat(em1, "fopen ", MAXLEN - 1);
2070 strnz__cat(em1, tmp_spec, MAXLEN - 1);
2071 strerror_r(errno, em2, MAXLEN - 1);
2072 display_error(em0, em1, em2, nullptr);
2073 return false;
2074 }
2075 fgets(tmp_str, MAXLEN - 1, tmp_fp);
2076 strnz(tmp_str, MAXLEN - 1);
2077 fclose(tmp_fp);
2078 unlink(tmp_spec);
2079 if (!verify_spec_arg(file_spec, tmp_str, "~/menuapp/tmp", ".",
2080 S_WCOK | S_QUIET)) {
2081 ssnprintf(em0, MAXLEN - 1, "Unable to open %s for writing",
2082 tmp_str);
2083 strnz__cpy(em1, "Try again? y (yes) or n (no) ", MAXLEN - 1);
2084 rc = display_error(em0, em1, nullptr, nullptr);
2085 if (rc == 'y' || rc == 'Y')
2086 continue;
2087
2088 } else
2089 return true;
2090 }
2091 return true;
2092}
@ FA_CANCEL
Definition form.h:34
Init * init
Definition init.c:74
int popup_form(Init *, int, char **, int, int)
instantiate a form popup window
Definition popups.c:113
#define MAX_ARGS
Definition cm.h:28
#define MAXARGS
Definition cm.h:30
#define S_QUIET
Definition cm.h:219
#define S_WCOK
Definition cm.h:218
int eargc
Definition futil.c:51
char earg_str[MAXLEN]
Definition futil.c:50
char * eargv[MAXARGS]
Definition futil.c:52
char em1[MAXLEN]
Definition dwin.c:142
char em0[MAXLEN]
Definition dwin.c:141
char em2[MAXLEN]
Definition dwin.c:143
void restore_wins()
Restore all windows after a screen resize.
Definition dwin.c:933
int display_error(char *em0, char *em1, char *em2, char *em3)
Display an error message window or print to stderr.
Definition dwin.c:1102
int destroy_argv(int argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:385
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:506
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:311
bool expand_tilde(char *, int)
Replaces "~/" in string with the user's home directory.
Definition futil.c:904
bool mk_dir(char *dir)
If directory doesn't exist, make it.
Definition futil.c:1181
int str_to_args(char **, char *, int)
Converts a string into an array of argument strings.
Definition futil.c:331
bool verify_spec_arg(char *, char *, char *, char *, int)
Verify file specification argument.
Definition mem.c:406

References View::begy, destroy_argv(), display_error(), em0, em1, em2, expand_tilde(), FA_CANCEL, View::in_fd, View::lines, Init::mapp_home, mk_dir(), popup_form(), restore_wins(), ssnprintf(), str_to_args(), strnz(), strnz__cat(), strnz__cpy(), verify_spec_arg(), Init::view, and view.

Referenced by view_cmd_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_cmd_arg()

int get_cmd_arg ( View * view,
char * prompt )

Get Command Argument from User Input.

Parameters
viewPointer to the View structure containing the state and parameters of the view application. This structure is used to access and modify the state of the application as needed.
promptA string containing the prompt to be displayed to the user when requesting input for the command argument. This prompt is shown on the command line to guide the user in providing the necessary input for the command being executed.
Returns
Returns the command character entered by the user, or a special value if a mouse event is detected. The command argument entered by the user is stored in the view->cmd_arg buffer for use by the calling function. The function handles user input, including editing keys, and updates the command argument buffer accordingly. If the user enters a numeric argument, it is validated based on the context of the command being executed.

Basic Editing Keys for Command Line

Definition at line 734 of file view_engine.c.

734 {
735 int c;
736 int numeric_arg = false;
737 char *cmd_p;
738 char *cmd_e;
739 char prompt_s[PAD_COLS + 1];
740 char *n;
741 int prompt_l;
742 prompt_l = strnz__cpy(prompt_s, prompt, view->cols - 4);
743 if (view->cmd_arg[0] != '\0')
744 return 0;
745 cmd_p = view->cmd_arg;
746 cmd_e = view->cmd_arg + MAXLEN - 2;
747 wmove(view->cmdln_win, view->cmd_line, 0);
748 if (prompt_l == 0)
749 numeric_arg = true;
750 if (prompt_l > 1) {
751 wstandout(view->cmdln_win);
752 waddch(view->cmdln_win, ' ');
753 waddstr(view->cmdln_win, prompt_s);
754 waddch(view->cmdln_win, ' ');
755 wstandend(view->cmdln_win);
756 } else {
757 if (*prompt == ':')
758 numeric_arg = true;
759 else {
760 n = prompt;
761 if (*n >= '0' && *n <= '9') {
762 *cmd_p++ = *n;
763 *cmd_p = '\0';
764 numeric_arg = true;
765 }
766 }
767 waddstr(view->cmdln_win, prompt_s);
768 wmove(view->cmdln_win, view->cmd_line, prompt_l);
769 }
770 wclrtoeol(view->cmdln_win);
771 while (1) {
772 c = xwgetch(view->cmdln_win, nullptr, -1);
773 switch (c) {
775 case KEY_LEFT:
776 case KEY_BACKSPACE:
777 case '\b':
778 if (cmd_p > view->cmd_arg) {
779 cmd_p--;
780 if (*cmd_p < ' ' || *cmd_p == 0x7f) {
781 getyx(view->cmdln_win, view->cury, view->curx);
782 if (view->curx > 0) {
783 view->curx--;
784 wmove(view->cmdln_win, view->cmd_line, view->curx);
785 waddch(view->cmdln_win, ' ');
786 wmove(view->cmdln_win, view->cmd_line, view->curx);
787 }
788 }
789 getyx(view->cmdln_win, view->cury, view->curx);
790 if (view->curx > 0) {
791 view->curx--;
792 wmove(view->cmdln_win, view->cmd_line, view->curx);
793 waddch(view->cmdln_win, ' ');
794 wmove(view->cmdln_win, view->cmd_line, view->curx);
795 }
796 }
797 break;
798 case '\n':
799 case KEY_ENTER:
800 return c;
801 case '\033':
802 case KEY_F(9):
803 return c;
804 case KEY_MOUSE:
805 continue;
806 default:
807 *cmd_p++ = (char)c;
808 *cmd_p = '\0';
809 if ((char)c < ' ') {
810 waddch(view->cmdln_win, '^');
811 c |= '@';
812 } else if ((uchar)c == 0x7f)
813 c = '?';
814 waddch(view->cmdln_win, (char)c);
815 if (cmd_p >= cmd_e)
816 return 0;
817 if (numeric_arg && (c < '0' || c > '9'))
818 return -1;
819 break;
820 }
821 }
822 return c;
823}
unsigned char uchar
Definition cm.h:543
#define PAD_COLS
Definition view.h:30
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:1651

References View::cmd_arg, View::cmd_line, View::cmdln_win, View::cols, View::curx, View::cury, strnz__cpy(), and xwgetch().

Referenced by view_cmd_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_cmd_char()

int get_cmd_char ( View * view,
off_t * n )

Get Command Character and Numeric Argument.

Parameters
viewPointer to the View structure containing the state around the view application. This structure is used to access and modify the state
nis used to store the numeric argument entered by the user, if applicable. The function reads user input and extracts both the command character and any numeric argument, allowing for commands that require a numeric parameter to be processed effectively.
Returns
Returns the command character entered by the user, or a special value if a mouse event is detected. The numeric argument is stored in the variable pointed to by n if applicable.

Definition at line 695 of file view_engine.c.

695 {
696 int c = 0, i = 0;
697 char cmd_str[33];
698 cmd_str[0] = '\0';
700 wmove(view->cmdln_win, view->cmd_line, view->curx);
701 do {
702 c = xwgetch(view->cmdln_win, nullptr, 0);
703 if ((c >= '0' && c <= '9') && i < 32) {
704 cmd_str[i++] = (char)c;
705 cmd_str[i] = '\0';
706 } else {
707 if (c >= 256)
708 return c;
709 else
710 continue;
711 }
712 } while (c >= '0' && c <= '9');
713 *n = atol(cmd_str);
714 view->cmd_arg[0] = '\0';
715 return (c);
716}
int pad_refresh(View *)
Refresh Pad and Line Number Window.

References View::cmd_arg, View::cmd_line, View::cmdln_win, View::curx, pad_refresh(), and xwgetch().

Referenced by view_cmd_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ lp()

void lp ( char * PrintFile)

Send File to Print Queue.

Parameters
PrintFile- file to print

Definition at line 938 of file view_engine.c.

938 {
939 char *print_cmd_ptr;
940 char shell_cmd_spec[MAXLEN];
941 print_cmd_ptr = getenv("PRINTCMD");
942 if (print_cmd_ptr == nullptr || *print_cmd_ptr == '\0')
943 print_cmd_ptr = PRINTCMD;
944 ssnprintf(shell_cmd_spec, MAXLEN - 1, "%s %s", print_cmd_ptr, PrintFile);
945 display_prompt(view, shell_cmd_spec);
946 shell(shell_cmd_spec);
947}
#define PRINTCMD
Definition common.h:44
int shell(char *)
Execute a shell command.
Definition exec.c:82
int display_prompt(View *, char *)
Display Command Line Prompt.

References display_prompt(), shell(), ssnprintf(), and view.

Referenced by view_cmd_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_file()

void remove_file ( View * view)

Remove File.

Parameters
viewis the current view data structure

Definition at line 1935 of file view_engine.c.

1935 {
1936 char c;
1937 if (view->f_at_end_remove) {
1938 wmove(view->pad, view->cmd_line, 0);
1939 waddstr(view->pad, "Remove File (Y or N)->");
1940 wclrtoeol(view->pad);
1941 c = (char)xwgetch(view->cmdln_win, nullptr, -1);
1942 waddch(view->pad, (char)toupper(c));
1943 if (c == 'Y' || c == 'y')
1944 remove(view->cur_file_str);
1945 }
1946}

References View::cmd_line, View::cmdln_win, View::cur_file_str, View::f_at_end_remove, View::pad, and xwgetch().

Here is the call graph for this function:

◆ view_cmd_processor()

int view_cmd_processor ( Init * init)

Main Command Processing Loop for View.

Parameters
initPointer to the Init structure containing initialization parameters and state for the view application. This structure is used to pass necessary information and maintain state across different functions within the view application.

< Ctrl('R') or KEY_RESIZE - Handle terminal resize

< KEY_ALTHOME - horizontal scroll to the first column

< KEY_ALTEND horizontal scroll to the last column

< 'h', Ctrl('H'), KEY_LEFT, KEY_BACKSPACE - Horizontal scroll left by two thirds of the page width

< 'l', 'L', KEY_RIGHT - Horizontal scroll right by two thirds of the page width

'k', 'K', KEY_UP, Ctrl('K') - Scroll up one line

'j', 'J', KEY_DOWN, KEY_ENTER, SPACE - scroll down one line

'b', 'B', Ctrl('B'), KEY_PPAGE - Previous Page

'f', 'F', Ctrl('F'), KEY_NPAGE Next Page

'g', KEY_HOME - Go to the beginning of the document

KEY_LL - Go to the end of the document

'!', Execute Shell Command from within C-Menu View

'+', Set Startup Command

'-', Change View Settings

-i ignore_case in search

-n line numbers

-s squeeze multiple blank lines

-t n set tab stop columns

-h display help

-n line numbers

-s Squeeze Multiple Blank Lines

-t n Set Tab Stop Columns

-h Display Help

Pedantic reassignment of view pointer as the init->view pointer was was reassigned during view_display_help

':' - Set a Prompt String

'n' - Repeat Previous Search

'/' or '?' - Search Forward fromk top of page

'?' - Search Backward

'o' or 'O' - Open a File

'g' or 'G' - Go to the End of the Document

'H' or KEY_F(1) - Display Help Information

'm' - Set a Mark at the Current Position

'M' - Go to a Mark

'N' - Close Current File and Open Next File

'p' or '' - Go to a Percent of the File

Ctrl('Z') - Send File to Print Queue with Notation

'P' or KEY_CATAB or KEY_PRINT - Print Current File

'P' or KEY_F(9) or ESC - Close Current File and Open Next

'q' or 'Q' or KEY_F(9) or ESC - Quit the Application

'v' - Open Current File in Editor

'w' - Write the current buffer to file

'V' - Display Version Information

Definition at line 178 of file view_engine.c.

178 {
179 char tmp_str[MAXLEN];
180 int tfd;
181 int c;
182 int shift = 0;
183 int search_cmd = 0;
184 int prev_search_cmd = 0;
185 int rc, i;
186 ssize_t bytes_written;
187 char *e;
188 char shell_cmd_spec[MAXLEN];
189 off_t n_cmd = 0L;
190 off_t prev_file_pos;
191 int swidth;
192 int max_pmincol;
193 view = init->view;
194 view->cmd[0] = '\0';
195 while (1) {
196 if (view->f_redisplay_page) {
198 view->f_redisplay_page = false;
199 }
200 c = view->next_cmd_char;
201 view->next_cmd_char = 0;
202 if (!c) {
204 display_prompt(view, view->prompt_str);
205 if (view->f_ln) {
206 touchwin(view->ln_win);
207 wrefresh(view->ln_win);
208 }
209 c = get_cmd_char(view, &n_cmd);
210 if (c >= '0' && c <= '9') {
211 tmp_str[0] = (char)c;
212 tmp_str[1] = '\0';
213 c = get_cmd_arg(view, tmp_str);
214 }
215 }
216 switch (c) {
217 case Ctrl(
218 'R'):
219 case 'x':
220 case KEY_RESIZE:
221 getmaxyx(stdscr, view->lines, view->cols);
222#ifdef DEBUG_RESIZE
223 ssnprintf(em0, MAXLEN - 1,
224 "view->page_top_ln=%d, resized to lines: %d, cols: %d\n",
225 view->page_top_ln, view->lines, view->cols);
227#endif
228 if (view->f_full_screen) {
230 } else {
231 view_win_resize(init, view->title);
232 }
233 view->f_redisplay_page = true;
234 continue;
235 case KEY_ALTHOME:
237 view->pmincol = 0;
238 break;
239 case KEY_ALTEND:
242 if (view->maxcol > view->cols)
243 view->pmincol = view->maxcol - view->cols;
244 else
245 view->pmincol = 0;
246 break;
247 case 'h':
249 case Ctrl('H'):
250 case KEY_LEFT:
251 case KEY_BACKSPACE:
252 if (n_cmd <= 0)
253 n_cmd = 1;
254 shift = (int)n_cmd;
255 // swidth = view->smaxcol - view->smincol;
256 if (view->pmincol - shift > 0)
257 view->pmincol -= shift;
258 else
259 view->pmincol = 0;
260 break;
261 case 'l':
263 case 'L':
264 case KEY_RIGHT:
265 if (n_cmd <= 0)
266 n_cmd = 1;
267 shift = (int)n_cmd;
268 swidth = view->smaxcol - view->smincol + 1;
269 if (view->f_ln)
270 max_pmincol = view->maxcol - swidth + 8;
271 else
272 max_pmincol = view->maxcol - swidth;
273 if (view->pmincol + shift < max_pmincol)
274 view->pmincol += shift;
275 else
276 view->pmincol = max_pmincol;
277 break;
278 case 'k':
279 case 'K':
280 case KEY_UP:
281 case Ctrl('K'):
282 if (n_cmd <= 0)
283 n_cmd = 1;
284 scroll_up_n_lines(view, n_cmd);
285 break;
287 case 'j':
288 case 'J':
289 case '\n':
290 case ' ':
291 case KEY_DOWN:
292 case KEY_ENTER:
293 if (n_cmd <= 0)
294 n_cmd = 1;
295 for (i = 0; i < n_cmd; i++) {
297 }
298 break;
300 case KEY_PPAGE:
301 case 'b':
302 case 'B':
303 case Ctrl('B'):
305 break;
307 case 'f':
308 case 'F':
309 case KEY_NPAGE:
310 case Ctrl('F'):
312 break;
314 case 'g':
315 case KEY_HOME:
316 view->pmincol = 0;
317 go_to_line(view, 0);
318 break;
320 case KEY_LL:
322 break;
324 case '!':
325 if (view->f_displaying_help)
326 break;
327 if (get_cmd_arg(view, "!") == 0) {
328 if (!view->f_is_pipe) {
329 view->prev_file_pos = view->page_top_pos;
330 view->next_file_spec_ptr = view->file_spec_ptr;
331 str_subc(shell_cmd_spec, view->cmd_arg, '%',
332 view->cur_file_str, MAXLEN - 1);
333 } else
334 strnz__cpy(shell_cmd_spec, view->cmd_arg, MAXLEN - 1);
335 full_screen_shell(shell_cmd_spec);
336 if (!view->f_is_pipe) {
337 view->next_file_spec_ptr = view->cur_file_str;
338 return 0;
339 }
340 }
341 break;
343 case '+':
344 if (get_cmd_arg(view, "Startup Command:") == 0)
345 strnz__cpy(view->cmd, view->cmd_arg, MAXLEN - 1);
346 break;
348 case '-':
349 display_prompt(view, "(i, n, s, t, or h)->");
350 c = get_cmd_char(view, &n_cmd);
351 c = S_TOLOWER(c);
352 switch (c) {
358 case 'i':
359 display_prompt(view, "Ignore Case in search (Y or N)->");
360 if ((c = get_cmd_char(view, &n_cmd)) == 'y' || c == 'Y')
361 view->f_ignore_case = true;
362 else if (c == 'n' || c == 'N')
363 view->f_ignore_case = false;
364 break;
366 case 'n':
367 if (view->f_ln)
368 view->f_ln = false;
369 else
370 view->f_ln = true;
371 view_win_resize(init, view->title);
372 view->ln = view->page_top_ln;
373 view->file_pos = view->ln_tbl[view->ln];
374 view->maxcol = 0;
375 view->cury = 0;
376 view->page_top_ln = view->ln;
377 mvwaddstr(view->pad, view->cmd_line, 0, " ");
380 break;
382 case 's':
384 view, "view->f_squeeze Multiple Blank lines (Y or N)->");
385 if ((c = get_cmd_char(view, &n_cmd)) == 'y' || c == 'Y')
386 view->f_squeeze = true;
387 else if (c == 'n' || c == 'N')
388 view->f_squeeze = false;
389 break;
391 case 't':
392 sprintf(tmp_str,
393 "Tabstop Colums Currently %d:", view->tab_stop);
394 i = 0;
395 if (get_cmd_arg(view, tmp_str) == 0)
396 i = atoi(view->cmd_arg);
397 if (i >= 1 && i <= 12) {
398 view->tab_stop = i;
399 view->f_redisplay_page = true;
400 } else
401 Perror("Tab stops not changed");
402 break;
404 case 'h':
405 case KEY_F(1):
406 if (!view->f_displaying_help) {
411 view = init->view;
412 }
413 view->next_cmd_char = '-';
414 break;
415 default:
416 break;
417 }
418 break;
420 case ':':
421 view->next_cmd_char = get_cmd_arg(view, ":");
422 break;
424 case 'n':
425 if (prev_search_cmd == 0 || view->f_search_complete) {
426 Perror("No previous search or search complete");
427 break;
428 }
429 if (prev_search_cmd == '/') {
430 view->cury = 0;
431 view->srch_curr_pos = view->page_bot_pos;
432 } else {
433 view->cury = view->scroll_lines + 1;
434 view->srch_curr_pos = view->page_top_pos;
435 }
436 search(view, &prev_search_cmd, prev_regex_pattern);
437 break;
439 case '/':
440 view->f_search_complete = false;
441 strnz__cpy(tmp_str, "(forward)->", MAXLEN - 1);
442 search_cmd = c;
443 c = get_cmd_arg(view, tmp_str);
444 if (c == '\n') {
445 view->cury = 0;
446 view->f_first_iter = true;
447 view->srch_beg_pos = view->page_top_pos;
448 view->srch_curr_pos = view->page_top_pos;
449 search(view, &search_cmd, view->cmd_arg);
450 prev_search_cmd = search_cmd;
452 }
453 break;
455 case '?':
456 view->f_search_complete = false;
457 strnz__cpy(tmp_str, "(backward)->", MAXLEN - 1);
458 search_cmd = c;
459 c = get_cmd_arg(view, tmp_str);
460 if (c == '\n') {
461 view->cury = view->scroll_lines;
462 view->f_first_iter = true;
463 view->srch_beg_pos = view->page_bot_pos;
464 view->srch_curr_pos = view->page_bot_pos;
465 search(view, &search_cmd, view->cmd_arg);
466 prev_search_cmd = search_cmd;
468 }
469 break;
471 case 'o':
472 case 'O':
473 case 'e':
474 case 'E':
475 if (get_cmd_arg(view, "File name:") == 0) {
476 strtok(view->cmd_arg, " ");
477 view->next_file_spec_ptr = strdup(view->cmd_arg);
478 view->f_redisplay_page = true;
479 return 0;
480 }
481 break;
483 case 'G':
484 case KEY_END:
485 if (n_cmd <= 0)
487 else
488 go_to_line(view, n_cmd);
489 break;
491 case 'H':
492 case KEY_F(1):
493 if (!view->f_displaying_help) {
495 view = init->view;
496 }
497 break;
499 case 'm':
500 display_prompt(view, "Mark label (A-Z)->");
501 c = get_cmd_char(view, &n_cmd);
502 if (c == '@' || c == KEY_F(9) || c == '\033')
503 if (c >= 'A' && c <= 'Z')
504 c += ' ';
505 if (c < 'a' || c > 'z')
506 Perror("Not (a-z)");
507 else
508 view->mark_tbl[c - 'a'] = view->page_top_pos;
509 break;
511 case 'M':
512 display_prompt(view, "Goto mark (A-Z)->");
513 c = get_cmd_char(view, &n_cmd);
514 if (c == '@' || c == KEY_F(9) || c == '\033')
515 break;
516 if (c >= 'A' && c <= 'Z')
517 c += ' ';
518 if (c < 'a' || c > 'z')
519 Perror("Not (A-Z)");
520 else
521 go_to_mark(view, c);
522 break;
524 case 'N':
525 if (n_cmd <= 0)
526 n_cmd = 1;
527 if (view->curr_argc + n_cmd >= view->argc) {
528 Perror("no more files");
529 view->curr_argc = view->argc - 1;
530 } else {
531 view->curr_argc++;
532 if (view->curr_argc < view->argc)
533 view->next_file_spec_ptr = view->argv[view->curr_argc];
534 return 0;
535 }
536 break;
538 case 'p':
539 case '%':
540 if (n_cmd < 0)
541 go_to_line(view, 1);
542 if (n_cmd >= 100)
544 else
545 go_to_percent(view, n_cmd);
546 break;
548 case Ctrl('Z'):
549 get_cmd_arg(view, "Enter Notation:");
550 strnz__cpy(tmp_str, "/tmp/view-XXXXXX", MAXLEN - 1);
551 tfd = mkstemp(tmp_str);
552 strnz__cpy(view->tmp_file_name_ptr, tmp_str, MAXLEN - 1);
553 if (tfd == -1) {
554 Perror("Unable to create temporary file");
555 break;
556 }
557 strnz__cpy(shell_cmd_spec, "echo ", MAXLEN - 5);
558 strnz__cat(shell_cmd_spec, view->cmd_arg, MAXLEN - 5);
559 strnz__cat(shell_cmd_spec, view->tmp_file_name_ptr, MAXLEN - 5);
560 shell(shell_cmd_spec);
561 strnz__cpy(shell_cmd_spec, "cat ", MAXLEN - 5);
562 strnz__cat(shell_cmd_spec, view->cmd_arg, MAXLEN - 5);
563 strnz__cat(shell_cmd_spec, ">>", MAXLEN - 5);
564 strnz__cat(shell_cmd_spec, view->tmp_file_name_ptr, MAXLEN - 5);
565 shell(shell_cmd_spec);
566 lp(view->cur_file_str);
567 shell(shell_cmd_spec);
568 ssnprintf(shell_cmd_spec, (size_t)(MAXLEN - 5), "rm %s",
569 view->tmp_file_name_ptr);
570 strnz__cpy(shell_cmd_spec, "rm ", MAXLEN - 5);
571 strnz__cat(shell_cmd_spec, view->tmp_file_name_ptr, MAXLEN - 5);
572 shell(shell_cmd_spec);
573 restore_wins();
574 view->f_redisplay_page = true;
575 unlink(tmp_str);
576 break;
578 case Ctrl('P'):
579 case KEY_CATAB:
580 case KEY_PRINT:
581 lp(view->cur_file_str);
582 view->f_redisplay_page = true;
583 break;
585 case 'P':
586 if (n_cmd <= 0)
587 n_cmd = 1;
588 if (view->curr_argc - n_cmd < 0) {
589 Perror("No previous file");
590 view->curr_argc = 0;
591 } else {
592 view->curr_argc--;
593 if (view->curr_argc >= 0)
594 view->next_file_spec_ptr = view->argv[view->curr_argc];
595 return 0;
596 }
597 break;
599 case 'q':
600 case 'Q':
601 case KEY_F(9):
602 case '\033':
603 view->curr_argc = view->argc;
604 view->next_file_spec_ptr = nullptr;
605 return 0;
607 case 'v':
608 if (init->editor[0] == 0) {
609 e = getenv("DEFAULTEDITOR");
610 if (e == nullptr || *e == '\0')
611 strnz__cpy(init->editor, DEFAULTEDITOR, MAXLEN);
612 else
613 strnz__cpy(init->editor, e, MAXLEN);
614 }
616 "View doesn't support editing current buffer directly",
617 MAXLEN - 1);
618 strnz__cpy(em1, "Would you like to write the buffer to a file?",
619 MAXLEN - 1);
620 strnz__cpy(em2, "Enter Y for yes or any other key to cancel.",
621 MAXLEN - 1);
622 rc = display_error(em0, em1, em2, nullptr);
623 if (rc != 'y' && rc != 'Y')
624 break;
625 if (!enter_file_spec(init, view->out_spec)) {
626 view->f_redisplay_page = true;
627 break;
628 }
629 prev_file_pos = view->page_top_pos;
630 bytes_written = write_view_buffer(init, view->f_strip_ansi);
631 if (bytes_written == 0) {
632 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__,
633 __LINE__ - 2);
634 strnz__cpy(em1, "0 bytes written", MAXLEN - 1);
635 strerror_r(errno, em1, MAXLEN - 1);
636 display_error(em0, em1, nullptr, nullptr);
637 break;
638 }
639 view->next_file_spec_ptr = view->in_spec;
640 strnz__cpy(shell_cmd_spec, init->editor, MAXLEN - 5);
641 strnz__cat(shell_cmd_spec, " ", MAXLEN - 5);
642 strnz__cat(shell_cmd_spec, view->in_spec, MAXLEN - 5);
643 full_screen_shell(shell_cmd_spec);
644 view->file_pos = view->page_top_pos = view->page_bot_pos =
645 prev_file_pos;
646
647 restore_wins();
648 view->f_redisplay_page = true;
649 return 0;
651 case 'w':
652 if (!enter_file_spec(init, view->out_spec)) {
653 view->f_redisplay_page = true;
654 break;
655 }
656 // prev_file_pos = view->page_top_pos;
657 bytes_written = write_view_buffer(init, view->f_strip_ansi);
658 if (bytes_written == 0) {
659 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__,
660 __LINE__ - 2);
661 strnz__cpy(em1, "0 bytes written", MAXLEN - 1);
662 strerror_r(errno, em1, MAXLEN - 1);
663 display_error(em0, em1, nullptr, nullptr);
664 break;
665 }
666 display_prompt(view, tmp_str);
667 view->f_redisplay_page = true;
668 break;
669 case CT_VIEW:
670 break;
672 case 'V':
673 ssnprintf(em0, MAXLEN - 1, "C-Menu Version: %s", CM_VERSION);
674 display_error(em0, em1, nullptr, nullptr);
675 break;
676 default:
677 break;
678 }
679 view->cmd_arg[0] = '\0';
680 }
681}
#define KEY_ALTEND
Definition cm.h:460
#define KEY_ALTHOME
Definition cm.h:457
int cols
#define S_TOLOWER(c)
Definition cm.h:109
int lines
#define Ctrl(c)
Definition cm.h:34
#define CM_VERSION
Definition version.h:7
@ CT_VIEW
Definition menu.h:47
char prev_regex_pattern[MAXLEN]
Definition view_engine.c:80
void view_win_resize(Init *, char *)
Resize the current window and its box, and update the title.
Definition init_view.c:265
void view_full_screen_resize(Init *)
Resize the full screen view and its components.
Definition init_view.c:115
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1162
int full_screen_shell(char *)
Execute a shell command in full screen mode.
Definition exec.c:62
bool str_subc(char *, char *, char, char *, int)
Replaces "ReplaceChr" in "s" with "Withstr" in "d" won't copy more than "l" bytes to "d" Replaces all...
Definition futil.c:581
void write_cmenu_log_nt(char *)
Write message to C-Menu log file without timestamp.
Definition futil.c:1562
void lp(char *)
Send File to Print Queue.
bool enter_file_spec(Init *, char *)
use form to enter a file specification
int write_view_buffer(Init *, bool)
Write buffer contents to files.
int get_cmd_arg(View *, char *)
Get Command Argument from User Input.
int get_cmd_char(View *, off_t *)
Get Command Character and Numeric Argument.
void build_prompt(View *)
Build Prompt String.
void go_to_eof(View *)
Go to End of File.
void prev_page(View *)
display previous page
bool search(View *, int *, char *)
Search for Regular Expression Pattern.
void scroll_down_n_lines(View *, int)
Scroll N Lines.
void scroll_up_n_lines(View *, int)
Scroll Up N Lines.
int go_to_line(View *, off_t)
Go to Specific Line.
void next_page(View *)
Advance to Next Page.
void go_to_mark(View *, int)
Go to Mark.
void go_to_percent(View *, int)
Go to Percent of File.
void view_display_help(Init *)
Display View Help File.
void view_display_page(View *)
Display Current Page.

References View::argc, View::argv, build_prompt(), View::cmd, View::cmd_arg, View::cmd_line, View::cols, CT_VIEW, View::cur_file_str, View::curr_argc, View::cury, display_error(), display_prompt(), Init::editor, em0, em1, em2, enter_file_spec(), View::f_displaying_help, View::f_first_iter, View::f_full_screen, View::f_ignore_case, View::f_is_pipe, View::f_ln, View::f_redisplay_page, View::f_search_complete, View::f_squeeze, View::f_strip_ansi, View::file_pos, View::file_spec_ptr, full_screen_shell(), get_cmd_arg(), get_cmd_char(), go_to_eof(), go_to_line(), go_to_mark(), go_to_percent(), View::in_spec, View::lines, View::ln, View::ln_tbl, View::ln_win, lp(), View::mark_tbl, View::maxcol, View::next_cmd_char, View::next_file_spec_ptr, next_page(), View::out_spec, View::pad, pad_refresh(), View::page_bot_pos, View::page_top_ln, View::page_top_pos, Perror(), View::pmincol, View::prev_file_pos, prev_page(), prev_regex_pattern, View::prompt_str, restore_wins(), scroll_down_n_lines(), View::scroll_lines, scroll_up_n_lines(), search(), shell(), View::smaxcol, View::smincol, View::srch_beg_pos, View::srch_curr_pos, ssnprintf(), str_subc(), strnz__cat(), strnz__cpy(), View::tab_stop, View::title, View::tmp_file_name_ptr, Init::view, view, view_display_help(), view_display_page(), view_full_screen_resize(), view_win_resize(), and write_view_buffer().

Referenced by view_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ view_file()

int view_file ( Init * init)

Start view.

Parameters
initPointer to the Init structure containing initialization parameters and state for the view application. This structure is used to pass necessary information and maintain state across different functions within the view application.
Returns
Returns 0 on successful completion of the view application, or a non-zero value if an error occurs during initialization or execution.

Definition at line 129 of file view_engine.c.

129 {
130 view = init->view;
131 if (view->argc < 1) {
132 view->curr_argc = -1;
133 view->argc = 0;
134 view->next_file_spec_ptr = "-";
135 } else
136 view->next_file_spec_ptr = view->argv[0];
137 while (view->curr_argc < view->argc) {
138 if (view->next_file_spec_ptr == nullptr ||
139 *view->next_file_spec_ptr == '\0') {
140 break;
141 }
142 view->file_spec_ptr = view->next_file_spec_ptr;
143 view->next_file_spec_ptr = nullptr;
144 strnz__cpy(view->cur_file_str, view->file_spec_ptr, MAXLEN - 1);
145 if (view_init_input(view, view->cur_file_str) == 0) {
146 if (view->buf) {
147 view->f_eod = 0;
148 view->f_bod = 0;
149 view->maxcol = 0;
150 view->page_top_pos = 0;
151 view->page_top_ln = 0;
152 view->page_bot_ln = 0;
153 view->ln_max_pos = 0;
154 view->ln = 0;
155 view->page_bot_pos = 0;
156 view->file_pos = 0;
160 munmap(view->buf, view->file_size);
161 }
162 } else {
163 view->curr_argc++;
164 if (view->curr_argc < view->argc) {
165 view->next_file_spec_ptr = view->argv[view->curr_argc];
166 }
167 }
168 }
169 return 0;
170}
int view_init_input(View *, char *)
Initialize the input for a C-Menu View.
Definition init_view.c:443
int view_cmd_processor(Init *)
Main Command Processing Loop for View.
void initialize_line_table(View *)
Initialize Line Table.

References View::argc, View::argv, View::buf, View::cur_file_str, View::curr_argc, View::f_bod, View::f_eod, View::file_pos, View::file_size, View::file_spec_ptr, initialize_line_table(), View::ln, View::ln_max_pos, View::maxcol, View::next_file_spec_ptr, next_page(), View::page_bot_ln, View::page_bot_pos, View::page_top_ln, View::page_top_pos, strnz__cpy(), Init::view, view, view_cmd_processor(), and view_init_input().

Referenced by main(), and popup_view().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_view_buffer()

int write_view_buffer ( Init * init,
bool f_strip_ansi )

Write buffer contents to files.

Parameters
initdata structure
f_strip_ansistrip ANSI escape sequences

write the buffer

Definition at line 879 of file view_engine.c.

879 {
880 ssize_t bytes_written = 0;
881 off_t pos;
882 View *view = init->view;
883 int rc;
884 size_t l;
885 char tmp_line_s[PAD_COLS];
886 if (!f_strip_ansi) {
887 strnz__cpy(em0, "Would you like to strip ansi escape sequences?",
888 MAXLEN - 1);
889 strnz__cpy(em1, "Enter Y for yes or any other key to cancel.",
890 MAXLEN - 1);
891 rc = answer_yn(nullptr, em0, em1, nullptr);
892 if (rc == 'y' || rc == 'Y')
893 f_strip_ansi = true;
894 else
895 f_strip_ansi = false;
896 }
897 restore_wins();
899 pos = 0;
900 view->out_fd = open(view->out_spec, O_CREAT | O_TRUNC | O_WRONLY, 0644);
901 if (view->out_fd == -1) {
902 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
903 strnz__cpy(em1, "fwrite ", MAXLEN - 1);
904 strnz__cat(em1, view->out_spec, MAXLEN - 1);
905 strerror_r(errno, em2, MAXLEN - 1);
906 display_error(em0, em1, em2, nullptr);
907 return false;
908 }
909 bytes_written = 0;
910 while (!view->f_eod) {
911 pos = get_next_line(view, pos);
912 if (f_strip_ansi)
913 strip_ansi(tmp_line_s, view->line_in_s);
914 else
915 strnz__cpy(tmp_line_s, view->line_in_s, MAXLEN - 1);
916 l = strnlf(tmp_line_s, PAD_COLS - 1);
917 bytes_written += write(view->out_fd, tmp_line_s, l);
918 }
919 close(view->out_fd);
920 strnz__cpy(view->in_spec, view->out_spec, MAXLEN - 1);
921 return bytes_written;
922}
int answer_yn(char *em0, char *em1, char *em2, char *em3)
Accept a single letter answer.
Definition dwin.c:1041
size_t strip_ansi(char *, char *)
Strips ANSI SGR escape sequences (ending in 'm') from string s to d.
Definition futil.c:763
size_t strnlf(char *, size_t)
terminates string with line feed
Definition futil.c:524
off_t get_next_line(View *, off_t)
Get Next Line from View->buf.
Definition view.h:37

References answer_yn(), display_error(), em0, em1, em2, View::f_eod, get_next_line(), View::in_spec, View::line_in_s, View::out_fd, View::out_spec, restore_wins(), ssnprintf(), strip_ansi(), strnlf(), strnz__cat(), strnz__cpy(), and Init::view.

Referenced by view_cmd_processor().

Here is the call graph for this function:
Here is the caller graph for this function: