2
3
4
5
6
7
8
11
12
13
16#include "../ui/ui_ncurses_internal.h"
17#include "ui_backend.h"
18#include <ncursesw/ncurses.h>
19#include <ncursesw/panel.h>
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#define get_next_char()
57 if (view->file_pos == view->file_size) {
62 c = view->buf[view->file_pos++];
68
69
70
71
72
73
74
75
76#define get_prev_char()
80 if (view->file_pos == 0
) {
85 c = view->buf[--view->file_pos];
91 if ((c = get_cmd_char(view, &n_cmd)) == 'y' || c == 'Y')
93 else if (c == 'n' || c == 'N')
99 ssnprintf(em0, MAXLEN - 1
, "%s, line: %d", __FILE__, __LINE__ - 2
);
100 strnz__cpy(em1, msg, MAXLEN - 1
);
101 display_error(em0, em1, nullptr, nullptr);
104#define _Refresh(view)
117void lp(View *,
char *);
123bool search(View *,
int,
char *);
143int a_toi(
char *,
bool *);
153
154
155
156
157
158
159
160
208
209
210
211
212
213
220 int prev_search_cmd = 0;
224 ssize_t bytes_written;
226 char shell_cmd_spec[
MAXLEN];
231 UiSurface *sfc = view
->sfc;
244 if (c >=
'0' && c <=
'9') {
245 tmp_str[0] = (
char)c;
258 ssnprintf(em0, MAXLEN - 1,
259 "%s:%d view->page_top_ln_no=%d, resized to lines: %d, cols: %d\n",
260 __FILE__, __LINE__, view->page_top_ln_no, view->lines, view->cols);
261 write_cmenu_log(em0);
270
274
275
282
287 else if (n_cmd == 0) {
303 else if (n_cmd == 0) {
383 else if (c ==
'n' || c ==
'N')
399 view
, "view->f_squeeze Multiple Blank lines (Y or N)->");
405 view
, "Line Wrapping (Y or N)->");
408 else if (c ==
'n' || c ==
'N')
419 "Tabstop Colums Currently %d:", view
->tab_stop);
423 if (i >= 1 && i <= 12) {
445 Perror("Search complete, no more matches");
448 if (prev_search_cmd == 0) {
452 if (prev_search_cmd ==
'/') {
471 if (c ==
KEY_F09 || c ==
'\033')
483 prev_search_cmd = search_cmd;
493 if (c ==
KEY_F09 || c ==
'\033')
505 prev_search_cmd = search_cmd;
538 if (c ==
'@' || c ==
KEY_F09 || c ==
'\033')
539 if (c >=
'A' && c <=
'Z')
541 if (c <
'a' || c >
'z')
550 if (c ==
'@' || c ==
KEY_F09 || c ==
'\033')
552 if (c >=
'A' && c <=
'Z')
554 if (c <
'a' || c >
'z')
587 tfd = mkstemp(tmp_str);
590 Perror("Unable to create temporary file");
644 e = getenv(
"DEFAULTEDITOR");
645 if (e ==
nullptr || *e ==
'\0')
651 "View doesn't support editing current buffer directly",
658 if (rc !=
'y' && rc !=
'Y')
666 if (bytes_written == 0) {
693 if (bytes_written == 0) {
718
719
720
721
722
723
724
725
726
727
728
729
730
731
739 UiSurface *sfc = view
->sfc;
745 if (i == 1 && !once) {
754 event
.y = event
.x = -1;
788 if (i < 32 && cmd_str[i] !=
'\0') {
802 if (i < 32 && cmd_str[i] !=
'\0') {
822 if (c <
'0' || c >
'9' || i == 32)
824 cmd_str[i++] = (
char)c;
830 if (c <
'0' || c >
'9' || i == 32)
833 if (cmd_str[0] ==
'\0') {
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
867 UiSurface *sfc = view
->sfc;
885 uint fcol = prompt_l + 1;
886 uint flen = view
->cols - prompt_l;
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
926 if (prompt_l > (view
->cols - 4) / 2)
938 if (prompt_l > (view
->cols - 4) / 2)
959 if (prompt_l > (view
->cols - 4) / 2)
973
974
975
976
977
979 ssize_t bytes_written = 0;
990 if (rc ==
'y' || rc ==
'Y')
993 f_strip_ansi =
false;
1015 bytes_written += write(view
->out_fd, tmp_line_s, l);
1021 return bytes_written;
1024
1025
1036
1037
1038
1039void lp(View *view,
char *PrintFile) {
1040 char *print_cmd_ptr;
1041 char shell_cmd_spec[
MAXLEN];
1042 print_cmd_ptr = getenv(
"PRINTCMD");
1043 if (print_cmd_ptr ==
nullptr || *print_cmd_ptr ==
'\0')
1050
1051
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094bool search(View *view,
int search_cmd,
char *regex_pattern) {
1097 regmatch_t pmatch[1];
1098 regex_t compiled_regex;
1105 memset(&mbstate, 0,
sizeof(mbstate));
1106 wchar_t wstr[2] = {L'\0', L'\0'};
1111 bool f_page =
false;
1112 UiSurface *sfc = view
->sfc;
1113 if (*regex_pattern ==
'\0')
1116 REG_FLAGS = REG_ICASE | REG_EXTENDED;
1118 REG_FLAGS = REG_EXTENDED;
1119 reti = regcomp(&compiled_regex, regex_pattern, REG_FLAGS);
1127 if (search_cmd ==
'/') {
1138 if (search_cmd ==
'/')
1150 if (search_cmd ==
'/') {
1165 compiled_regex.re_nsub + 1, pmatch, REG_FLAGS);
1166 if (reti == REG_NOMATCH) {
1169 if (search_cmd ==
'?')
1173 (search_cmd ==
'?' && view
->cury == 1)) {
1182 regerror(reti, &compiled_regex, err_str,
sizeof(err_str));
1192 if (search_cmd ==
'/') {
1202 if (search_cmd ==
'?')
1204 bool f_first_match =
true;
1210 match_idx = line_offset + pmatch[0].rm_so;
1211 match_len = pmatch[0].rm_eo - pmatch[0].rm_so;
1212 for (uint i = match_idx; i < match_idx + match_len; i++) {
1215 ui_getcchar(&cc, wstr, &attr, &cpx,
nullptr);
1217 ui_setcchar(&cc, wstr, attr, cpx,
nullptr);
1223 if (f_first_match) {
1224 f_first_match =
false;
1228 line_offset += pmatch[0].rm_eo;
1229 if (line_offset >= line_len)
1233 compiled_regex.re_nsub + 1, pmatch, REG_FLAGS);
1234 if (reti == REG_NOMATCH)
1238 regerror(reti, &compiled_regex, msgbuf,
sizeof(msgbuf));
1239 sprintf(tmp_str,
"Regex match failed: %s", msgbuf);
1244 if (search_cmd ==
'/') {
1248 }
else if (view
->cury == 1) {
1256 regfree(&compiled_regex);
1262
1263
1265
1266
1267
1268
1269
1276 uint scroll, avail, scroll_this_line;
1280 while (scroll > 0) {
1300 scroll_this_line =
min(scroll, avail);
1301 scroll -= scroll_this_line;
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1349
1350
1351
1356 UiSurface *sfc = view
->sfc;
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1398 UiSurface *sfc = view
->sfc;
1416 ui_mvwadd_wchstr(sfc, PAD, view->cury, 0, view->cmplx_buf);
1427
1428
1429
1430
1431
1432
1433
1434
1435
1438 UiSurface *sfc = view
->sfc;
1478
1479
1480
1481
1482
1483
1484
1486 UiSurface *sfc = view
->sfc;
1496
1497
1498
1499
1500
1501
1502
1503
1504
1506 uint scroll, scroll_this_line, avail;
1508 UiSurface *sfc = view
->sfc;
1514 while (scroll > 0) {
1528 scroll_this_line =
min(scroll, avail);
1529 scroll -= scroll_this_line;
1544 while (scroll > 0) {
1562 scroll_this_line =
min(scroll, avail);
1563 scroll -= scroll_this_line;
1602 while (scroll > 0) {
1620
1621
1622
1623
1624
1625
1626
1627
1628
1630 uint scroll, avail, scroll_this_line;
1640 UiSurface *sfc = view
->sfc;
1657 while (scroll > 0) {
1679 scroll_this_line =
min(scroll, avail);
1680 scroll -= scroll_this_line;
1695 while (scroll > 0) {
1711 while (scroll > 0) {
1732 scroll_this_line =
min(scroll, avail);
1733 scroll -= scroll_this_line;
1749 while (scroll > 0) {
1811
1812
1813
1837
1838
1839
1840
1843 Perror("Cannot determine file length");
1860
1861
1862
1863
1864
1865
1868 Perror("Line number out of bounds");
1881
1882
1883
1884
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1905 off_t prev_ln_no = 0;
1906 while (low <= high) {
1907 off_t guess = low + (high - low) / 2;
1908 if (view
->ln_tbl[guess] == position)
1910 if (view
->ln_tbl[guess] < position) {
1919
1920
1921
1922
1923
1924
1925
1930 Perror("Memory allocation failed");
1938
1939
1940
1941
1942
1943
1944
1955
1956
1957
1958
1959
1960
1961
1962
1963
1975 Perror("Memory allocation failed");
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
2013 while (view
->ln_tbl[idx] > target_pos)
2023
2024
2025
2027
2028
2030
2031
2032
2033
2041 rc = prefresh(view->sfc->mwin[PAD],
2049 ssnprintf(em0, MAXLEN - 1,
"%s:%d prefresh(view->sfc->mwin[WIN2], pminrow=%d, pmincol=%d, smaxrow=%d, smaxcol=%d) returned %d\n",
2050 __FILE__, __LINE__ - 1, view->pminrow, view->pmincol, view->smaxrow, view->smaxcol, rc);
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2075 uint i = 0, j = 0, x = 0;
2077 uint tab_spaces = 0;
2082 wchar_t wstr[2] = {L'\0', L'\0'};
2086 uint word_cells = 0;
2098 memset(&mbstate, 0,
sizeof(mbstate));
2108 while (in_str[i] !=
'\0') {
2110 if (in_str[i] ==
'\033') {
2111 if (in_str[i + 1] ==
'[') {
2112 len = strcspn(&in_str[i],
"mK ") + 1;
2113 memcpy(ansi_tok, &in_str[i], len + 1);
2114 ansi_tok[len] =
'\0';
2115 if (ansi_tok[0] ==
'\0') {
2120 if (len == 0 || in_str[i + len - 1] ==
' ') {
2123 }
else if (in_str[i + len - 1] ==
'K') {
2134 if (in_str[i] ==
' ' || in_str[i] ==
'-') {
2135 if (view
->wrap && (sl_cols + word_cols) > (sl_maxlen - 1))
2137 (in_str[i] ==
'-') ? (wstr[0] = L'-') : (wstr[0] = L' ');
2141 cmplx_buf[j++] = cc;
2143 sl_cols += word_cols + 1;
2145 sl_cells += word_cells + 1;
2151 if (in_str[i] ==
'\0') {
2153 if (sl_cols + word_cols + 1 > sl_maxlen - 1)
2155 sl_cols += word_cols;
2157 sl_cells += word_cells;
2162 if (in_str[i] ==
'\t') {
2164 if (view
->wrap && sl_cols + word_cols + tab_spaces > sl_maxlen - 1)
2169 for (uint z = 0; z < tab_spaces; z++) {
2171 cmplx_buf[j++] = cc;
2174 sl_cols += word_cols + tab_spaces;
2176 sl_cells += word_cells + tab_spaces;
2183 len = mbrtowc(wstr, &in_str[i], MB_CUR_MAX, &mbstate);
2189 char_width = wcwidth(wstr[0]);
2192 for (uint n = 1; n < char_width; n++)
2195 cmplx_buf[j++] = cc;
2198 word_cols += char_width;
2205 if (word_cols > 0) {
2206 if (sl_cols <= sl_maxlen) {
2212 sl_s = &sl_s[sl_cols];
2213 sl_cc = &sl_cc[sl_cells];
2215 sl_cols = word_cols;
2216 sl_cells = word_cells;
2221 while (sl_cols > sl_maxlen - 1) {
2222 uint safe_cells = 0;
2224 while (safe_cols < sl_maxlen && safe_cells < sl_cells) {
2229 uint cw = wcwidth(wstr_chk[0]);
2230 if (safe_cols + cw > sl_maxlen)
2235 if (safe_cells == 0) {
2237 safe_cols = sl_maxlen;
2244 sl_s = &sl_s[safe_cells];
2245 sl_cc = &sl_cc[safe_cells];
2247 sl_cols -= safe_cols;
2248 sl_cells -= safe_cells;
2283
2284
2285
2286
2287
2288
2289
2296 memset(tmp_str, 0,
sizeof(tmp_str));
2303
2304
2305
2306
2307
2308
2309
2310
2311
2318 memset(tmp_str, 0,
sizeof(tmp_str));
2324 if (wstr[0] == L'\0')
2327 tmp_str[c] = (
char)wstr[0];
2333
2334
2335
2336
2337
2338
2339
2346
2347
2348
2349
2350
2351
2352
2358 memset(tmp_str, 0,
sizeof(tmp_str));
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2428 uint fg_clr, bg_clr;
2429 char *ansi_p = ansi_str + 2;
2434 tok = strtok((
char *)ansi_p,
";m");
2435 bool a_toi_error =
false;
2437 if (tok ==
nullptr || *tok ==
'\0')
2443 if (t0 ==
'3' || t0 ==
'4') {
2445 tok = strtok(
nullptr,
";m");
2446 if (tok !=
nullptr) {
2448 tok = strtok(
nullptr,
";m");
2449 if (tok !=
nullptr) {
2453 }
else if (*tok ==
'2') {
2454 tok = strtok(
nullptr,
";m");
2456 tok = strtok(
nullptr,
";m");
2458 tok = strtok(
nullptr,
";m");
2466 }
else if (t1 ==
'9') {
2471 }
else if (t1 >=
'0' && t1 <=
'7') {
2478 }
else if (t0 ==
'4') {
2486 }
else if (t0 ==
'0') {
2497 switch (
a_toi(tok
, &a_toi_error
)) {
2523 }
else if (len == 0) {
2528 tok = strtok(
nullptr,
";m");
2530 if (!a_toi_error && (fg_clr != fg || bg_clr != bg))
2535
2536
2537
2541 UiSurface *sfc = view
->sfc;
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2588 eargv[eargc++] = strdup(
"view");
2589 eargv[eargc++] = strdup(
"-N");
2590 eargv[eargc++] = strdup(tmp_str);
2591 eargv[eargc] =
nullptr;
2603
2604
2606
2607
2608
2609
2610
2611
2612
2613
2636 while (rc ==
false) {
2639 view
->in_fd = mkstemp(tmp_spec);
2650
2661 tmp_fp = fopen(tmp_spec,
"r");
2662 if (tmp_fp ==
nullptr) {
2671 fgets(tmp_str,
MAXLEN - 1, tmp_fp);
2681 if (rc ==
'y' || rc ==
'Y')
int popup_form(Init *, int, char **, uint, uint)
instantiate a form popup window
int popup_view(Init *, int, char **, uint, uint, uint, uint)
instantiate a view popup window
size_t rtrim(char *)
Trims trailing spaces from string s in place.
#define min(x, y)
min macro evaluates two expressions, returning least result
int ui_wclrtobot(UiSurface *s, uint w)
int ui_mvwadd_wchstr(UiSurface *s, uint w, uint y, uint x, const UiCell *cell)
int ui_cursor_move(UiSurface *s, uint w, uint y, uint x)
void ui_getyx(UiSurface *s, uint w, uint *lines, uint *cols)
int ui_bkgdset(UiSurface *s, uint w, const UiCell *cell)
int ui_mvwaddstr(UiSurface *s, uint w, uint y, uint x, const char *text)
int ui_wadd_wchnstr(UiSurface *s, uint w, const UiCell *cell, uint m)
int ui_add_color_rgb(RGB *rgb)
int ui_mvwadd_wchnstr(UiSurface *s, uint w, uint y, uint x, const UiCell *cell, uint m)
int ui_get_event_no_mouse(UiSurface *surface, uint w, UiEvent *ev)
int ui_mvwaddch(UiSurface *s, uint w, uint y, uint x, const char c)
void ui_surface_destroy(UiSurface *s)
void ui_get_screen_size(uint *lines, uint *cols)
int ui_waddstr(UiSurface *s, uint w, const char *text)
int ui_wclrtoeol(UiSurface *s, uint w)
int ui_wscrl(UiSurface *s, uint w, int rows)
int ui_curs_set(int visibility)
int ui_mvwadd_wch(UiSurface *s, uint w, uint y, uint x, const UiCell *cell)
int ui_cursor_enable_yx(UiSurface *s, uint w, uint y, uint x, bool visible)
Disable (visible = false) or enable (visibile = true) the cursor at a specified position on the surfa...
int ui_pair_content(uint pair, uint *fg, uint *bg)
uint ui_add_pair(uint fg, uint bg)
int ui_getcchar(const UiCell *uc, wchar_t *wstr, attr_t *attrs, uint16_t *pair, void *opts)
int ui_setcchar(cchar_t *wch, const wchar_t *wc, const attr_t attrs, short pair, const void *opts)
char prev_regex_pattern[MAXLEN]
void get_line(View *, off_t)
int cf_accept(UiSurface *sfc, uint w, char *accept_s, uint flin, uint fcol, uint flen)
Accepts input for a field in a C-Menu window.
RGB xterm256_idx_to_rgb(uint idx)
Convert XTerm 256 color index to RGB.
void view_full_screen_resize(Init *)
Resize the full screen view and its components.
void view_boxwin_resize(Init *)
Resize the current window and its box.
int border_title(UiSurface *sfc, char *title)
Draw a box with a title around the specified window.
int answer_yn(char *msg0, char *msg1, char *msg2, char *msg3)
Accept a single letter answer.
int Perror(char *emsg_str)
Display a simple error message window or print to stderr.
int display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
int shell(char *)
Execute a shell command.
int full_screen_shell(char *)
Execute a shell command in full screen mode.
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
void write_cmenu_log(char *)
Write message to C-Menu log file without timestamp.
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
int str_to_args(char **, char *, uint)
Converts a string into an array of argument strings.
bool expand_tilde(char *, uint)
Replaces "~/" in string with the user's home directory.
size_t strip_ansi(char *, char *)
Strips ANSI SGR escape sequences (ending in 'm') from string s to d.
bool mk_dir(char *dir)
If directory doesn't exist, make it.
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
size_t strnlf(char *, size_t)
terminates string with line feed
int a_toi(char *, bool *)
a safer alternative to atoi() for converting ASCII strings to integers.
bool str_subc(char *, char *, char, char *, uint)
Replaces "ReplaceChr" in "s" with "Withstr" in "d" won't copy more than "l" bytes to "d" Replaces all...
int destroy_argv(uint argc, char **argv)
Deallocates memory allocated for argument strings in argv.
bool base_name(char *, char *)
Returns the base name of a file specification.
int view_init_input(Init *init, char *file_name)
Initialize the input for the C-Menu View.
bool verify_spec_arg(char *, char *, char *, char *, uint)
Verify file specification argument.
int view_file(Init *)
Start view.
bool enter_file_spec(Init *, char *)
use form to enter a file specification
int write_view_buffer(Init *, bool)
Write buffer contents to files.
void lp(View *, char *)
Send File to Print Queue.
#define get_prev_char()
read the previous characater from the virtual fileThere is no need to track line numbers when moving ...
void cat_file(View *)
Concatenate File to Standard Output.
int get_cmd_arg(View *, char *)
Get Command Argument from User Input.
int view_cmd_processor(Init *)
Main Command Processing Loop for View.
int get_cmd_char(View *, off_t *)
Get Command Character from User Input.
void build_prompt(View *)
Build Prompt String.
#define get_next_char()
read the next characater from the virtual file
void sync_ln(View *)
Synchronize Line Table with Current File Position.
void go_to_percent(View *, uint)
Go to Percent of File.
off_t line_number(View *, off_t)
Get Line Number for a Given File Position.
void scroll_up(View *, uint)
Scroll Up by n Lines.
void go_to_eof(View *)
Go to End of File.
void prev_page(View *)
display previous page
void go_to_position(View *, off_t)
Go to Specific File Position.
void go_to_mark(View *, uint)
Go to Mark.
void scroll_down(View *, uint)
Scroll Down by n Lines.
void initialize_line_table(View *)
Initialize Line Table.
bool search(View *, int, char *)
Search for Regular Expression Pattern.
void destroy_line_table(View *)
Destroy Line Table.
int go_to_line(View *, off_t)
Go to Specific Line.
void next_page(View *)
Advance to Next Page.
void increment_ln(View *)
Increment Line Index and Update Line Table.
void log_cc_buf(View *)
Log Complex Character Buffer.
void log_split_lines(View *)
Log Split Lines.
void display_line(View *)
Display Line on Padparam View *view data structure.
int pad_refresh(View *)
Refresh Pad and Line Number Window.
void display_line_eod(View *)
Display End of Data.
int display_prompt(View *, char *)
Display Command Line Prompt.
void log_strnz(char *, uint)
Log String with Specified Length.
int fmt_line(View *)
Format Line for Display.
void display_split_line(View *)
Display Split Line on Pad.
void view_display_help(Init *)
Display View Help File.
void view_display_page(View *)
Display Current Page.
void log_stripped_line_out(View *)
Log Stripped Line Output.
void parse_ansi_str(char *, attr_t *, ushort *)
Parse ANSI SGR Escape Sequence.
char * next_file_spec_ptr
UiCell cmplx_buf[PAD_COLS]
char stripped_line_out[PAD_COLS]
char cur_file_str[MAXLEN]
char line_out_s[PAD_COLS]