C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
pick_engine.c
Go to the documentation of this file.
1/** @file pick_engine.c
2 @brief pick from a list of choices
3 @author Bill Waller
4 Copyright (c) 2025
5 MIT License
6 billxwaller@gmail.com
7 @date 2026-02-09
8 */
9
10/** @defgroup pick_engine Object Selection
11 @brief Navigate, Select, and Perform Action on Objects
12 */
13
14#include "common.h"
15#include <fcntl.h>
16#include <stdbool.h>
17#include <string.h>
18#include <sys/mman.h>
19#include <sys/stat.h>
20#include <sys/wait.h>
21#include <termios.h>
22#include <unistd.h>
25int pick_engine(Init *);
26void save_object(Pick *, char *);
27int picker(Init *, char *field);
28void display_pick_page(Pick *);
29void reverse_object(Pick *);
30void unreverse_object(Pick *);
31void toggle_object(Pick *);
32int output_objects(Pick *);
33int exec_objects(Init *);
34int open_pick_win(Init *);
35void display_pick_help(Init *);
36int read_pick_input(Init *);
37void deselect_object(Pick *);
38int read_theme(Init *);
39int new_pick_view(Init *);
40void new_view_file(Init *, char *);
41void end_pick_view(Init *);
42void destroy_pick_view(Init *);
43int match_objects(Pick *pick, char *s);
44void remove_right_angle(Pick *);
45void pick_std_chyron(Pick *);
46int pipe_fd[2];
47
48UiMultiMedia ui_mm;
49
50char const pagers_editors[12][10] = {"view", "view", "less", "more",
51 "vi", "vim", "nano", "nvim",
52 "pico", "emacs", "edit", ""};
53
54/** @brief Initializes pick structure and opens pick input file or pipe
55 * @ingroup pick_engine
56 @param init Pointer to Init structure
57 @param argc Argument count
58 @param argv Argument vector
59 @param by Beginning y coordinate for pick window
60 @param bx Beginning x coordinate for pick window
61 @details If provider_cmd is specified, it takes precedence over in_spec and
62 input file arguments.
63 provider_cmd is executed and its output is read as pick input
64 If provider_cmd is not specified, in_spec is used to read pick
65 input from a file or stdin
66 If provider_cmd is specified, it is executed and its output is
67 read as pick input */
68int init_pick(Init *init, int argc, char **argv, uint by, uint bx) {
69 struct stat sb;
70 char *s_argv[MAXARGS];
71 int s_argc;
72 char tmp_str[MAXLEN];
73 pid_t pid = 0;
74
75 Pick *pick = new_pick(init, argc, argv, by, bx);
76 if (init->pick != pick)
77 ui_abend(-1, "init->pick != pick\n");
78 // SIO *sio = init->sio;
79 if (pick->provider_cmd[0] != '\0') {
80 s_argc = str_to_args(s_argv, pick->provider_cmd, MAXARGS - 1);
81 if (pipe(pipe_fd) == -1) {
82 ui_perror(_("pipe(pipe_fd) failed in init_pick"));
83 return (1);
84 }
85
86 if ((pid = fork()) == -1) {
87 ui_perror(_("fork() failed in init_pick"));
88 return (1);
89 }
90 if (pid == 0) {
91 /** Prevent child process from writing to terminal */
92 int dev_null = open("/dev/null", O_WRONLY);
93 if (dev_null == -1) {
94 ui_perror(_("open(/dev/null) failed in init_pick child process"));
95 exit(EXIT_FAILURE);
96 }
97 dup2(dev_null, STDERR_FILENO);
98 /** Close read end of pipe as Child only needs to write to pipe */
99 close(dev_null);
100 close(pipe_fd[P_READ]);
101 /** Connect CHILD STDOUT to write end of pipe */
102 dup2(pipe_fd[P_WRITE], STDOUT_FILENO);
103 /** STDOUT attached to write end of pipe, so close pipe fd */
104 close(pipe_fd[P_WRITE]);
105 execvp(s_argv[0], s_argv);
106 strnz__cpy(tmp_str, _("Can't exec pick start cmd: "), MAXLEN - 1);
107 strnz__cat(tmp_str, s_argv[0], MAXLEN - 1);
108 ui_perror(tmp_str);
109 exit(EXIT_FAILURE);
110 }
111 /** Return to Parent
112 Close write end of pipe as Parent only needs to read from pipe */
113 /** Open a file pointer on read end of pipe */
114 close(pipe_fd[P_WRITE]);
115 pick->in_fp = fdopen(pipe_fd[P_READ], "rb");
116 pick->f_in_pipe = true;
117 destroy_argv(s_argc, s_argv);
118 } else {
119 if ((pick->in_spec[0] == '\0') || strcmp(pick->in_spec, "-") == 0 || strcmp(pick->in_spec, "/dev/stdin") == 0) {
120 strnz__cpy(pick->in_spec, "/dev/stdin", MAXLEN - 1);
121 pick->in_fp = fdopen(STDIN_FILENO, "rb");
122 pick->f_in_pipe = true;
123 }
124 }
125 stdio_fdnames(stdio_names_str, "pick_engine.c 122");
126 if (!pick->f_in_pipe) {
127 /** No provider_cmd specified, so read pick input from file or stdin */
128 if (lstat(pick->in_spec, &sb) == -1) {
129 strnz__cpy(tmp_str, _("Can\'t stat pick input file: "), MAXLEN - 1);
130 strnz__cat(tmp_str, pick->in_spec, MAXLEN - 1);
131 ui_perror(tmp_str);
132 return (1);
133 }
134 if (sb.st_size == 0) {
135 strnz__cpy(tmp_str, _("Pick input file empty: "), MAXLEN - 1);
136 strnz__cat(tmp_str, pick->in_spec, MAXLEN - 1);
137 ui_perror(tmp_str);
138 return (1);
139 }
140 if ((pick->in_fp = fopen(pick->in_spec, "rb")) == nullptr) {
141 strnz__cpy(tmp_str, _("Can't open pick input file: "), MAXLEN - 1);
142 strnz__cat(tmp_str, pick->in_spec, MAXLEN - 1);
143 ui_perror(tmp_str);
144 return (1);
145 }
146 }
147 /*------------------------------------------------------------*/
148 if (pick->in_fp == nullptr) {
149 ui_perror(_("No pick input available"));
150 return (1);
151 }
152 /*------------------------------------------------------------*/
154 if (pick->f_in_pipe && pid > 0) {
155 waitpid(pid, nullptr, 0);
156 // restore_program_tioctl();
157 // sig_prog_mode();
158 }
159 close(pipe_fd[P_READ]);
160 stdio_fdnames(stdio_names_str, "pick_engine.c 160");
161 if (pick->m_cnt == 0) {
162 ui_perror(_("No pick objects available"));
163 return (1);
164 }
165
166 // Open Pick Window so we can build chyron
167 if (open_pick_win(init)) {
168 ui_perror(_("Failed to open pick window"));
169 exit(EXIT_FAILURE);
170 }
171 init->view = nullptr;
172
173 pick_engine(init);
175 if (pick->p_view_files) {
176 if (init->view) {
178 init->view = nullptr;
179 }
180#ifdef NOTCURSES_UI
181 if (ui_mm.ncv != nullptr) {
182 ncvisual_destroy(ui_mm.ncv);
183 ui_mm.ncv = nullptr;
184 }
185 if (ui_mm.sfc != nullptr) {
186 ui_surface_destroy(ui_mm.sfc);
187 ui_mm.sfc = nullptr;
188 }
189#endif
191 }
192 return 0;
193}
194
195/** @brief Destroys pick view, unmaps file buffer, and cleans up resources
196 * @ingroup pick_engine
197 @param init Pointer to Init structure containing pick information
198 @details If pick->p_view_files is true and view->buf is not nullptr, destroys
199 line table, unmaps the file buffer, and sets view->buf to nullptr. Destroys
200 view window and view structure to free associated resources.
201 */
202void destroy_pick_view(Init *init) {
203 if (!init->view)
204 return;
205 View *view = init->view;
206 Pick *pick = init->pick;
208 if (pick->p_view_files) {
209 if (view->buf != nullptr) {
211 munmap(view->buf, view->file_size);
212 view->buf = nullptr;
213 }
214 }
215 destroy_view(init);
216}
217/** @brief Reads pick input from file pointer and saves objects into pick
218 structure
219 * @ingroup pick_engine
220 @param init Pointer to Init structure containing pick information
221 @return 0 on success, -1 if no objects were read
222 @details Reads lines from pick->in_fp and saves them as objects in the pick
223 structure using save_object function. If no objects are read, returns -1.
224 Otherwise, sets obj_cnt to the number of objects read and resets obj_idx to 0
225 before returning 0. */
226int read_pick_input(Init *init) {
227 int i;
228
229 Pick *pick = init->pick;
230 pick->select_cnt = 0;
231 pick->tbl_pages = 1;
232
233 if (pick->in_fp) {
234 while (fgets(pick->in_buf, sizeof(pick->in_buf), pick->in_fp) != nullptr)
235 save_object(pick, pick->in_buf);
236
237 } else
238 for (i = 1; i < pick->argc; i++)
239 save_object(pick, pick->argv[i]);
240 if (pick->in_fp != nullptr)
241 fclose(pick->in_fp);
242 if (!pick->m_idx)
243 return (-1);
244 pick->m_cnt = pick->m_idx;
245 return 0;
246}
247int open_pick_win(Init *init) {
248 uint maxy, maxx;
249 uint whitespace_ratio = 15;
250 uint usable_lines;
251 uint pick_ratio = 50;
252 uint tbl_max_cols, pg_max_objs;
253
254 Pick *pick = init->pick;
255 ui_get_screen_size(&maxy, &maxx);
256 // Screen Geometry
257 // Calculate pick window size and position based on terminal size and pick
258 // parameters
259 //
260 // Calculate line usage:
261 if (pick->begy == 0)
262 pick->begy = (maxy * whitespace_ratio) / 200;
263 usable_lines = maxy - (maxy * whitespace_ratio) / 100;
264 usable_lines -= pick->begy;
265 usable_lines -= 5; // Pick overhead lines
266 if (pick->p_view_files) {
267 if (pick->lines == 0) {
268 pick->lines = usable_lines * pick_ratio / 100;
269 usable_lines -= pick->lines;
270 }
271 init->begy = pick->begy + 5 + pick->lines;
272 init->begx = 0;
273 usable_lines -= 3; // View overhead lines
274 init->lines = usable_lines;
275 init->cols = maxx - 2;
276 } else if (pick->lines == 0)
277 pick->lines = usable_lines;
278
279 pick->tbl_col_width = max(pick->tbl_col_width, 4);
280 pick->tbl_col_width = min(pick->tbl_col_width, (maxx - (2 + pick->begx)));
281 pick->m_idx = 0; // master index
282 pick->d_idx = 0; // display index
283 while (pick->m_idx < pick->m_cnt)
284 pick->d_object[pick->d_idx++] = pick->m_object[pick->m_idx++];
285 pick->d_cnt = pick->d_idx;
286 if (pick->d_cnt <= pick->lines) {
287 pick->tbl_lines = pick->d_cnt;
288 pick->lines = pick->d_cnt;
289 pick->tbl_cols = 1;
290 } else {
291 tbl_max_cols = ((maxx - (2 + pick->begx)) / (pick->tbl_col_width + 1));
292 pg_max_objs = pick->lines * tbl_max_cols;
293 if (pick->d_cnt > pg_max_objs)
294 pick->tbl_cols = tbl_max_cols;
295 else
296 pick->tbl_cols = pick->d_cnt / pick->lines;
297 pick->tbl_lines = pick->d_cnt / tbl_max_cols;
298 }
299 pick->tbl_pages = (pick->tbl_lines / (pick->lines - 1)) + 1;
300 // pick->lines = (pick->tbl_lines + pick->tbl_pages - 1) / pick->tbl_pages;
301 pick->tbl_page = 0;
302 // if (pick->begy == 0)
303 // pick->begy = (LINES - pick->lines) / 5;
304 // else if (pick->begy + pick->lines > LINES - 4)
305 // pick->begy = LINES - pick->lines - 2;
306 pick->width = (pick->tbl_col_width + 1) * pick->tbl_cols;
307
308 pick->width = max(pick->width, 60);
309 char tmp_str[MAXLEN];
310
311 int ui_split_win_lines = 2;
312 if (ui_tracked_sfc_split_box(pick->lines, pick->width, ui_split_win_lines, 0, pick->begy, pick->begx, pick->title)) {
313 ssnprintf(tmp_str, MAXLEN - 1, "ui_tracked_sfc_split_box(%d, %d, %d, %d, %d, %d, %s) failed",
314 pick->lines, pick->width, ui_split_win_lines, 0, pick->begy, pick->begx, pick->title);
315 ui_perror(tmp_str);
316 return (1);
317 }
319 UiSurface *sfc = pick->surface;
320 ui_setscrreg(sfc, WIN, 0, pick->lines - 1);
321 ui_scrollok(sfc, WIN, true);
322 ui_keypad(sfc, WIN, true);
323 pick->separator_line = pick->lines + 1;
324
325 pick->x = 1;
326
327 pick->chyron = ui_new_chyron(pick->surface, WIN2);
329 ui_set_chyron_key(pick->chyron, 2, _("F9 Cancel"),
331 ui_set_chyron_key(pick->chyron, 3, _("F10 Accept"),
333 ui_set_chyron_key(pick->chyron, 4, _("F11 View"),
335 ui_set_chyron_key(pick->chyron, 5, _("<q> Quit View"),
336 'q');
337 ui_set_chyron_key(pick->chyron, 6, _("<Sp> Process"), ' ');
338 ui_set_chyron_key(pick->chyron, 7, _("<Sp> Edit"), ' ');
339 ui_set_chyron_key(pick->chyron, 9, _("<Tab> Search"),
340 '\t');
341 ui_set_chyron_key(pick->chyron, 10, _("<Tab> Select"),
342 '\t');
350 return 0;
351}
352
353int pick_engine(Init *init) {
354 int rc = 0;
355 bool f_processed = false;
356 Pick *pick = init->pick;
357 /** Enter picker loop to handle user input and
358 * interactions */
359 char field[MAXLEN]; /**< Buffer for user input in the field */
360 field[0] = '\0';
362 do {
363 rc = picker(init, field);
364 if (rc == UIKEY_F09)
365 break;
366 if (rc == -1)
367 break;
368 else {
369 if (pick->select_cnt > 0) {
370 if (pick->f_out_spec && pick->out_spec[0]) {
372 f_processed = true;
373 }
374 if (pick->f_cmd && pick->cmd[0]) {
375 exec_objects(init);
376 f_processed = true;
377 }
378 if (pick->f_read_theme) {
379 read_theme(init);
380 f_processed = true;
381 }
382 if (f_processed) {
383 ui_mvwaddstr(pick->surface, WIN2, 0, 0, _("Selection Processed"));
385 }
386 }
387 }
389 } while (1);
391 return (rc);
392}
393/** @brief Sets standard chyron key states based on pick structure
394 * @ingroup pick_engine
395 @param pick Pointer to Pick structure containing chyron and selection
396 information
397 @details Updates the active state of chyron keys based on the current state
398 of the pick structure. Enables or disables keys for help, cancel, accept,
399 view, quit view, process, toggle, search, select, page up, page down, and
400 insert based on selection count, view mode, and table pages.
401 */
402void pick_std_chyron(Pick *pick) {
403 // * 1 F1 Help UIKEY_F01);
404 // * 2 F9 Cancel UIKEY_F09);
405 // * 3 F10 Accept UIKEY_F10);
406 // ? 4 <v> View <v>
407 // ? 5 <q> Quit View <q>
408 // ? 6 <Sp> Toggle <Sp>
409 // ? 7 <Sp> Edit <Sp>
410 // ? 9 <Tab> Search <Tab>
411 // ? 10 <Tab> Select" <Tab>
412 // ? 11 PgUp UIKEY_PPAGE
413 // ? 12 PgDn UIKEY_NPAGE
414 // ? 13 INS UIKEY_IC
415 pick->chyron->key[1]->active = true; // F1 Help
416 pick->chyron->key[2]->active = true; // F9 Cancel
417 pick->chyron->key[3]->active = pick->select_max != 1 ? true : false; // F10 Accept
418 pick->chyron->key[4]->active = pick->p_view_files; // <v> View
419 pick->chyron->key[5]->active = false; // <q> Quit View
420 pick->chyron->key[6]->active = pick->select_max == 1 ? false : true; // <Sp> Toggle
421 pick->chyron->key[7]->active = pick->select_max == 1 ? true : false; // <Sp> Process
422 pick->chyron->key[9]->active = true; // <Tab> Search;
423 pick->chyron->key[10]->active = false; // <Tab> Select;
424 pick->chyron->key[11]->active = pick->tbl_page > 0 ? true : false; // PgUp
425 pick->chyron->key[12]->active = pick->tbl_page < pick->tbl_pages - 1 ? true : false; // PgDn
426 pick->chyron->key[13]->active = false; // INS
427}
428/** @brief Saves a string as an object in the pick structure
429 * @ingroup pick_engine
430 @param pick Pointer to Pick structure
431 @param s String to save as an object
432 @details If the current object index is less than the maximum allowed, saves
433 the string as an object in the pick structure. Updates the column width if
434 necessary and marks the object as not selected. Increments the object index
435 for the next object to be saved. */
436void save_object(Pick *pick, char *s) {
437 uint l;
438
439 if (pick->m_idx < OBJ_MAXCNT - 1) {
440 l = strlen(s);
441 if (l > OBJ_MAXLEN - 1)
442 s[OBJ_MAXLEN - 1] = '\0';
443 pick->tbl_col_width = max(pick->tbl_col_width, l);
444 l = max(l, 1);
445 pick->m_object[pick->m_idx] = (char *)calloc(l + 1, sizeof(char));
447 pick->f_selected[pick->m_idx] = false;
448 pick->m_idx++;
449 }
450}
451
452/** @brief Displays current page of objects in pick window
453 * @ingroup pick_engine
454 @param pick Pointer to Pick structure containing objects and display
455 information
456 @details Clears the pick window and displays the current page of objects
457 based on the current table page, line, and column. Marks selected objects with
458 an asterisk. Updates the chyron with page information at the bottom of the pick
459 window. */
460void display_pick_page(Pick *pick) {
461 UiSurface *sfc = pick->surface;
462 uint col;
463 ui_bkgdset(sfc, WIN, &cell_nt);
465 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols;
466 for (col = 0; col < pick->tbl_cols; col++) {
467 pick->x = col * (pick->tbl_col_width + 1) + 1;
468 pick->y = 0;
469 while (pick->d_idx < pick->d_cnt && pick->y < pick->lines) {
470 if (pick->f_selected[pick->d_idx])
471 ui_mvwaddstr(sfc, WIN, pick->y, pick->x - 1, "*");
472 ui_mvwaddstr_fill(sfc, 1, pick->y++, pick->x,
473 pick->d_object[pick->d_idx++], pick->tbl_col_width - 1);
475 }
476 }
477 pick->d_idx -= 1;
478 pick->tbl_lines = pick->d_cnt;
479 pick->tbl_pages = ((pick->tbl_lines + pick->lines - 1) / pick->lines);
480 if (pick->y < pick->lines) {
481 pick->y_offset = pick->lines - pick->y;
482 ui_wscrl(sfc, WIN, -pick->y_offset);
483 } else
484 pick->y_offset = 0;
485}
486/** @brief Displays current page of objects in pick window
487 @ingroup pick_engine
488 @param pick Pointer to Pick structure containing objects and display
489 information
490 @param s String to filter objects by
491 @details Clears the pick window and displays the current page of objects
492 based on the current table page, line, and column. Marks selected objects
493 with an asterisk. Updates the chyron with page information at the bottom of
494 the pick window. */
495int match_objects(Pick *pick, char *s) {
496 /** pick->m_idx Master (as read from input) */
497 /** pick->d_idx Display (to display) */
498 pick->m_idx = 0;
499 pick->d_idx = 0;
500 while (pick->m_idx < pick->m_cnt) {
501 if (s == nullptr || s[0] == '\0' || strstr(pick->m_object[pick->m_idx], s) != nullptr) {
502 pick->d_object[pick->d_idx++] = pick->m_object[pick->m_idx];
503 }
504 pick->m_idx++;
505 }
506 pick->d_cnt = pick->d_idx;
507 return pick->d_cnt;
508}
509/** @brief Reverses the display of the currently selected object in pick window
510 * @ingroup pick_engine
511 @param pick Pointer to Pick structure containing object and display
512 information
513 @details Calculates the x coordinate for the currently selected object based
514 on the current table column and column width. Moves the cursor to the object's
515 position in the pick window, turns on reverse video attribute, and displays
516 the object's text. Turns off reverse video attribute and refreshes the pick
517 window to show the updated display. Moves the cursor back to the position
518 before the object text for potential further interactions. */
519void reverse_object(Pick *pick) {
520 UiSurface *sfc = pick->surface;
521 if (pick->d_idx >= pick->d_cnt)
522 pick->d_idx = pick->d_cnt - 1;
523 pick->x = pick->tbl_col * (pick->tbl_col_width + 1) + 1;
524 pick->tbl_line = (pick->d_idx / pick->tbl_cols) % pick->lines;
525 pick->y = pick->tbl_line + pick->y_offset;
526 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
528 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x, pick->d_object[pick->d_idx],
529 pick->tbl_col_width - 1);
530 if (pick->f_selected[pick->d_idx])
531 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_chk, 1);
532 else
533 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_sp, 1);
534 ui_bkgdset(sfc, WIN, &cell_nt);
535}
536/** @brief Unreverses the display of the currently selected object in pick
537 window
538 @ingroup pick_engine
539 @param pick Pointer to Pick structure containing object and display
540 information
541 @details Calculates the x coordinate for the currently selected object based
542 on the current table column and column width. Moves the cursor to the
543 object's position in the pick window and displays the object's text without
544 reverse video attribute. Refreshes the pick window to show the updated
545 display. Moves the cursor back to the position before the object text for
546 potential further interactions. */
547void unreverse_object(Pick *pick) {
548 UiSurface *sfc = pick->surface;
549 if (pick->d_idx >= pick->d_cnt)
550 pick->d_idx = pick->d_cnt - 1;
551 pick->x = pick->tbl_col * (pick->tbl_col_width + 1) + 1;
552 pick->tbl_line = (pick->d_idx / pick->tbl_cols) % pick->lines;
553 pick->y = pick->tbl_line + pick->y_offset;
554 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
555 ui_bkgdset(sfc, WIN, &cell_nt);
556 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x, pick->d_object[pick->d_idx],
557 pick->tbl_col_width - 1);
558 if (pick->f_selected[pick->d_idx])
559 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_chk, 1);
560 else
561 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_sp, 1);
562 ui_cursor_move(sfc, WIN, pick->y, 0);
563}
564void remove_right_angle(Pick *pick) {
565 UiSurface *sfc = pick->surface;
566 if (pick->d_idx >= pick->d_cnt)
567 pick->d_idx = pick->d_cnt - 1;
568 pick->tbl_line = (pick->d_idx / pick->tbl_cols) % pick->lines;
569 pick->y = pick->tbl_line + pick->y_offset;
570 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
571 if (pick->f_selected[pick->d_idx])
572 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_chk, 1);
573 else
574 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_sp, 1);
575 ui_cursor_move(sfc, WIN, pick->y, 0);
576}
577/** @brief Toggles the selection state of the currently selected object in pick
578 window
579 @ingroup pick_engine
580 @param pick Pointer to Pick structure containing object and selection
581 information
582 @details Calculates the x coordinate for the currently selected object based
583 on the current table column and column width. If the object is currently
584 selected, it is deselected by updating the selection count, marking it as not
585 selected, and displaying a space before the object text. If the object is not
586 currently selected, it is selected by updating the selection count, marking
587 it as selected, and displaying an asterisk before the object text. Refreshes
588 the pick window to show the updated display. Moves the cursor back to the
589 position before the object text for potential further interactions. */
590void toggle_object(Pick *pick) {
591 UiSurface *sfc = pick->surface;
592 pick->x = pick->tbl_col * (pick->tbl_col_width + 1) + 1;
593 if (pick->f_selected[pick->d_idx]) {
594 pick->select_cnt--;
595 pick->f_selected[pick->d_idx] = false;
596 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_sp, 1);
597 } else {
598 pick->select_cnt++;
599 pick->f_selected[pick->d_idx] = true;
600 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_chk, 1);
601 }
602}
603/** @brief Deselects the currently selected object in pick window
604 @ingroup pick_engine
605 @details like toggle, but only deselects object */
606void deselect_object(Pick *pick) {
607 UiSurface *sfc = pick->surface;
608 pick->x = pick->tbl_col * (pick->tbl_col_width + 1) + 1;
609 if (pick->f_selected[pick->d_idx]) {
610 pick->select_cnt--;
611 pick->f_selected[pick->d_idx] = false;
612 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0, &cell_sp, 1);
613 }
614}
615int read_theme(Init *init) {
616 int rc;
619 if (rc)
620 return rc;
621 SIO *sio = init->sio;
624 return 0;
625}
626
627/** @brief Outputs selected objects to specified output file
628 @ingroup pick_engine
629 @param pick Pointer to Pick structure containing selected objects and
630 output file information
631 @return 0 on success, 1 on failure
632 @details If output file cannot be opened, an error message is printed and
633 the function returns 1. Otherwise, selected objects are written to the
634 output file, one per line, and the file is closed before returning 0.
635*/
636int output_objects(Pick *pick) {
637 char tmp_str[MAXLEN];
638 int m;
639 if ((pick->out_fp = fopen(pick->out_spec, "w")) == nullptr) {
640 m = MAXLEN - 30;
641 strnz__cpy(tmp_str, _("Can't open pick output file: "), m);
642 m -= strlen(pick->in_spec);
643 strnz__cat(tmp_str, pick->out_spec, m);
644 }
645 for (pick->d_idx = 0; pick->d_idx < pick->d_cnt; pick->d_idx++) {
646 if (pick->f_selected[pick->d_idx])
647 fprintf(stdout, "%s\n", pick->d_object[pick->d_idx]);
648 }
649 fflush(stdout);
650 if (pick->out_fp != nullptr)
651 fclose(pick->out_fp);
652 return (0);
653}
654/** @brief Executes specified command with selected objects as arguments
655 @ingroup pick_engine
656 @param init Pointer to Init structure
657 @return 0 on success, 1 on failure
658 @details Parses command string and appends selected objects as arguments to
659 the command. If command contains "%%", it is replaced with a space- separated
660 list of selected objects. Executes the command using execvp in a child
661 process and waits for it to finish. If the command is a pager or editor, it
662 is executed within the pick interface using popup_view instead of execvp.
663 If f_append_objects is true, the argument containing %% is replaced with
664 the concatenated selected objects. If f_append_objects is false, selected
665 objects are added as separate arguments and the original command arguments
666 remain unchanged.
667 eargv should be null-terminated to indicate the end of arguments for
668 execvp
669 Memory allocated for arguments is freed after execution to prevent
670 memory leaks.
671 If execvp fails, an error message is printed and the child process
672 exits with failure status
673 The parent process waits for the child process to finish before
674 proceeding and restores terminal settings
675 If the command is a pager or editor, it is executed within the pick
676 interface using popup_view instead of execvp
677 The base name of the command is extracted to check if it is a pager or
678 editor
679 If the command is a pager or editor, the pick interface is used to
680 display the command output instead of executing it in a separate terminal
681 This allows the user to view the command output without leaving the pick
682 interface and provides a more seamless user experience.
683 If the command is not a pager or editor, it is executed in a separate
684 terminal and the pick interface is restored after execution
685 If the command to be executed is view, an external command is not
686 needed, instead the popup_view function can be used to display the output
687 within the pick interface */
688int exec_objects(Init *init) {
689 int rc = -1;
690 uint eargc;
691 char *eargv[MAXARGS];
692 char tmp_str[MAXLEN] = {'\0'};
693 char title[MAXLEN];
694 char sav_arg[MAXLEN];
695 char *out_s;
696 int eargx = 0;
697 uint i = 0;
698 pid_t pid = 0;
699 bool f_append_objects = false;
700
701 Pick *pick = init->pick;
702 title[0] = '\0';
703 if (pick->cmd[0] == '\0')
704 return -1;
705 if (pick->cmd[0] == '\\' || pick->cmd[0] == '\"') {
706 size_t len = strlen(pick->cmd);
707 if (len > 1 && pick->cmd[len - 1] == '\"') {
708 memmove(pick->cmd, pick->cmd + 1, len - 2);
709 pick->cmd[len - 2] = '\0';
710 }
711 }
712 eargc = str_to_args(eargv, pick->cmd, MAXARGS - 1);
713 tmp_str[0] = '\0';
714 if (pick->f_multiple_cmd_args) {
715 for (i = 0; i < pick->d_cnt; i++) {
716 if (pick->f_selected[i] && eargc < MAXARGS) {
717 if (tmp_str[0] != '\0')
718 strnz__cat(tmp_str, " ", MAXLEN - 1);
719 strnz__cat(tmp_str, pick->d_object[i], MAXLEN - 1);
720 }
721 }
722 eargv[eargc++] = strdup(tmp_str);
723 } else {
724 f_append_objects = false;
725 i = 0;
726 while (i < eargc) {
727 /** This is the line that gets the selected objects */
728 if (strstr(eargv[i], "%%") != nullptr) {
729 tmp_str[0] = '\0';
730 f_append_objects = true;
731 strnz__cpy(sav_arg, eargv[i], MAXLEN - 1);
732 eargx = i;
733 break;
734 }
735 i++;
736 }
737 for (i = 0; i < pick->d_cnt; i++) {
738 /** append arguments onto tmp_str */
739 if (pick->f_selected[i] && eargc < MAXARGS - 1) {
740 if (f_append_objects == true) {
741 if (tmp_str[0] != '\0')
742 strnz__cat(tmp_str, " ", MAXLEN - 1);
743 strnz__cat(tmp_str, pick->d_object[i], MAXLEN - 1);
744 continue;
745 }
746 eargv[eargc++] = strdup(pick->d_object[i]);
747 }
748 }
749 if (f_append_objects == true) {
750 if (eargv[eargx] != nullptr) {
751 free(eargv[eargx]);
752 eargv[eargx] = nullptr;
753 }
754 out_s = rep_substring(sav_arg, "%%", tmp_str);
755 if (out_s == nullptr || out_s[0] == '\0') {
756 i = 0;
757 while (i < eargc) {
758 if (eargv[i] != nullptr)
759 free(eargv[i]);
760 i++;
761 }
762 ui_perror(_("rep_substring() failed in exec_objects"));
763 return 1;
764 }
765 strnz__cpy(title, out_s, MAXLEN - 1);
766 eargv[eargx] = strdup(out_s);
767 if (out_s != nullptr) {
768 free(out_s);
769 out_s = nullptr;
770 }
771 }
772 }
773 strnz__cpy(tmp_str, eargv[0], MAXLEN - 1);
774 eargv[eargc] = nullptr;
775 char *sav_ptr;
776 char *tok;
777 tok = strtok_r(tmp_str, " ", &sav_ptr);
778 strnz__cpy(sav_arg, tok, MAXLEN - 1);
779 base_name(tmp_str, sav_arg);
780 if (tmp_str[0] != '\0' && (strcmp(tmp_str, "view") == 0 || strcmp(tmp_str, "view") == 0)) {
781 /** initialize popup_view arguments and execute popup_view to display
782 command output within pick interface */
783 init->lines = 60;
784 init->cols = 80;
785 init->begy = pick->begy + 1;
786 init->begx = pick->begx + 1;
787 if (title[0] != '\0')
788 strnz__cpy(init->title, title, MAXLEN - 1);
789 else
790 strnz__cpy(init->title, eargv[eargc], MAXLEN - 1);
791 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
792 init->begx);
793 i = 0;
794 while (i < eargc) {
795 if (eargv[i] != nullptr)
796 free(eargv[i]);
797 i++;
798 }
799 return 0;
800 } else {
803 if ((pid = fork()) == -1) {
804 /** fork failed, free eargv and return error */
805 i = 0;
806 while (i < eargc) {
807 if (eargv[i] != nullptr)
808 free(eargv[i]);
809 i++;
810 }
811 ui_perror(_("fork() failed in exec_objects"));
812 return (1);
813 } else if (pid == 0) {
814 /** Prevent child process from writing to terminal */
815 // int dev_null = open("/dev/null", O_WRONLY);
816 // if (dev_null == -1) {
817 // ui_perror(_("open(/dev/null) failed in init_pick child
818 // process"));
819 // exit(EXIT_FAILURE);
820 // }
821 // dup2(dev_null, STDERR_FILENO);
822 // close(dev_null);
823 execvp(eargv[0], eargv);
824 exit(EXIT_FAILURE);
825 }
826 }
827 waitpid(pid, nullptr, 0);
828 destroy_argv(eargc, eargv);
829 // sig_prog_mode();
831 return rc;
832}
833/** @brief Displays the help screen for the pick interface using view
834 @ingroup pick_engine
835 @param init Pointer to Init structure containing pick information
836 @details Initializes the help_spec field in the Pick structure with the
837 path to the pick help file. Then, constructs the argument list for
838 executing popup_view with the help file as an argument. Finally, calls
839 popup_view function to display the help screen within the pick interface. */
840void display_pick_help(Init *init) {
841 int eargc;
842 char *eargv[MAXARGS];
843 char tmp_str[MAXLEN];
844 Pick *pick = init->pick;
845 if (pick->f_help_spec && pick->help_spec[0] != '\0')
846 strnz__cpy(tmp_str, pick->help_spec, MAXLEN - 1);
847 else {
848 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
849 strnz__cat(tmp_str, "/", MAXLEN - 1);
851 }
852 eargc = 0;
853 eargv[eargc++] = strdup("view");
854 eargv[eargc++] = strdup("-Nf");
855 eargv[eargc++] = strdup(tmp_str);
856 eargv[eargc] = nullptr;
857 init->lines = 30;
858 init->cols = 76;
859 init->begy = pick->begy + 1;
860 init->begx = pick->begx + 1;
861 strnz__cpy(init->title, _("Pick Help"), MAXLEN - 1);
862 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
863 init->begx);
864 destroy_argv(eargc, eargv);
865 return;
866}
867/** @brief Main loop for handling user input and interactions in the pick
868 interface
869 @ingroup pick_engine
870 @param init Pointer to Init structure containing pick information
871 @param field Buffer for user input in the field
872 @return Count of selected objects on success, -1 if user cancels
873 @details The first loop handles navigation through the pick table.
874 The second loop handles user input for selecting/deselecting objects,
875 accepting the selection, or canceling the selection. Depending on the key
876 pressed, the appropriate action is taken, such as toggling selection, moving
877 to the next/previous object, or displaying the help screen. If the user
878 accepts the selection, the count of selected objects is returned. If the user
879 cancels the selection, -1 is returned.
880 */
881int picker(Init *init, char *field) {
882 bool f_insert = false; /* Flag to indicate if insert mode is active */
883 Pick *pick = init->pick;
884 uint col = 0;
885 uint flen = pick->width - 4;
886 char *accept_s = field; /* pointer to start of field buffer */
887 char *ptr = field; /* pointer to current cursor position in field buffer */
888 char *s = field; /* source pointer for editing operations */
889 char *d = field; /* destination pointer for editing operations */
890 char *fend = field + flen;
891 char *str_end = field + strlen(field); /* End of field content */
892 uint pos = 0;
893 uint prev_pos = 0;
894 char prev_field[MAXLEN];
895 char *prev_ptr = prev_field;
896 char view_file[MAXLEN] = {'\0'};
897 pick = init->pick;
898 UiSurface *sfc = pick->surface;
899 UiEvent event;
900 uint maxy, maxx;
901 ptr = accept_s;
902 ptr = str_end;
903 char tmp_str[MAXLEN];
904
905#ifdef UAL_UI
906 ui_mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION);
907#else
908 ui_mice_enable(0);
909#endif
910 f_insert = false;
911
912 ui_keypad(sfc, WIN, true);
913
914 int in_key = 0;
915 while (1) {
916 while (1) {
917 /** ===========================================================
918 Pick Objects Loop
919 =========================================================== */
920 if (in_key == 0) {
922 pick->tbl_line = (pick->d_idx / pick->tbl_cols) % pick->lines;
923 pick->y = pick->tbl_line + pick->y_offset;
924
925 /** box display_pick_page_info */
926 ssnprintf(tmp_str, MAXLEN - 1, _("Line %d, Page %d/%d"),
927 pick->tbl_line + 1, pick->tbl_page + 1,
928 pick->tbl_pages);
930 if (pick->p_view_files)
931 if (strcmp(pick->d_object[pick->d_idx], view_file) != 0) {
932 strnz__cpy(view_file, pick->d_object[pick->d_idx], MAXLEN - 1);
933 new_view_file(init, view_file);
934 }
937 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
938 ui_mvwadd_wchnstr(sfc, WIN2, 0, 0, &cell_ran, 1);
940 ui_top_surface(sfc, WIN);
941 ui_cursor_enable_yx(sfc, WIN, pick->y, pick->x, true);
943 in_key = ui_get_event(sfc, WIN, pick->chyron, &event, -1);
944 ui_cursor_enable_yx(sfc, WIN, pick->y, pick->x, false);
945 if (event.mouse_action != UI_MOUSE_NONE) {
946 ui_getmaxyx(sfc, WIN2, &maxy, &maxx);
947 if (event.in_win == pick->chyron->w &&
948 event.y == pick->chyron->y)
949 in_key = ui_get_chyron_key(pick->chyron, event.x);
950 } else {
951 if (pick->f_selected[pick->d_idx])
952 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0,
953 &cell_chk, 1);
954 else
955 ui_mvwadd_wchnstr(sfc, WIN, pick->y, 0,
956 &cell_sp, 1);
957 }
958 }
959 switch (in_key) {
960 case UIKEY_F01:
963 f_insert = false;
964 ui_mvwadd_wchnstr(sfc, WIN2, 0, 0, &cell_ran, 1);
965 in_key = 0;
966 continue;
967
968 case UIKEY_F11:
969 if (!pick->p_view_files) {
970 in_key = 0;
971 continue;
972 }
973 pick->chyron->key[1]->active = true; // F1 Help
974 pick->chyron->key[2]->active = true; // F9 Cancel
975 pick->chyron->key[4]->active = false; // F11 View
976 pick->chyron->key[5]->active = true; // <q> Quit View
977 pick->chyron->key[6]->active = false; // <Sp> Toggle
978 pick->chyron->key[7]->active = false; // <Sp> Edit
979 pick->chyron->key[9]->active = false; // <Tab> Search;
980 pick->chyron->key[10]->active = false; // <Tab> Select;
981 pick->chyron->key[11]->active = true; // PgUp
982 pick->chyron->key[12]->active = true; // PgDn
983 pick->chyron->key[13]->active = false; // INS
986 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
988 if (pick->p_view_files)
992 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
993 in_key = 0;
994 continue;
995
996 case 't':
997 case ' ':
999 toggle_object(pick);
1000 if (pick->select_max > 0 && pick->select_cnt == pick->select_max)
1001 return pick->select_cnt;
1002 in_key = 0;
1003 continue;
1004
1005 /** 'q', or UIKEY_F09 cancel selection and exit picker */
1006 case 'q':
1007 case UIKEY_F09:
1009 return -1;
1010
1011 /** Enter or UIKEY_F10 Accepts current selection and exits
1012 picker, returning count of selected objects */
1013 case UIKEY_F10:
1014 case '\n':
1015 case UIKEY_ENTER:
1016 reverse_object(pick);
1017 return pick->select_cnt;
1018
1019 /** UIKEY_END Moves selection to last object in list */
1020 case UIKEY_END:
1021 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x,
1022 pick->d_object[pick->d_idx],
1023 pick->tbl_col_width - 1);
1024 uint display_tbl_page = pick->tbl_page;
1025 pick->d_idx = pick->d_cnt - 1;
1026 pick->tbl_page = pick->d_idx / (pick->lines * pick->tbl_cols);
1027 pick->tbl_line = (pick->d_idx / pick->tbl_cols) % pick->lines;
1028 pick->tbl_col = pick->d_idx % pick->tbl_cols;
1029 pick->y = pick->tbl_line;
1030 if (display_tbl_page != pick->tbl_page)
1032 in_key = 0;
1033 continue;
1034 case '\t':
1036 // ui_wnoutrefresh(sfc, WIN);
1037 in_key = 0;
1038 break;
1039
1040 /** 'h' or UIKEY_LEFT or Backspace Moves selection to previous
1041 object in list */
1042 case 'h':
1043 case UIKEY_LEFT:
1044 case UIKEY_BACKSPACE:
1045 if (pick->tbl_col == 0) {
1046 in_key = 0;
1047 continue;
1048 }
1050 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x,
1051 pick->d_object[pick->d_idx],
1052 pick->tbl_col_width - 1);
1053 if (pick->tbl_col > 0)
1054 pick->tbl_col--;
1055 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
1056 in_key = 0;
1057 reverse_object(pick);
1058 continue;
1059
1060 /** 'j' or UIKEY_DOWN Moves selection to next object in list */
1061 case 'j':
1062 case UIKEY_DOWN:
1063 if (pick->tbl_line == pick->tbl_lines - 1)
1064 break;
1065 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x,
1066 pick->d_object[pick->d_idx],
1067 pick->tbl_col_width - 1);
1069 if (pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line < pick->d_cnt - 1 && pick->tbl_line < pick->lines - 1)
1070 pick->tbl_line++;
1071 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
1072 in_key = 0;
1073 reverse_object(pick);
1074 continue;
1075
1076 /** 'k' or UIKEY_UP Moves selection to previous object in list */
1077 case 'k':
1078 case UIKEY_UP:
1079 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x,
1080 pick->d_object[pick->d_idx],
1081 pick->tbl_col_width - 1);
1083 if (pick->tbl_line > 0)
1084 pick->tbl_line--;
1085 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
1086 in_key = 0;
1087 reverse_object(pick);
1088 continue;
1089
1090 /** 'l' or UIKEY_RIGHT Moves selection to next object in list */
1091 case 'l':
1092 case UIKEY_RIGHT:
1093 if (pick->tbl_col == pick->tbl_cols - 1) {
1094 in_key = 0;
1095 continue;
1096 }
1097 ui_mvwaddstr_fill(sfc, WIN, pick->y, pick->x,
1098 pick->d_object[pick->d_idx],
1099 pick->tbl_col_width - 1);
1101 /** pick->obj_idx += pick->tbl_lines -> next column */
1102 if (pick->tbl_page * pick->lines * pick->tbl_cols + (pick->tbl_col + 1) * pick->lines + pick->tbl_line < pick->d_cnt - 1 && pick->tbl_col < pick->tbl_cols - 1)
1103 pick->tbl_col++;
1104 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->tbl_line;
1105 in_key = 0;
1106 reverse_object(pick);
1107 continue;
1108
1109 /** UIKEY_NPAGE or 'Ctrl+f' Moves selection to next page of
1110 objects */
1111 case UIKEY_NPAGE:
1112 case '\06':
1113 if (pick->tbl_pages == 1) {
1114 in_key = 0;
1115 continue;
1116 }
1117 if (pick->tbl_page < pick->tbl_pages - 1) {
1118 pick->tbl_page++;
1119 pick->pg_line = 0;
1120 pick->tbl_col = 0;
1121 }
1122 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_cols * pick->pg_line + pick->tbl_col;
1124 in_key = 0;
1125 continue;
1126
1127 /** UIKEY_PPAGE or 'Ctrl+b' Moves selection to previous page of
1128 objects */
1129 case UIKEY_PPAGE:
1130 case '\02':
1131 if (pick->tbl_pages == 1) {
1132 in_key = 0;
1133 continue;
1134 }
1135 if (pick->tbl_page > 0)
1136 pick->tbl_page--;
1137 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_cols * pick->pg_line + pick->tbl_col;
1139 in_key = 0;
1140 continue;
1141
1142 /** UIKEY_HOME Moves selection to first object in list */
1143 case UIKEY_HOME:
1144 pick->tbl_page = 0;
1145 pick->tbl_line = 0;
1146 pick->tbl_col = 0;
1147 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_cols * pick->pg_line + pick->tbl_col;
1149 in_key = 0;
1150 continue;
1151
1152 /** UIKEY_LL (lower left of numeric pad) Moves selection to last
1153 object in list */
1154 // case UIKEY_END:
1155 // pick->tbl_page = pick->tbl_pages - 1;
1156 // pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols +
1157 // // pick->tbl_cols * pick->pg_line +
1158 // // pick->tbl_col;
1159 // display_pick_page(pick);
1160 // in_key = 0;
1161 // continue;
1162
1163 /** UIKEY_MOUSE Handles mouse events for selection and chyron
1164 * key activation */
1165
1166 case UIKEY_BUTTON1:
1167 if (event.y < pick->y_offset) {
1168 in_key = 0;
1169 continue;
1170 }
1172 pick->y = event.y;
1173 pick->tbl_col = (event.x - 1) / (pick->tbl_col_width + 1);
1174 if (pick->tbl_col >= pick->tbl_cols)
1175 continue;
1176 pick->d_idx = pick->tbl_page * pick->lines * pick->tbl_cols + pick->tbl_col * pick->lines + pick->y;
1177 in_key = UIKEY_F12; /** toggle selection on mouse click */
1178 event.y = event.x = -1;
1179 continue;
1180
1181 default:
1182 in_key = 0;
1183 continue;
1184 }
1185 in_key = 0;
1186 break;
1187 }
1188 /** ===============================================================
1189 Line editor loop
1190 =============================================================== */
1191 pick->chyron->key[1]->active = true; // F1 Help
1192 pick->chyron->key[2]->active = true; // F9 Cancel
1193 pick->chyron->key[3]->active = false; // F10 Accept
1194 pick->chyron->key[4]->active = true; // F11 View
1195 pick->chyron->key[5]->active = false; // <q> Quit View
1196 pick->chyron->key[6]->active = false; // <Sp> Toggle
1197 pick->chyron->key[7]->active = false; // <Sp> Edit
1198 pick->chyron->key[9]->active = false; // <Tab> Search
1199 pick->chyron->key[10]->active = true; // <Tab> Select
1200 pick->chyron->key[11]->active = false; // PgDn
1201 pick->chyron->key[12]->active = false; // PgUp
1202 pick->chyron->key[13]->active = true; // INS
1203
1204 while (1) {
1205
1206 if (in_key == 0) {
1207 // mouse_win = nullptr;
1208 if (accept_s != nullptr && accept_s[0] != '\0') {
1209 if (match_objects(pick, accept_s) == 0) {
1210 strnz__cpy(field, prev_field, MAXLEN - 1);
1211 pos = prev_pos;
1212 ptr = prev_ptr;
1213 } else {
1215 ssnprintf(tmp_str, MAXLEN - 1, _("Line %d, Page %d/%d"),
1216 pick->tbl_line + 1, pick->tbl_page + 1,
1217 pick->tbl_pages);
1218 strnz__cat(tmp_str, " ", MAXLEN - 1);
1219 tmp_str[21] = '\0';
1220 ui_mvwaddstr(sfc, BOX, pick->separator_line, 3, tmp_str);
1221 }
1222 }
1224 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
1225 ui_cursor_move(sfc, WIN2, 0, 1);
1226 /** display_field_content */
1227 rtrim(accept_s);
1228 col = 1;
1229 ui_mvwaddstr(sfc, WIN2, 0, col, accept_s);
1230 ui_wclrtoeol(sfc, WIN2);
1231 if (pick->p_view_files)
1232 if (strcmp(pick->d_object[pick->d_idx], view_file) != 0) {
1233 strnz__cpy(view_file, pick->d_object[pick->d_idx], MAXLEN - 1);
1234 new_view_file(init, view_file);
1235 }
1236 // mouse_win = nullptr;
1237 pos = col + strlen(accept_s);
1238 ui_mvwadd_wchnstr(sfc, WIN2, 0, 0, &cell_ran, 1);
1239 ui_top_surface(sfc, WIN2);
1240 ui_cursor_enable_yx(sfc, WIN2, 0, pos, true);
1242 in_key = ui_get_event(sfc, WIN2, pick->chyron, &event, -1);
1243 ui_cursor_enable_yx(sfc, WIN2, 0, pos, false);
1244 ui_getmaxyx(sfc, WIN2, &maxy, &maxx);
1245 if (event.mouse_action != UI_MOUSE_NONE) {
1246 if (event.in_win == WIN2 && event.y == maxy - 1)
1247 in_key = ui_get_chyron_key(pick->chyron, event.x);
1248 if (event.in_win == WIN)
1249 break;
1250 }
1251 if (in_key == UIKEY_F12) {
1252 in_key = 0;
1253 continue;
1254 }
1255 }
1256 strnz__cpy(prev_field, accept_s, MAXLEN - 1);
1257 prev_pos = pos;
1258 prev_ptr = ptr;
1259 switch (in_key) {
1260 case '\n':
1261 case UIKEY_ENTER:
1262 in_key = 0;
1263 break;
1264
1265 case UIKEY_UP:
1266 case '\t':
1267 in_key = 0;
1268 break;
1269
1270 case UIKEY_F01:
1271 return (in_key);
1272
1273 case UIKEY_F02:
1274 if (pick->p_view_files)
1276 in_key = 0;
1277 continue;
1278
1279 /** UIKEY_F09 Cancels the current operation */
1280 case UIKEY_F09:
1281 in_key = UIKEY_F09;
1282 return (in_key);
1283
1284 /** UIKEY_F10 is the default key for accepting the field */
1285 case UIKEY_F10:
1286 return (in_key);
1287 case UIKEY_F11:
1288 if (!pick->p_view_files) {
1289 in_key = 0;
1290 continue;
1291 }
1292 pick->chyron->key[1]->active = true; // F1 Help
1293 pick->chyron->key[2]->active = true; // F9 Cancel
1294 pick->chyron->key[4]->active = false; // F11 View
1295 pick->chyron->key[5]->active = true; // <q> Quit View
1296 pick->chyron->key[6]->active = false; // <Sp> Toggle
1297 pick->chyron->key[7]->active = false; // <Sp> Edit
1298 pick->chyron->key[9]->active = false; // <Tab> Search;
1299 pick->chyron->key[10]->active = false; // <Tab> Select;
1300 pick->chyron->key[11]->active = true; // PgUp
1301 pick->chyron->key[12]->active = true; // PgDn
1302 pick->chyron->key[13]->active = false; // INS
1305 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
1307 if (pick->p_view_files)
1311 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
1312 in_key = 0;
1313 continue;
1314
1315 case UIKEY_END:
1316 case Ctrl('e'):
1317 while (*ptr != '\0')
1318 ptr++;
1319 pos = col + (ptr - accept_s);
1320 in_key = 0;
1321 continue;
1322
1323 case UIKEY_IC:
1324 if (f_insert) {
1325 f_insert = false;
1328 } else {
1329 f_insert = TRUE;
1332 }
1334 ui_display_chyron(sfc, WIN2, pick->chyron, 1, pick->chyron->l);
1335 in_key = 0;
1336 continue;
1337
1338 /** UIKEY_DC deletes character at cursor */
1339 case UIKEY_DC:
1340 s = ptr + 1;
1341 d = ptr;
1342 while (*s != '\0')
1343 *d++ = *s++;
1344 *d = '\0';
1345 str_end = d;
1346 f_insert = false;
1347 in_key = 0;
1348 continue;
1349
1350 /** UIKEY_HOME moves cursor to start of field */
1351 case UIKEY_HOME:
1352 case Ctrl('a'):
1353 ptr = accept_s;
1354 pos = col;
1355 in_key = 0;
1356 continue;
1357
1358 /** UIKEY_BACKSPACE deletes character before cursor */
1359 case UIKEY_BACKSPACE:
1360 if (ptr > accept_s) {
1361 ptr--;
1362 pos--;
1363 } else {
1364 in_key = 0;
1365 continue;
1366 }
1367 s = ptr + 1;
1368 d = ptr;
1369 while (*s != '\0')
1370 *d++ = *s++;
1371 *d = '\0';
1372 str_end = d;
1373 if (ptr == accept_s) {
1374 match_objects(pick, accept_s);
1376 ssnprintf(tmp_str, MAXLEN - 1, _("Line %d, Page %d/%d"),
1377 pick->tbl_line + 1, pick->tbl_page + 1,
1378 pick->tbl_pages);
1379 strnz__cat(tmp_str, " ", MAXLEN - 1);
1380 tmp_str[21] = '\0';
1381 ui_mvwaddstr(sfc, BOX, pick->separator_line, 3, tmp_str);
1382 }
1383 in_key = 0;
1384 continue;
1385
1386 /** UIKEY_LEFT moves cursor left one character */
1387 case UIKEY_LEFT:
1388 if (ptr > accept_s) {
1389 ptr--;
1390 pos--;
1391 }
1392 in_key = 0;
1393 continue;
1394
1395 /** UIKEY_RIGHT moves cursor right one character */
1396 case UIKEY_RIGHT:
1397 if (ptr < fend && ptr <= str_end) {
1398 ptr++;
1399 pos++;
1400 }
1401 in_key = 0;
1402 continue;
1403
1404 /** Handles mouse events for field editing */
1405 case UIKEY_BUTTON1:
1406 if (event.x < col || event.x >= col + flen) {
1407 in_key = 0;
1408 continue;
1409 }
1410 pos = event.x;
1411 fend = accept_s + flen;
1412 str_end = accept_s + strlen(accept_s);
1413 ptr = accept_s + (pos - col);
1414 ptr = min(ptr, str_end);
1415 pos = col + (ptr - accept_s);
1416 event.x = -1;
1417 in_key = 0;
1418 continue;
1419
1420 default:
1421 if (in_key < ' ' || in_key > '~') {
1422 in_key = 0;
1423 continue;
1424 }
1425 if (ptr >= fend) {
1426 in_key = 0;
1427 continue;
1428 }
1429 if (f_insert) {
1430 if (str_end < fend) {
1431 s = str_end - 1;
1432 d = str_end;
1433 while (s >= ptr)
1434 *d-- = *s--;
1435 *ptr++ = in_key;
1436 str_end++;
1437 pos++;
1438 }
1439 } else {
1440 if (ptr < fend) {
1441 if (ptr < str_end) {
1442 *ptr++ = in_key;
1443 pos++;
1444 } else if (ptr == str_end) {
1445 *ptr++ = in_key;
1446 *ptr = '\0';
1447 str_end = ptr;
1448 pos++;
1449 }
1450 }
1451 }
1452 in_key = 0;
1453 continue;
1454 }
1455 break;
1456 }
1458 }
1459}
1460/** @brief Initializes a new view for displaying file contents in the pick
1461 interface
1462 @ingroup pick_engine
1463 @param init Pointer to Init structure containing pick information
1464 @return 0 on success, 1 on failure
1465 @details Allocates memory for a new View structure and initializes its
1466 fields based on the parameters specified in the Init structure. Sets up the
1467 help_spec field for the view, and calls init_view_boxwin to create the view's
1468 window. Returns 0 on success, or 1 if window creation fails.
1469 */
1470int new_pick_view(Init *init) {
1471 char *e;
1472 // if (init->view != nullptr)
1473 // view_stack_push(&view_stack, *init->view);
1474 init->view = nullptr;
1476 View *view = init->view;
1477 view = new_view(init); // View struct allocation
1478 view->lines = init->lines;
1479 view->cols = init->cols;
1480 view->begy = init->begy;
1481 view->begx = init->begx;
1482 view->receiver_cmd[0] = '\0';
1485 view->f_squeeze = init->f_squeeze;
1486 view->tab_stop = init->tab_stop;
1487 view->f_ln = init->f_ln;
1488 view->h_shift = init->h_shift;
1489 e = getenv("VIEW_HELP_FILE");
1490 if (e && e[0] != '\0') {
1492 }
1493 view->f_help_spec =
1495 "~/menuapp/help", R_OK);
1496 if (!view->f_help_spec) {
1498 strnz__cat(view->help_spec, "/help/", MAXLEN - 1);
1500 }
1501 int rc = init_view_boxwin(init);
1502 return rc;
1503}
1504/** @brief Initializes a new view for displaying the contents of a specified
1505 file in the pick interface
1506 @ingroup pick_engine
1507 @param init Pointer to Init structure containing pick information
1508 @param file Name of the file to be displayed in the view
1509 @details If a view is already initialized, it destroys the existing line
1510 table and unmaps the buffer. Then, it sets up the provider command for
1511 highlighting the specified file, initializes the view input, and if successful,
1512 resets various view parameters, initializes the line table, and displays the
1513 first page of the file contents along with the prompt.
1514 */
1515void new_view_file(Init *init, char *file) {
1516 View *view = init->view;
1517 Pick *pick = init->pick;
1518 if (pick->p_view_files && init->view != nullptr) {
1520 munmap(view->buf, view->file_size);
1521 view->buf = nullptr;
1522 }
1523#ifdef NOTCURSES_UI
1524 if (ui_mm.ncv != nullptr) {
1525 ncvisual_destroy(ui_mm.ncv);
1526 ui_mm.ncv = nullptr;
1527 ui_surface_destroy(ui_mm.sfc);
1528 ui_mm.sfc = nullptr;
1529 ui_render();
1530 }
1531#endif
1532 FileType ft = file_type(file);
1533 switch (ft) {
1534 case FT_IMAGE:
1535#ifdef NOTCURSES_UI
1536 if (init->view != nullptr) {
1537 destroy_pick_view(init);
1538 init->view = nullptr;
1539 destroy_line_table(view);
1540 munmap(view->buf, view->file_size);
1541 view->buf = nullptr;
1542 }
1543 ui_display_image(ui->nc, &ui_mm, file, -1, -1, 35, 0);
1544 if (ui_mm.sfc == nullptr) {
1545 ui_log(ERROR, _("ui_display_image() failed in new_view_file"));
1546 return;
1547 }
1548 if (ui_mm.ncv == nullptr) {
1549 ui_log(ERROR, _("ui_display_image() failed in new_view_file"));
1550 return;
1551 }
1552#endif
1553 break;
1554 case FT_VIDEO:
1555#ifdef NOTCURSES_UI
1556 if (init->view != nullptr) {
1557 destroy_pick_view(init);
1558 init->view = nullptr;
1559 destroy_line_table(view);
1560 munmap(view->buf, view->file_size);
1561 view->buf = nullptr;
1562 }
1563 ui_display_image(ui->nc, &ui_mm, file, -1, -1, 35, 0);
1564 if (ui_mm.sfc == nullptr) {
1565 ui_log(ERROR, _("ui_display_image() failed in new_view_file"));
1566 return;
1567 }
1568 if (ui_mm.ncv == nullptr) {
1569 ui_log(ERROR, _("ui_display_image() failed in new_view_file"));
1570 return;
1571 }
1572#endif
1573 break;
1574 case FT_AUDIO:
1575 break;
1576 case FT_TEXT:
1577 if (!pick->p_view_files)
1578 return;
1579 if (init->view == nullptr) {
1580 new_pick_view(init);
1581 view = init->view;
1582 } else {
1583 view = init->view;
1585 munmap(view->buf, view->file_size);
1586 view->buf = nullptr;
1587 }
1588 strnz__cpy(view->provider_cmd, _("tree-sitter highlight "), MAXLEN - 1);
1590 strnz__cpy(view->title, file, MAXLEN - 1);
1591 if (view_init_input(init, file) == 0) {
1592 if (view->buf) {
1593 view->f_eod = 0;
1594 view->f_bod = 0;
1595 view->maxcol = 0;
1596 view->page_top_pos = 0;
1597 view->page_top_ln_no = 0;
1598 view->page_bot_ln_no = 0;
1599 view->ln_pos_max = 0;
1600 view->ln_no = 0;
1601 view->page_bot_pos = 0;
1602 view->file_pos = 0;
1605 page_next(view);
1606 build_prompt(view);
1608 pad_refresh(view);
1609 }
1610 }
1611 break;
1612 default:
1613 break;
1614 }
1615}
int open_pick_win(Init *)
#define P_READ
Definition common.h:53
#define PICK_HELP_FILE
Definition common.h:37
int popup_view(Init *, int, char **, uint, uint, uint, uint)
instantiate a view popup window
Definition popups.c:145
int pick_engine(Init *)
#define VIEW_HELP_FILE
Definition common.h:38
#define P_WRITE
Definition common.h:54
#define OBJ_MAXLEN
Definition pick.h:20
#define OBJ_MAXCNT
Definition pick.h:21
size_t rtrim(char *)
Trims trailing spaces from string s in place.
Definition futil.c:308
char stdio_names_str[4096]
Definition futil.c:122
#define MAXARGS
Definition cm.h:64
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:104
char * stdio_fdnames(char *, char *)
Definition futil.c:1108
#define Ctrl(c)
Definition cm.h:67
#define max(a, b)
max macro evaluates two expressions, returning greatest result.
Definition cm.h:97
char * rep_substring(const char *, const char *, const char *) __attribute__((nonnull(1
Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
Definition futil.c:1449
UiCell cell_sp
Definition ui_common.c:132
void ui_render()
Render the UI by updating panels and refreshing the display.
Definition ui_ncurses.c:884
UiCell cell_nt
Definition ui_common.c:106
int ui_tracked_sfc_split_box(uint wlines, uint wcols, uint split_y, uint split_x, uint wbegy, uint wbegx, const char *wtitle)
Create a new surface with a split box window.
Definition ui_common.c:425
UiCell cell_nt_hl_rev
Definition ui_common.c:109
int ui_setscrreg(UiSurface *s, ss_t w, uint top, uint bottom)
Set the scrolling region for a UiSurface.
Definition ui_ncurses.c:820
void ui_getmaxyx(UiSurface *s, ss_t w, uint *lines, uint *cols)
Get the maximum dimensions of a UiSurface.
Definition ui_ncurses.c:690
int ui_cursor_enable_yx(UiSurface *s, ss_t w, uint y, uint x, bool visible)
Enable or disable the cursor at a specific position within a UiSurface.
Definition ui_ncurses.c:855
int ui_wscrl(UiSurface *s, ss_t w, int rows)
Scroll the contents of a UiSurface by a specified number of lines.
Definition ui_ncurses.c:738
int ui_cursor_move(UiSurface *s, ss_t w, uint y, uint x)
Move the cursor to a specified position within a UiSurface.
Definition ui_ncurses.c:666
int ui_cm_surface_destroy(UiSurface *sfc)
Destroy the most recently created surface.
Definition ui_common.c:466
void ui_surface_destroy(UiSurface *s)
Destroy a UiSurface, cleaning up its windows and panels.
Definition ui_ncurses.c:468
int ui_border_title(UiSurface *sfc, const char *title)
Draw a box with a title around the specified window.
Definition ui_common.c:563
void ui_restore_wins()
Restore the state of all windows in the UI. This function refreshes the standard screen and all surfa...
int ui_border_ysplit_text(UiSurface *sfc, char *text, uint separator_line)
Draw a box with a separator line and text around the specified window.
Definition ui_common.c:524
void ui_get_screen_size(uint *lines, uint *cols)
Get the current screen size (number of lines and columns).
Definition ui_ncurses.c:722
int ui_mousemask(int mask)
Enable or disable mouse support.
void ui_initialize_sio(SIO *sio)
Definition ui_common.c:182
UiSurface * stdsfc
Definition ui_ncurses.c:46
int sfc_ptr
Definition ui_ncurses.c:42
int ui_top_surface(UiSurface *s, ss_t w)
Hide a UiSurface, making it invisible on the screen.
Definition ui_ncurses.c:623
void ui_endwin()
End the UI application, cleaning up resources and shutting down the UI runtime.
Definition ui_ncurses.c:412
UiCell cell_ran
Definition ui_common.c:115
int ui_scrollok(UiSurface *s, ss_t w, bool enable)
Enable or disable scrolling for a UiSurface.
Definition ui_ncurses.c:755
int ui_wclrtoeol(UiSurface *s, ss_t w)
Clear to the end of the line in a surface window.
int ui_bkgdset(UiSurface *s, ss_t w, const UiCell *cell)
Set the background for new content to be written to a specific window within a UiSurface.
Definition ui_ncurses.c:941
int ui_werase(UiSurface *s, ss_t w)
Erase the contents of a UiSurface or all surfaces.
Definition ui_ncurses.c:551
UiCell cell_chk
Definition ui_common.c:116
UiCell cell_nt_rev
Definition ui_common.c:107
int ui_keypad(UiSurface *s, ss_t w, bool enable)
Enable or disable the keypad for a UiSurface.
Definition ui_ncurses.c:771
#define UIKEY_F02
#define UIKEY_DC
#define UIKEY_BACKSPACE
#define UIKEY_F12
#define UIKEY_LEFT
#define UIKEY_F09
#define UIKEY_IC
#define UIKEY_PPAGE
#define UIKEY_END
#define UIKEY_F01
#define UIKEY_BUTTON1
#define UIKEY_RIGHT
#define UIKEY_UP
#define UIKEY_F10
#define UIKEY_HOME
#define UIKEY_ENTER
#define UIKEY_F11
#define UIKEY_DOWN
#define UIKEY_NPAGE
int ui_get_event(UiSurface *s, ss_t w, UiChyron *chyron, UiEvent *ev, int timeout_ms)
Read input events.
void ui_set_chyron_key(UiChyron *chyron, uint k, char *s, uint kc)
Set chyron key with default color pair (cp_nt_rev).
Definition ui_common.c:717
UiChyron * ui_new_chyron(UiSurface *sfc, ss_t w)
Create new chyron structure.
Definition ui_common.c:601
void ui_display_chyron(UiSurface *sfc, ss_t w, UiChyron *chyron, uint line, uint col)
Display chyron on the specified line and column of the surface.
Definition ui_common.c:837
void ui_set_chyron_key_cb(UiChyron *chyron, uint k, char *s, uint kc, UiCell cell_base)
Set chyron key with color pair (cp).
Definition ui_common.c:693
void ui_abend(int ec, char *s)
Convert multibyte string to complex character array.
Definition ui_common.c:362
UiChyron * ui_destroy_chyron(UiChyron *chyron)
Destroy UiChyron structure.
Definition ui_common.c:656
int ui_get_chyron_key(UiChyron *chyron, uint x)
Get keycode from chyron.
Definition ui_common.c:861
void ui_compile_chyron(UiChyron *chyron)
construct the chyron string from the chyron structure
Definition ui_common.c:782
UiSurface * ui_surface[UI_SFC_MAX]
Definition ui_ncurses.c:40
int ui_mvwadd_wchnstr(UiSurface *s, ss_t w, uint y, uint x, const UiCell *cmplx_buf, uint n)
Draw a complex character string at a specific position in a surface window, with a maximum length.
int ui_mvwaddstr(UiSurface *s, ss_t w, uint y, uint x, const char *text)
Draw a text string at a specific position in a surface window.
int ui_mvwaddstr_fill(UiSurface *s, ss_t w, uint y, uint x, const char *str, int m)
Draw a text string at a specific position in a surface window, filling the remaining space with space...
#define TRUE
Definition iloan.c:31
#define MAXLEN
Definition curskeys.c:15
void end_pick_view(Init *)
int tbl_line
Definition pick_engine.c:23
int obj_idx
Definition pick_engine.c:24
char const pagers_editors[12][10]
Definition pick_engine.c:50
int tbl_cols
Definition pick_engine.c:23
int read_theme(Init *)
int tbl_col
Definition pick_engine.c:23
int tbl_pages
Definition pick_engine.c:23
int calculated_idx
Definition pick_engine.c:24
int pg_lines
Definition pick_engine.c:23
UiMultiMedia ui_mm
Definition pick_engine.c:48
int tbl_page
Definition pick_engine.c:23
void remove_right_angle(Pick *)
int pipe_fd[2]
Definition pick_engine.c:46
int process_config_file(char *, Init *)
Definition init.c:694
#define _(String)
Definition amort.c:23
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition whence.c:291
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:390
int str_to_args(char **, char *, uint)
Converts a string into an array of argument strings.
Definition futil.c:412
bool expand_tilde(char *, uint)
Replaces "~/" in string with the user's home directory.
Definition futil.c:989
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition whence.c:320
int destroy_argv(uint argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:468
bool base_name(char *, char *)
Returns the base name of a file specification.
Definition futil.c:1132
int init_view_boxwin(Init *init)
Initialize the C-Menu View in box window mode.
Definition init_view.c:162
int view_init_input(Init *init, char *file_name)
Initialize the input for the C-Menu View.
Definition init_view.c:299
bool verify_spec_arg(char *, char *, char *, char *, uint)
Verify file specification argument.
Definition mem.c:361
Pick * new_pick(Init *init, int argc, char **argv, uint begy, uint begx)
Create and initialize Pick structure.
Definition mem.c:178
View * destroy_view(Init *init)
Destroy View structure.
Definition mem.c:337
View * new_view(Init *init)
Create and initialize View structure.
Definition mem.c:291
void save_object(Pick *, char *)
Saves a string as an object in the pick structure.
void toggle_object(Pick *)
Toggles the selection state of the currently selected object in pick window.
int picker(Init *, char *field)
Main loop for handling user input and interactions in the pick interface.
int new_pick_view(Init *)
Initializes a new view for displaying file contents in the pick interface.
void unreverse_object(Pick *)
Unreverses the display of the currently selected object in pick window.
void destroy_pick_view(Init *)
Destroys pick view, unmaps file buffer, and cleans up resources.
void pick_std_chyron(Pick *)
Sets standard chyron key states based on pick structure.
int output_objects(Pick *)
Outputs selected objects to specified output file.
int match_objects(Pick *pick, char *s)
Displays current page of objects in pick window.
void deselect_object(Pick *)
Deselects the currently selected object in pick window.
int init_pick(Init *, int, char **, uint, uint)
Initializes pick structure and opens pick input file or pipe.
Definition pick_engine.c:68
int read_pick_input(Init *)
Reads pick input from file pointer and saves objects into pick structure.
void reverse_object(Pick *)
Reverses the display of the currently selected object in pick window.
void display_pick_page(Pick *)
Displays current page of objects in pick window.
void new_view_file(Init *, char *)
Initializes a new view for displaying the contents of a specified file in the pick interface.
void display_pick_help(Init *)
Displays the help screen for the pick interface using view.
int exec_objects(Init *)
Executes specified command with selected objects as arguments.
int view_cmd_processor(Init *)
Main Command Processing Loop for View.
void build_prompt(View *)
Build Prompt String.
void initialize_line_table(View *)
Initialize Line Table.
void destroy_line_table(View *)
Destroy Line Table.
void page_next(View *)
Advance to Next Page.
int pad_refresh(View *)
Refresh Pad and Line Number Window.
int display_prompt(View *, char *)
Display Command Line Prompt.
int ui_perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition ui_common.c:1257
UiMouseAction mouse_action
Definition ui_backend.h:114
ss_t in_win
Definition ui_backend.h:112
char title[MAXLEN]
Definition common.h:132
char mapp_help[MAXLEN]
Definition common.h:152
int begx
Definition common.h:121
SIO * sio
Definition common.h:117
int argc
Definition common.h:133
int cols
Definition common.h:119
int tab_stop
Definition common.h:185
char mapp_home[MAXLEN]
Definition common.h:150
bool f_squeeze
Definition common.h:140
int begy
Definition common.h:120
int h_shift
Definition common.h:186
bool f_ln
Definition common.h:146
View * view
Definition common.h:193
bool f_at_end_remove
Definition common.h:138
bool f_ignore_case
Definition common.h:136
char ** argv
Definition common.h:134
int lines
Definition common.h:118
char mapp_theme[MAXLEN]
Definition common.h:155
Pick * pick
Definition common.h:191
char ** m_object
Definition pick.h:71
UiChyron * chyron
Definition pick.h:94
uint separator_line
Definition pick.h:92
uint tbl_line
Definition pick.h:87
bool f_cmd
Definition pick.h:69
uint y
Definition pick.h:33
uint select_max
Definition pick.h:74
bool p_view_files
Definition pick.h:64
uint m_idx
Definition pick.h:77
uint tbl_cols
Definition pick.h:89
uint tbl_page
Definition pick.h:86
char ** d_object
Definition pick.h:79
char cmd[MAXLEN]
Definition pick.h:54
bool f_help_spec
Definition pick.h:61
FILE * in_fp
Definition pick.h:44
bool f_out_spec
Definition pick.h:58
int argc
Definition pick.h:42
bool f_multiple_cmd_args
Definition pick.h:63
uint d_cnt
Definition pick.h:76
bool f_in_pipe
Definition pick.h:59
bool f_selected[OBJ_MAXCNT]
Definition pick.h:65
uint m_cnt
Definition pick.h:75
char title[MAXLEN]
Definition pick.h:41
char help_spec[MAXLEN]
Definition pick.h:51
char in_buf[BUFSIZ]
Definition pick.h:70
uint tbl_pages
Definition pick.h:85
UiSurface * surface
Definition pick.h:40
char ** argv
Definition pick.h:43
uint tbl_col_width
Definition pick.h:91
bool f_read_theme
Definition pick.h:62
char in_spec[MAXLEN]
Definition pick.h:49
FILE * out_fp
Definition pick.h:45
uint lines
Definition pick.h:29
uint x
Definition pick.h:34
uint select_cnt
Definition pick.h:73
uint d_idx
Definition pick.h:78
uint tbl_lines
Definition pick.h:88
uint begy
Definition pick.h:31
uint tbl_col
Definition pick.h:90
uint y_offset
Definition pick.h:80
uint begx
Definition pick.h:32
uint pg_line
Definition pick.h:81
uint width
Definition pick.h:30
char provider_cmd[MAXLEN]
Definition pick.h:52
char out_spec[MAXLEN]
Definition pick.h:50
char provider_cmd[MAXLEN]
Definition view.h:74
off_t page_top_ln_no
Definition view.h:157
char * buf
Definition view.h:171
uint maxcol
Definition view.h:125
off_t page_top_pos
Definition view.h:152
off_t file_pos
Definition view.h:150
uint lines
Definition view.h:70
off_t ln_no
Definition view.h:182
char prompt_str[MAXLEN]
Definition view.h:78
uint begx
Definition view.h:73
bool f_bod
Definition view.h:99
char help_spec[MAXLEN]
Definition view.h:142
off_t ln_pos_max
Definition view.h:187
bool f_ignore_case
Definition view.h:83
bool f_help_spec
Definition view.h:145
char receiver_cmd[MAXLEN]
Definition view.h:75
bool f_ln
Definition view.h:181
bool f_eod
Definition view.h:100
bool f_at_end_remove
Definition view.h:84
off_t file_size
Definition view.h:149
bool f_squeeze
Definition view.h:85
int tab_stop
Definition view.h:95
char title[MAXLEN]
Definition view.h:79
uint cols
Definition view.h:71
off_t page_bot_pos
Definition view.h:153
off_t page_bot_ln_no
Definition view.h:158
uint begy
Definition view.h:72
int h_shift
Definition view.h:96
UiSurface * sfc
Definition view.h:89