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

Navigation functions for the view application. More...

Functions

void destroy_line_table (View *view)
 Destroy Line Table.
void go_to_eof (View *view)
 Go to End of File.
int go_to_line (View *view, off_t line_idx)
 Go to Specific Line.
void go_to_mark (View *view, uint c)
 Go to Mark.
void go_to_percent (View *view, uint percent)
 Go to Percent of File.
void go_to_position (View *view, off_t go_to_pos)
 Go to Specific File Position.
void increment_ln (View *view)
 Increment Line Index and Update Line Table.
void initialize_line_table (View *view)
 Initialize Line Table.
off_t line_number (View *view, off_t position)
 Get Line Number for a Given File Position.
void next_page (View *view)
 Advance to Next Page.
void prev_page (View *view)
 display previous page
void scroll_down (View *view, uint n)
 Scroll Down by n Lines.
void scroll_up (View *view, uint n)
 Scroll Up by n Lines.
bool search (View *view, int search_cmd, char *regex_pattern)
 Search for Regular Expression Pattern.
void sync_ln (View *view)
 Synchronize Line Table with Current File Position.

Detailed Description

Navigation functions for the view application.

Function Documentation

◆ destroy_line_table()

void destroy_line_table ( View * view)

Destroy Line Table.

Parameters
viewdata structure

This function frees the memory allocated for the line table and resets the relevant fields in the View structure. It ensures that the line table is properly cleaned up when it is no longer needed, preventing memory leaks.

Definition at line 1945 of file view_engine.c.

1945 {
1946 if (view->ln_tbl == nullptr)
1947 return;
1948 free(view->ln_tbl);
1949 view->ln_tbl = nullptr;
1950 view->ln_tbl_size = 0;
1951 view->ln_max_pos = 0;
1952 view->ln_no = 0;
1953}
View * view
Definition mem.c:38

References View::ln_max_pos, View::ln_no, View::ln_tbl, and View::ln_tbl_size.

Referenced by destroy_pick_view(), new_view_file(), and view_file().

Here is the caller graph for this function:

◆ go_to_eof()

void go_to_eof ( View * view)

Go to End of File.

Parameters
viewdata structure

Definition at line 1814 of file view_engine.c.

1814 {
1815 view->file_pos = view->file_size;
1816 sync_ln(view);
1817 view->ln_no--;
1818 view->ln_no_max = view->ln_no;
1819 if (view->wrap) {
1820 view->page_top_ln_no = view->ln_no;
1821 view->f_eod = true;
1822 prev_page(view);
1823 return;
1824 }
1825 if (view->ln_no > view->scroll_lines)
1826 view->ln_no -= view->scroll_lines - 1;
1827 // else
1828 // view->page_top_ln_no = 0;
1829 view->page_top_ln_no = view->ln_no;
1830 // view->page_top_pos = view->ln_tbl[view->ln_no];
1831 // view->page_bot_pos = view->page_top_pos;
1832 // view->file_pos = view->page_top_pos;
1833 view->cury = 0;
1834 next_page(view);
1835}
void sync_ln(View *)
Synchronize Line Table with Current File Position.
void prev_page(View *)
display previous page
void next_page(View *)
Advance to Next Page.

References View::cury, View::f_eod, View::file_pos, View::file_size, View::ln_no, View::ln_no_max, next_page(), View::page_top_ln_no, prev_page(), View::scroll_lines, sync_ln(), and View::wrap.

Referenced by view_cmd_processor().

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

◆ go_to_line()

int go_to_line ( View * view,
off_t line_idx )

Go to Specific Line.

Parameters
viewdata structure
line_idxline number to go to (1-based index)
Returns
0 on success, EOF if line index is out of bounds or end of data is reached

Definition at line 1866 of file view_engine.c.

1866 {
1867 if (line_idx < 0 || line_idx > view->ln_tbl_size - 1) {
1868 Perror("Line number out of bounds");
1869 return EOF;
1870 }
1871 view->ln_no = line_idx;
1872 view->file_pos = view->ln_tbl[view->ln_no];
1873 sync_ln(view);
1874 view->page_top_pos = view->file_pos;
1875 view->page_bot_pos = view->file_pos;
1876 // view->file_pos = view->page_top_pos;
1877 next_page(view);
1878 return 0;
1879}
int Perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition dwin.c:841

References View::file_pos, View::ln_no, View::ln_tbl, View::ln_tbl_size, next_page(), View::page_bot_pos, View::page_top_pos, Perror(), and sync_ln().

Referenced by view_cmd_processor().

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

◆ go_to_mark()

void go_to_mark ( View * view,
uint c )

Go to Mark.

Parameters
viewPointer to the View structure containing the state and parameters of the view application. This structure is used to access and modify the state of the application as needed.
cThe character representing the mark to go to. This character is typically a lowercase letter (a-z) corresponding to a mark that has been set previously in the view application. The function will attempt to navigate to the position associated with this mark, allowing the user to quickly jump to specific locations in the file based on the marks they have set. If the mark is not set, an error message will be displayed to the user.

Definition at line 1065 of file view_engine.c.

1065 {
1066 if (c == '\'')
1067 view->file_pos = view->mark_tbl[(NMARKS - 1)];
1068 else
1069 view->file_pos = view->mark_tbl[c - 'a'];
1070 if (view->file_pos == NULL_POSITION)
1071 Perror("Mark not set");
1072 else
1073 go_to_position(view, view->file_pos);
1074}
#define NMARKS
Definition view.h:35
#define NULL_POSITION
Definition view.h:38
void go_to_position(View *, off_t)
Go to Specific File Position.

References View::file_pos, go_to_position(), View::mark_tbl, and Perror().

Referenced by view_cmd_processor().

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

◆ go_to_percent()

void go_to_percent ( View * view,
uint percent )

Go to Percent of File.

Parameters
viewdata structure
percentof file

Definition at line 1841 of file view_engine.c.

1841 {
1842 if (view->file_size < 0) {
1843 Perror("Cannot determine file length");
1844 return;
1845 }
1846 view->file_pos = (percent * view->file_size) / 100;
1847 view->ln_no = line_number(view, view->file_pos);
1848 view->file_pos = view->ln_tbl[view->ln_no];
1849 sync_ln(view);
1850 if (view->ln_no > view->scroll_lines)
1851 view->page_top_ln_no = view->ln_no - view->scroll_lines;
1852 else
1853 view->page_top_ln_no = 0;
1854 view->page_top_pos = view->ln_tbl[view->page_top_ln_no];
1855 view->page_bot_pos = view->page_top_pos;
1856 view->file_pos = view->page_top_pos;
1857 next_page(view);
1858}
off_t line_number(View *, off_t)
Get Line Number for a Given File Position.

References View::file_pos, View::file_size, line_number(), View::ln_no, View::ln_tbl, next_page(), View::page_bot_pos, View::page_top_ln_no, View::page_top_pos, Perror(), View::scroll_lines, and sync_ln().

Referenced by view_cmd_processor().

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

◆ go_to_position()

void go_to_position ( View * view,
off_t go_to_pos )

Go to Specific File Position.

Parameters
viewdata Structure
go_to_pos

Definition at line 1885 of file view_engine.c.

1885 {
1886 view->ln_no = line_number(view, go_to_pos);
1887 view->file_pos = view->ln_tbl[view->ln_no];
1888 sync_ln(view);
1889 next_page(view);
1890}

References View::file_pos, line_number(), View::ln_no, View::ln_tbl, next_page(), and sync_ln().

Referenced by go_to_mark().

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

◆ increment_ln()

void increment_ln ( View * view)

Increment Line Index and Update Line Table.

Parameters
viewdata structure

This function is called when a line feed character is encountered while reading the file. It increments the line index (view->ln_no) and checks if the current file position exceeds the maximum position recorded in the line table. If it does, it updates the line table with the new file position. If the line index exceeds the current size of the line table, the table is resized by allocating more memory.

Definition at line 1964 of file view_engine.c.

1964 {
1965 // view->ln_tbl[0] is set to 0 in initialize_line_table
1966 // view->ln_tbl[1] is the second line
1967 view->ln_no++;
1968 if (view->file_pos <= view->ln_max_pos)
1969 return;
1970 if (view->ln_no > view->ln_tbl_size - 1) {
1971 view->ln_tbl_size += LINE_TBL_INCR;
1972 view->ln_tbl =
1973 (off_t *)realloc(view->ln_tbl, view->ln_tbl_size * sizeof(off_t));
1974 if (view->ln_tbl == nullptr) {
1975 Perror("Memory allocation failed");
1976 exit(EXIT_FAILURE);
1977 }
1978 }
1979 view->ln_tbl_cnt = view->ln_no;
1980 view->ln_max_pos = view->file_pos;
1981 view->ln_tbl[view->ln_no] = view->file_pos;
1982}
#define LINE_TBL_INCR
Definition view.h:48

References View::file_pos, View::ln_max_pos, View::ln_no, View::ln_tbl, View::ln_tbl_cnt, View::ln_tbl_size, and Perror().

Here is the call graph for this function:

◆ initialize_line_table()

void initialize_line_table ( View * view)

Initialize Line Table.

Parameters
viewdata structure

The line table is initialized with a specified increment size (LINE_TBL_INCR). Memory is allocated for the line table, and the first entry is set to 0, indicating the file position of the first line. The line index (view->ln_no) is initialized to 0.

Definition at line 1926 of file view_engine.c.

1926 {
1927 view->ln_tbl_size = LINE_TBL_INCR;
1928 view->ln_tbl = (off_t *)calloc(view->ln_tbl_size, sizeof(off_t));
1929 if (view->ln_tbl == nullptr) {
1930 Perror("Memory allocation failed");
1931 exit(EXIT_FAILURE);
1932 }
1933 view->ln_max_pos = 0;
1934 view->ln_tbl[0] = 0;
1935 view->ln_no = 0;
1936}

References View::ln_max_pos, View::ln_no, View::ln_tbl, View::ln_tbl_size, and Perror().

Referenced by new_view_file(), and view_file().

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

◆ line_number()

off_t line_number ( View * view,
off_t position )

Get Line Number for a Given File Position.

Parameters
viewdata structure
targetfile position
Returns
line number corresponding to the given file position

This function performs a binary search on the line table (view->ln_tbl) to find the line number corresponding to the specified file position (target). It returns the index of the line in the line table that is closest to the target position without exceeding it. If the target position is not found, it returns the previous line number.

Definition at line 1902 of file view_engine.c.

1902 {
1903 off_t low = 0;
1904 off_t high = view->ln_tbl_size - 1;
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)
1909 return guess;
1910 if (view->ln_tbl[guess] < position) {
1911 prev_ln_no = guess;
1912 low = guess + 1;
1913 } else
1914 high = guess - 1;
1915 }
1916 return prev_ln_no;
1917}

References View::ln_tbl, and View::ln_tbl_size.

Referenced by go_to_percent(), and go_to_position().

Here is the caller graph for this function:

◆ next_page()

void next_page ( View * view)

Advance to Next Page.

Parameters
viewdata structure

Advances from view->page_bot_pos to view the next page of content. view->page_bot_pos must be set properly when calling this function. If the current bottom position of the page is at the end of the file, the function returns without making any changes. Otherwise, it resets the maximum column and current line position to the top of the page, updates the file position to the current bottom position of the page, and sets the top position and line number of the page accordingly. Finally, it calls the function to display the new page content.

Definition at line 1338 of file view_engine.c.

1338 {
1339
1340 view->file_pos = view->ln_tbl[view->ln_no];
1341 if (view->file_pos == view->file_size)
1342 return;
1343 view->maxcol = 0;
1344 view->cury = 0;
1345 view->page_top_ln_no = view->ln_no;
1347}
void view_display_page(View *)
Display Current Page.

References View::cury, View::file_pos, View::file_size, View::ln_no, View::ln_tbl, View::maxcol, View::page_top_ln_no, and view_display_page().

Referenced by go_to_eof(), go_to_line(), go_to_percent(), go_to_position(), new_view_file(), prev_page(), view_cmd_processor(), and view_file().

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

◆ prev_page()

void prev_page ( View * view)

display previous page

Parameters
viewdata structure

Displays the previous page starting at (view->page_top_ln_no - view->scroll_lines).

Definition at line 1270 of file view_engine.c.

1270 {
1271 off_t ln_no;
1272 if (view->page_top_ln_no == 0)
1273 return;
1274 view->cury = 0;
1275 view->ln_no = view->page_top_ln_no;
1276 uint scroll, avail, scroll_this_line;
1277 if (view->wrap) {
1278 scroll = view->scroll_lines;
1279 ln_no = view->page_top_ln_no;
1280 while (scroll > 0) {
1281 get_line(view, ln_no);
1282 fmt_line(view);
1283 view->page_top_sl = (view->cur.sl_cnt > 1);
1284 if (view->page_top_sl == false) {
1285 scroll--;
1286 if (ln_no > 0)
1287 ln_no--;
1288 continue;
1289 }
1290 if (ln_no == view->page_top_ln_no && ln_no != view->ln_no_max) {
1291 view->cur.sl_idx = view->page_top_sl_idx;
1292 if (view->cur.sl_idx == 0) {
1293 if (ln_no > 0)
1294 ln_no--;
1295 continue;
1296 }
1297 avail = view->cur.sl_idx;
1298 } else
1299 avail = view->cur.sl_cnt;
1300 scroll_this_line = min(scroll, avail);
1301 scroll -= scroll_this_line;
1302 if (ln_no == view->page_top_ln_no && ln_no != view->ln_no_max)
1303 view->cur.sl_idx -= scroll_this_line;
1304 else
1305 view->cur.sl_idx = view->cur.sl_cnt - scroll_this_line;
1306 if (ln_no > 0)
1307 ln_no--;
1308 }
1309 ln_no++;
1310 view->page_top_sl_idx = view->cur.sl_idx;
1311 view->page_top_sl_cnt = view->cur.sl_cnt;
1312 view->page_top_ln_no = ln_no;
1313 view->ln_no = view->page_top_ln_no;
1314 view->page_top_sl = (view->page_top_sl_cnt > 1);
1315 } else {
1316 view->ln_no = view->page_top_ln_no;
1317 view->cury = 0;
1318 if (view->ln_no - view->scroll_lines >= 0)
1319 view->ln_no -= view->scroll_lines;
1320 else
1321 view->ln_no = 0;
1322 view->page_top_ln_no = view->ln_no;
1323 }
1324 next_page(view);
1325}
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:91
void get_line(View *, off_t)
int fmt_line(View *)
Format Line for Display.

References View::cur, View::cury, fmt_line(), get_line(), View::ln_no, View::ln_no_max, next_page(), View::page_top_ln_no, View::page_top_sl, View::page_top_sl_cnt, View::page_top_sl_idx, View::scroll_lines, SplitLine::sl_cnt, SplitLine::sl_idx, and View::wrap.

Referenced by go_to_eof(), and view_cmd_processor().

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

◆ scroll_down()

void scroll_down ( View * view,
uint n )

Scroll Down by n Lines.

Parameters
viewPointer to the View structure containing the state and parameters of the view application. This structure is used to access and modify the state of the application as needed.
nThe number of lines to scroll down. This parameter specifies how many lines the view should move down in the file, effectively advancing the display by n lines. The function will handle scrolling, updating the current line number, and refreshing the display accordingly.

Definition at line 1505 of file view_engine.c.

1505 {
1506 uint scroll, scroll_this_line, avail;
1507 off_t ln_no;
1508 UiSurface *sfc = view->sfc;
1509 view->f_bod = false;
1510 if (view->wrap) {
1511 // Set Top Line State
1512 scroll = n;
1513 ln_no = view->page_top_ln_no;
1514 while (scroll > 0) {
1515 get_line(view, ln_no);
1516 if (view->f_eod)
1517 break;
1518 fmt_line(view);
1519 view->page_top_sl = (view->cur.sl_cnt > 1);
1520 if (view->page_top_sl == false) {
1521 ln_no++;
1522 scroll--;
1523 continue;
1524 }
1525 if (ln_no == view->page_top_ln_no)
1526 view->cur.sl_idx = view->page_top_sl_idx;
1527 avail = view->cur.sl_cnt - 1 - view->cur.sl_idx;
1528 scroll_this_line = min(scroll, avail);
1529 scroll -= scroll_this_line;
1530 if (ln_no == view->page_top_ln_no)
1531 view->cur.sl_idx += scroll_this_line;
1532 else
1533 view->cur.sl_idx += scroll_this_line - 1;
1534 if (scroll != 0)
1535 ln_no++;
1536 }
1537 view->page_top_sl_idx = view->cur.sl_idx;
1538 view->page_top_sl_cnt = view->cur.sl_cnt;
1539 view->page_top_ln_no = ln_no;
1540 view->page_top_sl = (view->cur.sl_cnt > 1);
1541 // Set Bottom Line State
1542 scroll = n;
1543 ln_no = view->page_bot_ln_no;
1544 while (scroll > 0) {
1545 get_line(view, ln_no);
1546 if (view->f_eod)
1547 break;
1548 fmt_line(view);
1549 view->page_bot_sl = (view->cur.sl_cnt > 1);
1550 if (view->page_bot_sl == false) {
1551 ln_no++;
1552 scroll--;
1553 continue;
1554 }
1555 if (ln_no == view->page_bot_ln_no)
1556 view->cur.sl_idx = view->page_bot_sl_idx;
1557 avail = view->cur.sl_cnt - 1 - view->cur.sl_idx;
1558 if (avail == 0) {
1559 ln_no++;
1560 continue;
1561 }
1562 scroll_this_line = min(scroll, avail);
1563 scroll -= scroll_this_line;
1564 if (ln_no == view->page_bot_ln_no)
1565 view->cur.sl_idx += scroll_this_line;
1566 else
1567 view->cur.sl_idx += scroll_this_line - 1;
1568 view->page_bot_sl_idx = view->cur.sl_idx;
1569 view->page_bot_sl_cnt = view->cur.sl_cnt;
1570 view->page_bot_ln_no = ln_no;
1571 view->page_bot_sl = (view->cur.sl_cnt > 1);
1572 view->ln_no = view->page_bot_ln_no;
1573 if (view->f_ln)
1574 ui_wscrl(sfc, LNNO, 1);
1575 ui_wscrl(sfc, PAD, scroll_this_line);
1576 view->cury = view->scroll_lines - scroll_this_line;
1577 ui_cursor_move(sfc, PAD, view->cury, 0);
1579 if (scroll != 0)
1580 ln_no++;
1581 }
1582 } else {
1583 view->ln_no = view->page_bot_ln_no;
1584 if (view->ln_no >= view->ln_no_max)
1585 return;
1586 if (n > view->scroll_lines) {
1587 if (view->f_ln) {
1588 ui_cursor_move(sfc, LNNO, 0, 0);
1589 ui_wclrtobot(sfc, LNNO);
1590 }
1591 ui_cursor_move(sfc, PAD, 0, 0);
1592 ui_wclrtobot(sfc, PAD);
1593 } else {
1594 if (view->f_ln)
1595 ui_wscrl(sfc, LNNO, n);
1596 ui_wscrl(sfc, PAD, n);
1597 if (n < view->scroll_lines)
1598 view->cury = view->scroll_lines - n;
1599 }
1600 view->page_top_ln_no += n;
1601 scroll = n;
1602 while (scroll > 0) {
1603 if (view->ln_no >= view->ln_no_max)
1604 break;
1605 view->ln_no++;
1606 get_line(view, view->ln_no);
1607 if (view->f_eod)
1608 break;
1609 fmt_line(view);
1610 ui_cursor_move(sfc, PAD, view->cury, 0);
1612 if (view->cury == view->scroll_lines)
1613 break;
1614 }
1615 view->page_bot_ln_no = view->ln_no;
1616 }
1617 return;
1618}
int ui_wclrtobot(UiSurface *s, uint w)
int ui_cursor_move(UiSurface *s, uint w, uint y, uint x)
Definition ui_ncurses.c:727
int ui_wscrl(UiSurface *s, uint w, int rows)
void display_line(View *)
Display Line on Padparam View *view data structure.
A drawable surface in the NotCurses backend.

References View::cur, View::cury, display_line(), View::f_bod, View::f_eod, View::f_ln, fmt_line(), get_line(), View::ln_no, View::ln_no_max, LNNO, PAD, View::page_bot_ln_no, View::page_bot_sl, View::page_bot_sl_cnt, View::page_bot_sl_idx, View::page_top_ln_no, View::page_top_sl, View::page_top_sl_cnt, View::page_top_sl_idx, View::scroll_lines, View::sfc, SplitLine::sl_cnt, SplitLine::sl_idx, ui_cursor_move(), ui_wclrtobot(), ui_wscrl(), and View::wrap.

Referenced by view_cmd_processor().

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

◆ scroll_up()

void scroll_up ( View * view,
uint n )

Scroll Up by n Lines.

Parameters
viewPointer to the View structure containing the state and parameters of the view application. This structure is used to access and modify the state of the application as needed.
nThe number of lines to scroll up. This parameter specifies how many lines the view should move up in the file, effectively moving the display up by n lines. The function will handle scrolling, updating the current line number, and refreshing the display accordingly.

Definition at line 1629 of file view_engine.c.

1629 {
1630 uint scroll, avail, scroll_this_line;
1631 off_t ln_no;
1632 view->f_eod = false;
1633 if (view->page_top_ln_no == 0) {
1634 if (view->wrap) {
1635 if (view->page_top_sl == false || view->page_top_sl_idx == 0)
1636 return;
1637 } else
1638 return;
1639 }
1640 UiSurface *sfc = view->sfc;
1641 if (n > view->scroll_lines) {
1642 if (view->f_ln) {
1643 ui_cursor_move(sfc, LNNO, 0, 0);
1644 ui_wclrtobot(sfc, LNNO);
1645 }
1646 ui_cursor_move(sfc, PAD, 0, 0);
1647 ui_wclrtobot(sfc, PAD);
1648 } else {
1649 if (view->f_ln)
1650 ui_wscrl(sfc, LNNO, -n);
1651 ui_wscrl(sfc, PAD, -n);
1652 }
1653 ui_cursor_move(sfc, PAD, 0, 0);
1654 if (view->wrap) {
1655 scroll = n;
1656 ln_no = view->page_top_ln_no;
1657 while (scroll > 0) {
1658 get_line(view, ln_no);
1659 if (view->f_bod)
1660 break;
1661 fmt_line(view);
1662 view->page_top_sl = (view->cur.sl_cnt > 1);
1663 if (view->page_top_sl == false) {
1664 scroll--;
1665 if (ln_no > 0)
1666 ln_no--;
1667 continue;
1668 }
1669 if (ln_no == view->page_top_ln_no) {
1670 view->cur.sl_idx = view->page_top_sl_idx;
1671 if (view->cur.sl_idx == 0) {
1672 if (ln_no > 0)
1673 ln_no--;
1674 continue;
1675 }
1676 avail = view->cur.sl_idx;
1677 } else
1678 avail = view->cur.sl_cnt;
1679 scroll_this_line = min(scroll, avail);
1680 scroll -= scroll_this_line;
1681 if (ln_no == view->page_top_ln_no)
1682 view->cur.sl_idx -= scroll_this_line;
1683 else
1684 view->cur.sl_idx = view->cur.sl_cnt - scroll_this_line;
1685 if (scroll == 0)
1686 break;
1687 }
1688 view->page_top_sl_idx = view->cur.sl_idx;
1689 view->page_top_sl_cnt = view->cur.sl_cnt;
1690 view->page_top_ln_no = ln_no;
1691 view->page_top_sl = (view->page_top_sl_cnt > 1);
1692
1693 view->cury = 0;
1694 scroll = n;
1695 while (scroll > 0) {
1696 if (view->ln_no != view->page_top_ln_no) {
1697 get_line(view, view->ln_no);
1698 if (view->f_eod)
1699 break;
1700 fmt_line(view);
1701 }
1703 scroll--;
1704 view->ln_no++;
1705 }
1706 view->ln_no--;
1707
1708 // Set Bottom Line State
1709 scroll = n;
1710 ln_no = view->page_bot_ln_no;
1711 while (scroll > 0) {
1712 get_line(view, ln_no);
1713 if (view->f_bod)
1714 break;
1715 fmt_line(view);
1716 view->page_bot_sl = (view->cur.sl_cnt > 1);
1717 if (view->page_bot_sl == false) {
1718 scroll--;
1719 if (ln_no > 0)
1720 ln_no--;
1721 continue;
1722 }
1723 if (ln_no == view->page_bot_ln_no) {
1724 view->cur.sl_idx = view->page_bot_sl_idx;
1725 if (view->cur.sl_idx == 0) {
1726 ln_no--;
1727 continue;
1728 }
1729 avail = view->cur.sl_idx;
1730 } else
1731 avail = view->cur.sl_cnt;
1732 scroll_this_line = min(scroll, avail);
1733 scroll -= scroll_this_line;
1734 if (ln_no == view->page_bot_ln_no)
1735 view->cur.sl_idx -= scroll_this_line;
1736 else
1737 view->cur.sl_idx = view->cur.sl_cnt - scroll_this_line;
1738 if (ln_no > 0)
1739 ln_no--;
1740 }
1741 ln_no++;
1742 view->page_bot_sl_idx = view->cur.sl_idx;
1743 view->page_bot_sl_cnt = view->cur.sl_cnt;
1744 view->page_bot_ln_no = ln_no;
1745 view->page_bot_sl = (view->cur.sl_cnt > 1);
1746 } else {
1747 view->cury = 0;
1748 scroll = n;
1749 while (scroll > 0) {
1750 view->ln_no = view->page_top_ln_no - scroll;
1751 if (view->ln_no < 0)
1752 view->ln_no = 0;
1753 get_line(view, view->ln_no);
1754 if (view->f_eod)
1755 break;
1756 fmt_line(view);
1758 scroll--;
1759 view->ln_no++;
1760 }
1761 view->ln_no--;
1762 }
1763 return;
1764}

References View::cur, View::cury, display_line(), View::f_bod, View::f_eod, View::f_ln, fmt_line(), get_line(), View::ln_no, LNNO, PAD, View::page_bot_ln_no, View::page_bot_sl, View::page_bot_sl_cnt, View::page_bot_sl_idx, View::page_top_ln_no, View::page_top_sl, View::page_top_sl_cnt, View::page_top_sl_idx, View::scroll_lines, View::sfc, SplitLine::sl_cnt, SplitLine::sl_idx, ui_cursor_move(), ui_wclrtobot(), ui_wscrl(), and View::wrap.

Referenced by view_cmd_processor().

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

◆ search()

bool search ( View * view,
int search_cmd,
char * regex_pattern )

Search for Regular Expression Pattern.

Parameters
viewPointer to View Structure
search_cmdSearch Command Character ('/' or '?')
regex_patternRegular Expression Pattern to Search For
Returns
true if a match is found and displayed, false if the search completes without finding a match or if an error occurs

The search performs extended regular expression matching, ignoring ANSI sequences and Unicode characters. Matches are highlighted on the screen, and the search continues until the page is full or the end of the file is reached. If the search wraps around the file, a message is displayed indicating that the search is complete. The search state is maintained in the view structure, allowing for repeat searches and tracking of the current search line. This function highlights all matches in the current ncurses pad, including those not displayed on the screen, and tracks the first and last match columns for prompt display. ANSI sequences and Unicode characters are stripped before matching, so matching corresponds to the visual display

initialize iteration

get line to scan

non-matching page filler

Display matching lines

Definition at line 1094 of file view_engine.c.

1094 {
1095 char tmp_str[MAXLEN];
1096 int REG_FLAGS = 0;
1097 regmatch_t pmatch[1];
1098 regex_t compiled_regex;
1099 int reti;
1100 uint line_offset;
1101 uint line_len;
1102 uint match_idx;
1103 uint match_len;
1104 mbstate_t mbstate;
1105 memset(&mbstate, 0, sizeof(mbstate));
1106 wchar_t wstr[2] = {L'\0', L'\0'};
1107 attr_t attr;
1108 ushort cpx;
1109 UiCell cc = {0};
1110 off_t prev_ln_no;
1111 bool f_page = false;
1112 UiSurface *sfc = view->sfc;
1113 if (*regex_pattern == '\0')
1114 return false;
1115 if (view->f_ignore_case)
1116 REG_FLAGS = REG_ICASE | REG_EXTENDED;
1117 else
1118 REG_FLAGS = REG_EXTENDED;
1119 reti = regcomp(&compiled_regex, regex_pattern, REG_FLAGS);
1120 if (reti) {
1121 Perror("Invalid pattern");
1122 return false;
1123 }
1124 bool rc = false;
1125 while (1) {
1127 if (search_cmd == '/') {
1128 if (view->srch_curr_ln_no == view->file_size)
1129 view->srch_curr_ln_no = 0;
1130 } else {
1131 if (view->srch_curr_ln_no == 0)
1132 view->srch_curr_ln_no = view->file_size;
1133 }
1134 if (view->srch_curr_ln_no == view->srch_beg_ln_no) {
1135 if (view->f_first_iter == true) {
1136 view->f_first_iter = false;
1137 view->f_search_complete = false;
1138 if (search_cmd == '/')
1139 view->cury = 0;
1140 else
1141 view->cury = view->scroll_lines + 1;
1142 } else {
1143 view->f_search_complete = true;
1144 goto cleanup;
1145 }
1146 }
1147 view->ln_no = view->srch_curr_ln_no;
1148 sync_ln(view);
1150 if (search_cmd == '/') {
1151 if (view->cury == view->scroll_lines)
1152 goto cleanup;
1153 prev_ln_no = view->srch_curr_ln_no;
1154 get_line(view, view->srch_curr_ln_no);
1155 view->page_bot_ln_no = view->srch_curr_ln_no;
1156 } else {
1157 if (view->cury == 0)
1158 goto cleanup;
1159 get_line(view, view->srch_curr_ln_no);
1160 prev_ln_no = view->srch_curr_ln_no;
1161 view->page_top_ln_no = view->srch_curr_ln_no;
1162 }
1163 fmt_line(view);
1164 reti = regexec(&compiled_regex, view->stripped_line_out,
1165 compiled_regex.re_nsub + 1, pmatch, REG_FLAGS);
1166 if (reti == REG_NOMATCH) {
1167 if (f_page) {
1169 if (search_cmd == '?')
1170 view->cury -= 2;
1172 if ((search_cmd == '/' && view->cury == view->scroll_lines) ||
1173 (search_cmd == '?' && view->cury == 1)) {
1174 break;
1175 }
1176 }
1177 view->srch_curr_ln_no += (search_cmd == '/') ? 1 : -1;
1178 continue;
1179 }
1180 if (reti) {
1181 char err_str[MAXLEN];
1182 regerror(reti, &compiled_regex, err_str, sizeof(err_str));
1183 strnz__cpy(tmp_str, "Regex match failed: ", MAXLEN - 1);
1184 strnz__cat(tmp_str, err_str, MAXLEN - 1);
1185 Perror(tmp_str);
1186 rc = false; /* Set status */
1187 goto cleanup;
1188 }
1189 rc = true;
1191 if (!f_page) {
1192 if (search_cmd == '/') {
1193 view->page_top_ln_no = prev_ln_no;
1194 ui_cursor_move(sfc, PAD, view->cury, 0);
1195 } else {
1196 view->page_bot_ln_no = view->ln_no;
1197 ui_cursor_move(sfc, PAD, 0, 0);
1198 }
1199 ui_wclrtobot(sfc, CMDLN);
1200 f_page = true;
1201 }
1202 if (search_cmd == '?')
1203 view->cury -= 2;
1204 bool f_first_match = true;
1205 view->first_match_x = -1;
1206 view->last_match_x = 0;
1207 line_len = strlen(view->stripped_line_out);
1208 line_offset = 0;
1209 while (1) {
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++) {
1213 cc = view->cmplx_buf[i];
1214#ifdef UAL_UI
1215 ui_getcchar(&cc, wstr, &attr, &cpx, nullptr);
1216 cpx = cp_nt_rev;
1217 ui_setcchar(&cc, wstr, attr, cpx, nullptr);
1218#else
1219 cc.channels = cell_nt_rev.channels;
1220#endif
1221 view->cmplx_buf[i] = cc;
1222 }
1223 if (f_first_match) {
1224 f_first_match = false;
1225 view->first_match_x = pmatch[0].rm_so;
1226 }
1227 view->last_match_x = line_offset + pmatch[0].rm_eo;
1228 line_offset += pmatch[0].rm_eo;
1229 if (line_offset >= line_len)
1230 break;
1231 view->line_out_p = view->stripped_line_out + line_offset;
1232 reti = regexec(&compiled_regex, view->line_out_p,
1233 compiled_regex.re_nsub + 1, pmatch, REG_FLAGS);
1234 if (reti == REG_NOMATCH)
1235 break;
1236 if (reti) {
1237 char msgbuf[100];
1238 regerror(reti, &compiled_regex, msgbuf, sizeof(msgbuf));
1239 sprintf(tmp_str, "Regex match failed: %s", msgbuf);
1240 Perror(tmp_str);
1241 rc = false; /* Set status */
1242 goto cleanup;
1243 }
1244 if (search_cmd == '/') {
1245 if (view->cury == view->scroll_lines - 1) {
1246 break;
1247 }
1248 } else if (view->cury == 1) {
1249 break;
1250 }
1251 }
1253 view->srch_curr_ln_no += (search_cmd == '/') ? 1 : -1;
1254 }
1255cleanup:
1256 regfree(&compiled_regex);
1257 view->ln_no = view->srch_curr_ln_no;
1258 return rc;
1259}
uint16_t attr_t
Definition ui_backend.h:256
int ui_getcchar(const UiCell *uc, wchar_t *wstr, attr_t *attrs, ushort *pair, void *opts)
int ui_setcchar(UiCell *wch, const wchar_t *wc, const attr_t attrs, short pair, const void *opts)
#define MAXLEN
Definition curskeys.c:15
ushort cp_nt_rev
Definition dwin.c:152
UiCell cell_nt_rev
Definition dwin.c:95
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:537
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:566

References cell_nt_rev, nccell::channels, CMDLN, View::cmplx_buf, View::cury, display_line(), View::f_first_iter, View::f_ignore_case, View::f_search_complete, View::file_size, View::first_match_x, fmt_line(), get_line(), View::last_match_x, View::line_out_p, View::ln_no, PAD, View::page_bot_ln_no, View::page_top_ln_no, Perror(), View::scroll_lines, View::sfc, View::srch_beg_ln_no, View::srch_curr_ln_no, View::stripped_line_out, strnz__cat(), strnz__cpy(), sync_ln(), ui_cursor_move(), and ui_wclrtobot().

Referenced by view_cmd_processor().

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

◆ sync_ln()

void sync_ln ( View * view)

Synchronize Line Table with Current File Position.

Parameters
viewdata Structure

The line table (view->ln_tbl) is an array that stores the file position of each line. The index (view->ln_no + 1) corresponds to the current line number. (the line number table is 0-based, while line numbering starts at 1).

If the line or position requested is not in the line table, this function reads forward to sycn. If the line or positione requested is behind the current line table index, the line index will be decremented it matches the file position.

Definition at line 1996 of file view_engine.c.

1996 {
1997 int c = 0;
1998 off_t idx;
1999 off_t target_pos;
2000 if (view->ln_tbl[view->ln_no] == view->file_pos)
2001 return;
2002 target_pos = view->file_pos;
2003 view->file_pos = view->ln_tbl[view->ln_tbl_cnt];
2004 if (view->file_pos < target_pos) {
2005 view->ln_no = view->ln_tbl_cnt;
2006 while (view->ln_max_pos < target_pos) {
2007 get_next_char();
2008 if (view->f_eod)
2009 return;
2010 }
2011 } else if (view->ln_tbl[view->ln_no] > target_pos) {
2012 idx = view->ln_no - 1;
2013 while (view->ln_tbl[idx] > target_pos)
2014 idx--;
2015 view->ln_no = idx;
2016 view->file_pos = view->ln_tbl[view->ln_no];
2017 } else {
2018 view->ln_no = view->ln_tbl_cnt;
2019 view->file_pos = view->ln_tbl[view->ln_no];
2020 }
2021}
#define get_next_char()
read the next characater from the virtual file
Definition view_engine.c:53

References View::f_eod, View::file_pos, View::ln_max_pos, View::ln_no, View::ln_tbl, and View::ln_tbl_cnt.

Referenced by go_to_eof(), go_to_line(), go_to_percent(), go_to_position(), and search().

Here is the caller graph for this function: