C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
init_view.c
Go to the documentation of this file.
1/** @file init_view.c
2 @brief Initialize C-Menu View Screen IO and Input
3 @ingroup init_view
4 @author Bill Waller
5 Copyright (c) 2025
6 MIT License
7 billxwaller@gmail.com
8 @date 2026-02-09
9 */
10
11/**
12 @defgroup init_view Initializing View I/O
13 @brief Populate the C-Menu View Struct and Connect Input
14 */
15#include <common.h>
16#include <errno.h>
17#include <fcntl.h>
18#include <stddef.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/mman.h>
22#include <sys/stat.h>
23#include <sys/sysmacros.h>
24#include <unistd.h>
25#include <wait.h>
26
28void view_full_screen_resize(Init *);
30void view_boxwin_resize(Init *);
31
32ViewStack view_stack;
33
34/** @brief Initialize C-Menu View in full screen mode.
35 @ingroup init_view
36 @param init Pointer to the Init structure containing view settings.
37 @return 0 on success, -1 on failure.
38 @details This function sets up the view structure for full screen mode and
39 creates a new pad for the view.
40 @verbatim
41 The function creates the following windows:
42 1. view->cmdln_win: Status or Command Line
43 2. view->lnno_win: Line Number Window
44 3. view->pad: Main Content Pad
45 @endverbatim
46 */
47int init_view_full_screen(Init *init) {
48 View *view = init->view;
49 view->f_full_screen = true;
50 // -------------------> 1. WIN <-------------------
52 view->sfc = ui_surface_new(WIN, NULL, 0, view->lines, view->cols, 0, 0);
53 if (!view->sfc) {
54 ssnprintf(em0, MAXLEN - 1, "newwin(LINES, COLS, 0, 0) failed in init_view_full_screen");
56 return -1;
57 }
59 // -------------------> 2. LNNO <-------------------
61 if (view->sfc->lnno == nullptr) {
62 ssnprintf(em0, MAXLEN - 1, "ui_sfc_addwin(LNNO, LINES - 1, COLS, 0, 0) failed in init_view_full_screen");
64 return -1;
65 }
70 // -------------------> 3. CMDLN <-------------------
72 if (view->sfc->cmdln == nullptr) {
73 ssnprintf(em0, MAXLEN - 1, "ui_sfc_addwin(CMDLN, 1, COLS, LINES - 1, 0) failed in init_view_full_screen");
75 return -1;
76 }
79 ui_idlok(view->sfc, CMDLN, false);
80 ui_idcok(view->sfc, CMDLN, false);
82 // -------------------> 4. PAD <-------------------
83
85
86 // ------------------------------------------------
87 return 0;
88}
89/** @brief Resize the full screen view and its components.
90 @ingroup window_support
91 @param init Pointer to the Init structure containing view settings.
92 @details This function resizes the full screen view and its components,
93 including the command line window, line number window, and main content pad.
94 It also recalculates the dimensions for the full screen mode and updates the
95 scroll regions accordingly.
96 */
97void view_full_screen_resize(Init *init) {
100 View *view = init->view;
104}
105/** @brief Calculate the dimensions for full screen mode.
106 @ingroup init_view
107 @details This function calculates the dimensions for the full screen mode of
108 the C-Menu View. It retrieves the maximum dimensions of the standard screen
109 and sets the view parameters accordingly. It also resizes the line number
110 window and command line window based on the new dimensions.
111 @param init Pointer to the Init structure containing view settings.
112 */
114 View *view = init->view;
116 view->ln_win_lines = view->lines;
117 view->ln_win_cols = 8;
118 view->scroll_lines = view->lines - 1;
119 view->h_shift = view->cols / 3;
120#ifdef DEBUG_RESIZE
121 char file[MAXLEN];
122 ssnprintf(
123 em0, MAXLEN - 1,
124 "%s:%d view->lines=%d, view->cols=%d, view->maxrows=%d, view->maxcols=%d",
125 __FILE__, __LINE__,
126 view->lines, view->cols, view->smaxrow, view->smaxcol);
127 write_cmenu_log(em0);
128#endif
129 view->cmd_line = 0;
130 view->pminrow = 0;
131 view->pmincol = 0;
132 view->sminrow = 0;
133 view->smincol = view->ln_win_cols;
134 view->smaxrow = view->lines - 1;
135 view->smaxcol = view->cols - 1;
137 view->page_bot_ln_no = view->ln_no;
138}
139/** @brief Initialize the C-Menu View in box window mode.
140 @ingroup init_view
141 @param init Pointer to the Init structure containing view settings.
142 @return 0 on success, -1 on failure.
143 @details sets up the view structure for box window mode, adjusts dimensions
144 based on screen size, and creates a new pad for the view. It also configures
145 various parameters such as scroll lines, command line position, and tab size.
146 */
147int init_view_boxwin(Init *init) {
148 View *view = init->view;
149 view->f_full_screen = false;
150 // -------------------> 1. BOX / WIN <-------------------
152 view->sfc = ui_box_surface_new(NULL, 0, view->lines, view->cols, view->begy, view->begx, NULL);
154 // -------------------> 2. LNNO <-------------------
158 ui_scrollok(view->sfc, LNNO, true);
160 // -------------------> 3. CMDLN <-------------------
163 ui_keypad(view->sfc, CMDLN, true);
164 ui_idlok(view->sfc, CMDLN, false);
165 ui_idcok(view->sfc, CMDLN, false);
166 ui_scrollok(view->sfc, CMDLN, false);
167 // -------------------> 4. PAD <-------------------
169 // ------------------------------------------------
170 return (0);
171}
172//------------------------------------------------------------------------------
173/** @brief Resize the current window and its box
174 @ingroup window_support
175 @param init Pointer to the Init structure containing view settings.
176 @details This function resizes the current window and its associated box
177 window to the specified number of lines and columns. */
178void view_boxwin_resize(Init *init) {
179 View *view = init->view;
184 // initialize_line_table(init->view);
185}
186/** @brief Calculate the dimensions and position of the box window for C-Menu
187 View.
188 @ingroup init_view
189 @details This function calculates the dimensions and position of the box
190 window for the C-Menu View based on the screen size and any specified
191 parameters in the Init structure. It ensures that the box window fits within
192 the screen dimensions and adjusts its size and position accordingly.
193 @param init Pointer to the Init structure containing view settings.
194 */
196 View *view = init->view;
197
198 /** Use view->lines and view->cols if set, otherwise calculate based on
199 * screen size with some padding. Ensure the view fits within the screen
200 * dimensions. */
201 uint scr_lines, scr_cols;
202 ui_get_screen_size(&scr_lines, &scr_cols);
203#ifdef DEBUG_RESIZE
204 ssnprintf(em0, MAXLEN - 1,
205 "%s:%d=%d calc lines=%d, cols=%d, begy=%d, begx=%d",
206 __FILE__, __LINE__, 526, view->lines, view->cols, view->begy, view->begx);
207 write_cmenu_log(em0);
208#endif
209 if (view->lines == 0 && view->cols == 0 && view->begy == 0 && view->begx == 0) {
210 view->lines = scr_lines - 3;
211 view->cols = scr_cols - 2;
212 view->begy = 0;
213 view->begx = 0;
214 }
215 uint lines = max(scr_lines / 10, 8);
216 view->lines = max(view->lines, lines);
217 if (view->lines > scr_lines - 3)
218 view->lines = scr_lines - 3;
219 if (view->lines + view->begy > scr_lines - 3)
220 view->begy = scr_lines - (view->lines + 3);
221
222 uint cols = max(scr_cols / 3, 40);
223 view->cols = max(view->cols, cols);
224 if (view->cols > scr_cols - 2)
225 view->cols = scr_cols - 2;
226 if (view->cols + view->begx > scr_cols - 2)
227 view->begx = scr_cols - (view->cols + 2);
228
229 view->h_shift = view->cols / 3;
230 view->ln_win_lines = view->lines - 1;
231 if (view->f_ln)
232 view->ln_win_cols = 8;
233 else
234 view->ln_win_cols = 0;
235 view->scroll_lines = view->lines - 1;
236 view->cmd_line = 0;
237 view->pminrow = 0;
238 view->pmincol = 0;
239 view->sminrow = view->begy + 1;
240 view->smincol = view->begx + view->ln_win_cols + 1;
241 view->smaxrow = view->begy + view->lines;
242 view->smaxcol = view->begx + view->cols;
244 view->page_bot_ln_no = view->ln_no;
245#ifdef DEBUG_RESIZE
246 ssnprintf(em0, MAXLEN - 1,
247 "%s:%d calc BOX lines=%d, cols=%d, begy=%d, begx=%d",
248 __FILE__, __LINE__, view->lines + 2, view->cols + 2, view->begy, view->begx);
249 write_cmenu_log(em0);
250 ssnprintf(em0, MAXLEN - 1,
251 "%s:%d calc WIN lines=%d, cols=%d, begy=%d, begx=%d",
252 __FILE__, __LINE__, view->lines, view->cols, 1, 1);
253 write_cmenu_log(em0);
254 ssnprintf(em0, MAXLEN - 1,
255 "%s:%d calc CMDLN lines=%d, cols=%d, begy=%d, begx=%d",
256 __FILE__, __LINE__, 1, view->cols, view->lines - 1, 1);
257 write_cmenu_log(em0);
258 ssnprintf(em0, MAXLEN - 1,
259 "%s:%d calc LNNO lines=%d, cols=%d, begy=%d, begx=%d",
260 __FILE__, __LINE__, view->lines - 1, view->ln_win_cols, 0, 0);
261 write_cmenu_log(em0);
262 ssnprintf(em0, MAXLEN - 1,
263 "%s:%d calc PAD lines=%d, cols=%d, begy=%d, begx=%d",
264 __FILE__, __LINE__, view->lines - 1, view->cols - view->ln_win_cols, 0, view->ln_win_cols);
265 write_cmenu_log(em0);
266
267#endif
268}
269/** @brief Initialize the input for the C-Menu View.
270 @ingroup init_view
271 @param init Pointer to the Init structure containing view settings.
272 @param file_name Name of the input file or "-" for standard input.
273 @return 0 on success, -1 on failure.
274 @details This function initializes the input for the C-Menu View. It handles
275 both regular files and standard input, setting up pipes if necessary. It also
276 memory-maps the input file for efficient access and sets up the view structure
277 accordingly.
278 */
279int view_init_input(Init *init, char *file_name) {
280 struct stat sb;
281 int idx = 0;
282 pid_t pid = -1;
283 int pipe_fd[2];
284 int s_argc = 0;
285 char *s_argv[MAXARGS];
286 char tmp_str[MAXLEN];
287 View *view = init->view;
288 view->f_in_pipe = false;
289 if (strcmp(file_name, "-") == 0) {
290 file_name = "/dev/stdin";
291 view->f_in_pipe = true;
292 }
293 if (view->provider_cmd[0] != '\0') {
294 s_argc = str_to_args(s_argv, view->provider_cmd, MAXARGS - 1);
295 if (pipe(pipe_fd) == -1) {
296 Perror("pipe(pipe_fd) failed in init_view");
297 return -1;
298 }
299 // endwin();
300 if ((pid = fork()) == -1) {
301 Perror("fork() failed in init_view");
302 return -1;
303 }
304 if (pid == 0) { // Child
305 /** Prevent child process from writing to terminal */
306 int dev_null = open("/dev/null", O_WRONLY);
307 if (dev_null == -1) {
308 Perror("open(/dev/null) failed in init_pick child process");
309 exit(EXIT_FAILURE);
310 }
311 dup2(dev_null, STDERR_FILENO);
312 close(dev_null);
313 close(pipe_fd[P_READ]);
314 dup2(pipe_fd[P_WRITE], STDOUT_FILENO);
315 close(pipe_fd[P_WRITE]);
316 execvp(s_argv[0], s_argv);
317 strnz__cpy(tmp_str, "Can't exec view start cmd: ", MAXLEN - 1);
318 strnz__cat(tmp_str, s_argv[0], MAXLEN - 1);
319 Perror(tmp_str);
320 exit(EXIT_FAILURE);
321 }
322 // Back to parent
323 destroy_argv(s_argc, s_argv);
326 close(pipe_fd[P_WRITE]);
327 view->in_fd = dup(pipe_fd[P_READ]);
328 view->f_in_pipe = true;
329 } else {
330 if (view->f_in_pipe)
331 view->in_fd = dup(STDIN_FILENO);
332 else {
333 /*----------------------------------------------------------------------*/
334 /* Open the input file for reading and get its size. */
335 expand_tilde(file_name, MAXLEN - 1);
336 view->in_fd = open(file_name, O_RDONLY);
337 if (view->in_fd == -1) {
338 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__,
339 __LINE__ - 3);
340 ssnprintf(em1, MAXLEN - 1, "open %s", file_name);
341 strerror_r(errno, em2, MAXLEN);
343 return -1;
344 }
345 if (fstat(view->in_fd, &sb) == -1) {
346 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__,
347 __LINE__ - 1);
348 ssnprintf(em1, MAXLEN - 1, "fstat %s", file_name);
349 strerror_r(errno, em2, MAXLEN);
351 close(view->in_fd);
352 return -1;
353 }
354 view->file_size = sb.st_size;
355 if (view->file_size == 0) {
356 close(view->in_fd);
357 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__,
358 __LINE__ - 1);
359 ssnprintf(em1, MAXLEN - 1, "file %s is empty", file_name);
360 strerror_r(errno, em2, MAXLEN);
362 return -1;
363 }
364 if (!S_ISREG(sb.st_mode))
365 view->f_in_pipe = true;
366 }
367 /*----------------------------------------------------------------------*/
368 }
369 if (view->f_in_pipe) {
370 errno = 0;
371 view->tmp_fd = memfd_create("view_input", MFD_CLOEXEC);
372 if (view->in_fd < 0 || errno != 0) {
373 ssnprintf(em0, MAXLEN - 1, "memfd_create failed\n");
374 ssnprintf(em1, MAXLEN - 1, "%s", strerror(errno));
375 ssnprintf(em2, MAXLEN - 1, "%s, line: %d, errno: %d", __FILE__,
376 __LINE__ - 4, errno);
378 exit(EXIT_FAILURE);
379 }
380 char buf[VBUFSIZ];
381 ssize_t bytes_read = 0;
382 ssize_t bytes_written = 0;
383 while ((bytes_read = read(view->in_fd, buf, sizeof(buf))) > 0) {
384 if ((bytes_written = write(view->tmp_fd, buf, bytes_read)) != bytes_read) {
385 abend(-1, "unable to write view->tmp_fd");
386 exit(EXIT_FAILURE);
387 }
388 }
389 if (fstat(view->tmp_fd, &sb) == -1) {
390 ssnprintf(em0, MAXLEN - 1, "fstat(view->in_fd) failed\n");
391 ssnprintf(em1, MAXLEN - 1, "%s", strerror(errno));
392 ssnprintf(em2, MAXLEN - 1, "%s, line: %d, errno: %d", __FILE__,
393 __LINE__ - 4, errno);
395 exit(EXIT_FAILURE);
396 }
397 view->file_size = sb.st_size;
398 if (view->file_size == 0) {
399 close(view->tmp_fd);
400 strnz__cpy(tmp_str, "no standard input", MAXLEN - 1);
401 abend(-1, tmp_str);
402 exit(EXIT_FAILURE);
403 }
404 waitpid(-1, nullptr, 0);
405 view->in_fd = view->tmp_fd;
406 }
407 view->buf =
408 mmap(nullptr, view->file_size, PROT_READ, MAP_PRIVATE, view->in_fd, 0);
409 if (view->buf == MAP_FAILED) {
410 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
411 ssnprintf(em1, MAXLEN - 1, "mmap %s", file_name);
412 strerror_r(errno, em2, MAXLEN);
414 close(view->in_fd);
415 return -1;
416 }
417 close(view->in_fd);
418 stdio_fdnames(stdio_names_str, "init_view.c 422");
419 view->file_size = sb.st_size;
421 view->buf_curr_ptr = view->buf;
422 if (view->cmd_all[0] != '\0')
424 for (idx = 0; idx < NMARKS; idx++)
425 view->mark_tbl[idx] = NULL_POSITION;
426 strnz__cpy(view->cur_file_str, file_name, MAXLEN - 1);
428 return 0;
429}
#define P_READ
Definition common.h:50
#define P_WRITE
Definition common.h:51
char stdio_names_str[4096]
Definition futil.c:127
#define MAXARGS
Definition cm.h:50
char * stdio_fdnames(char *, char *)
Definition futil.c:1082
#define max(a, b)
max macro evaluates two expressions, returning greatest result.
Definition cm.h:84
void ui_render()
Definition ui_ncurses.c:800
int ui_bkgdset(UiSurface *s, uint w, const UiCell *cell)
Definition ui_ncurses.c:760
UiSurface * ui_surface_new(uint w, UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x)
Definition ui_ncurses.c:414
int ui_setscrreg(UiSurface *s, uint w, uint top, uint bottom)
Definition ui_ncurses.c:662
int ui_scrollok(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:626
int ui_bkgd(UiSurface *s, uint w, const UiCell *cell)
Definition ui_ncurses.c:753
void ui_surface_destroy(UiSurface *s)
Definition ui_ncurses.c:377
int ui_idlok(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:644
void ui_restore_wins()
void ui_get_screen_size(uint *lines, uint *cols)
Definition ui_ncurses.c:692
int ui_erase()
Definition ui_ncurses.c:590
UiSurface * ui_box_surface_new(UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x, char *title)
Definition ui_ncurses.c:453
int ui_keypad(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:635
int ui_idcok(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:653
int ui_surface_addpad(UiSurface *s, uint w, uint view_win, uint lines, uint cols)
Definition ui_ncurses.c:509
int ui_surface_addwin(UiSurface *s, uint w, uint p, uint lines, uint cols, uint y, uint x)
Definition ui_ncurses.c:523
#define NMARKS
Definition view.h:35
#define VBUFSIZ
Definition view.h:39
#define PAD_COLS
Definition view.h:41
#define NULL_POSITION
Definition view.h:38
ViewStack view_stack
Definition init_view.c:32
#define MAXLEN
Definition curskeys.c:15
UiCell cell_nt
Definition dwin.c:94
char em1[MAXLEN]
Definition dwin.c:143
char em2[MAXLEN]
Definition dwin.c:144
UiCell cell_ln
Definition dwin.c:102
char em0[MAXLEN]
Definition dwin.c:142
void view_full_screen_resize(Init *)
Resize the full screen view and its components.
Definition init_view.c:97
void view_boxwin_resize(Init *)
Resize the current window and its box.
Definition init_view.c:178
int border_title(UiSurface *sfc, char *title)
Draw a box with a title around the specified window.
Definition dwin.c:676
int Perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition dwin.c:841
void abend(int ec, char *s)
Abnormal program termination.
Definition dwin.c:1204
int display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition dwin.c:778
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:537
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:413
int str_to_args(char **, char *, uint)
Converts a string into an array of argument strings.
Definition futil.c:433
bool expand_tilde(char *, uint)
Replaces "~/" in string with the user's home directory.
Definition futil.c:963
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:566
int destroy_argv(uint argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:487
bool base_name(char *, char *)
Returns the base name of a file specification.
Definition futil.c:1106
void view_calc_boxwin_dimensions(Init *)
Calculate the dimensions and position of the box window for C-Menu View.
Definition init_view.c:195
int init_view_full_screen(Init *init)
Initialize C-Menu View in full screen mode.
Definition init_view.c:47
int init_view_boxwin(Init *init)
Initialize the C-Menu View in box window mode.
Definition init_view.c:147
void view_calc_full_screen_dimensions(Init *)
Calculate the dimensions for full screen mode.
Definition init_view.c:113
int view_init_input(Init *init, char *file_name)
Initialize the input for the C-Menu View.
Definition init_view.c:279
void sig_prog_mode()
Set up signal handlers for interrupt signals.
Definition sig.c:62
View * view
Definition common.h:189
uint smaxrow
Definition view.h:144
char provider_cmd[MAXLEN]
Definition view.h:76
uint sminrow
Definition view.h:140
off_t page_top_ln_no
Definition view.h:169
char * buf
Definition view.h:183
uint smincol
Definition view.h:142
int in_fd
Definition view.h:175
uint lines
Definition view.h:72
off_t ln_no
Definition view.h:194
off_t prev_file_pos
Definition view.h:163
uint begx
Definition view.h:75
char cmd[MAXLEN]
Definition view.h:78
bool f_in_pipe
Definition view.h:174
int tmp_fd
Definition view.h:176
char * buf_curr_ptr
Definition view.h:184
bool f_full_screen
Definition view.h:120
bool f_ln
Definition view.h:193
off_t mark_tbl[NMARKS]
Definition view.h:173
uint cmd_line
Definition view.h:136
uint ln_win_cols
Definition view.h:192
off_t file_size
Definition view.h:161
uint scroll_lines
Definition view.h:135
char cur_file_str[MAXLEN]
Definition view.h:125
char title[MAXLEN]
Definition view.h:81
uint cols
Definition view.h:73
char cmd_all[MAXLEN]
Definition view.h:79
off_t page_bot_ln_no
Definition view.h:170
uint begy
Definition view.h:74
int h_shift
Definition view.h:108
uint pmincol
Definition view.h:139
uint smaxcol
Definition view.h:146
UiSurface * sfc
Definition view.h:101
char file_name[MAXLEN]
Definition view.h:115
uint ln_win_lines
Definition view.h:191
uint pminrow
Definition view.h:138