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 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 page_next (View *view)
 Advance to Next Page.
void page_prev (View *view)
 display previous page
void scroll_next (View *view, uint n)
 Scroll Down by n Lines.
void scroll_prev (View *view, uint n)
 Move the view scope n lines toward the beginning of the file.
bool search (View *view, int search_cmd, char *regex_pattern)
 Search for Regular Expression Pattern.
void sync_ln (View *view, off_t ln_no)
 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 1973 of file view_engine.c.

1973 {
1974 if (view->ln_tbl == nullptr)
1975 return;
1976 free(view->ln_tbl);
1977 view->ln_tbl = nullptr;
1978 view->ln_tbl_size = 0;
1979 view->ln_pos_max = 0;
1980 view->ln_no = 0;
1981}
View * view
Definition mem.c:38

References View::ln_no, View::ln_pos_max, 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 __go_to_eof

Definition at line 1856 of file view_engine.c.

1856 {
1857 sync_pos(view, view->file_size);
1858 view->ln_no--;
1859 view->ln_no_max = view->ln_no;
1860 if (view->wrap) {
1861 view->page_top_ln_no = view->ln_no;
1862 view->f_eod = true;
1863 page_prev(view);
1864 return;
1865 }
1866 if (view->ln_no > view->scroll_lines)
1867 view->ln_no -= view->scroll_lines - 1;
1868 // else
1869 // view->page_top_ln_no = 0;
1870 view->page_top_ln_no = view->ln_no;
1871 // view->page_top_pos = view->ln_tbl[view->ln_no];
1872 // view->page_bot_pos = view->page_top_pos;
1873 // view->file_pos = view->page_top_pos;
1874 view->cury = 0;
1875 page_next(view);
1876}
void sync_pos(View *, off_t pos)
void page_prev(View *)
display previous page
void page_next(View *)
Advance to Next Page.

References View::cury, View::f_eod, View::file_size, View::ln_no, View::ln_no_max, page_next(), page_prev(), View::page_top_ln_no, View::scroll_lines, sync_pos(), 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 1898 of file view_engine.c.

1898 {
1899 if (line_idx < 0 || line_idx > view->ln_tbl_size - 1) {
1900 ui_perror(_("Line number out of bounds"));
1901 return EOF;
1902 }
1903 sync_ln(view, line_idx);
1904 view->page_top_pos = view->file_pos;
1905 view->page_bot_pos = view->file_pos;
1906 // view->file_pos = view->page_top_pos;
1907 page_next(view);
1908 return 0;
1909}
#define _(String)
Definition amort.c:23
void sync_ln(View *, off_t ln_no)
Synchronize Line Table with Current File Position.
int ui_perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition ui_common.c:1257

References View::file_pos, View::ln_tbl_size, View::page_bot_pos, page_next(), View::page_top_pos, sync_ln(), and ui_perror().

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 1072 of file view_engine.c.

1072 {
1073 if (c == '\'')
1074 view->file_pos = view->mark_tbl[(NMARKS - 1)];
1075 else
1076 view->file_pos = view->mark_tbl[c - 'a'];
1077 if (view->file_pos == NULL_POSITION)
1078 ui_perror(_("Mark not set"));
1079 else
1080 go_to_position(view, view->file_pos);
1081}
#define NMARKS
Definition view.h:33
#define NULL_POSITION
Definition view.h:36
void go_to_position(View *, off_t)
Go to Specific File Position.

References View::file_pos, go_to_position(), View::mark_tbl, and ui_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 1882 of file view_engine.c.

1882 {
1883 off_t pos;
1884 if (view->file_size < 0) {
1885 ui_perror(_("Cannot determine file length"));
1886 return;
1887 }
1888 pos = (percent * view->file_size) / 100;
1889 go_to_position(view, pos);
1890}

References View::file_size, go_to_position(), and ui_perror().

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 pos )

Go to Specific File Position.

Parameters
viewdata Structure
go_to_pos

Definition at line 1915 of file view_engine.c.

1915 {
1916 sync_pos(view, pos);
1917 page_next(view);
1918}

References page_next(), and sync_pos().

Here is the call 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 1992 of file view_engine.c.

1992 {
1993 // view->ln_tbl[0] is set to 0 in initialize_line_table
1994 // view->ln_tbl[1] is the second line
1995 view->ln_no++;
1996 if (view->file_pos <= view->ln_pos_max)
1997 return;
1998 if (view->ln_no > view->ln_tbl_size - 1) {
1999 view->ln_tbl_size += LINE_TBL_INCR;
2000 view->ln_tbl =
2001 (off_t *)realloc(view->ln_tbl, view->ln_tbl_size * sizeof(off_t));
2002 if (view->ln_tbl == nullptr) {
2003 ui_perror(_("Memory allocation failed"));
2004 exit(EXIT_FAILURE);
2005 }
2006 }
2007 view->ln_no_max = view->ln_no;
2008 view->ln_pos_max = view->file_pos;
2009 view->ln_tbl[view->ln_no] = view->file_pos;
2010}
#define LINE_TBL_INCR
Definition view.h:46

References View::file_pos, View::ln_no, View::ln_no_max, View::ln_pos_max, View::ln_tbl, View::ln_tbl_size, and ui_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 1954 of file view_engine.c.

1954 {
1955 view->ln_tbl_size = LINE_TBL_INCR;
1956 view->ln_tbl = (off_t *)calloc(view->ln_tbl_size, sizeof(off_t));
1957 if (view->ln_tbl == nullptr) {
1958 ui_perror(_("Memory allocation failed"));
1959 exit(EXIT_FAILURE);
1960 }
1961 view->ln_pos_max = 0;
1962 view->ln_tbl[0] = 0;
1963 view->ln_no = 0;
1964}

References View::ln_no, View::ln_pos_max, View::ln_tbl, View::ln_tbl_size, and ui_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 1930 of file view_engine.c.

1930 {
1931 off_t low = 0;
1932 off_t high = view->ln_tbl_size - 1;
1933 off_t prev_ln_no = 0;
1934 while (low <= high) {
1935 off_t guess = low + (high - low) / 2;
1936 if (view->ln_tbl[guess] == position)
1937 return guess;
1938 if (view->ln_tbl[guess] < position) {
1939 prev_ln_no = guess;
1940 low = guess + 1;
1941 } else
1942 high = guess - 1;
1943 }
1944 return prev_ln_no;
1945}

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

◆ page_next()

void page_next ( 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. __page_next

Definition at line 1349 of file view_engine.c.

1349 {
1350
1351 view->file_pos = view->ln_tbl[view->ln_no];
1352 if (view->file_pos == view->file_size)
1353 return;
1354 view->maxcol = 0;
1355 view->cury = 0;
1356 view->page_top_ln_no = view->ln_no;
1358}
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_position(), new_view_file(), page_prev(), view_cmd_processor(), and view_file().

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

◆ page_prev()

void page_prev ( View * view)

display previous page

Parameters
viewdata structure

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

Definition at line 1280 of file view_engine.c.

1280 {
1281 off_t ln_no;
1282 if (view->page_top_ln_no == 0)
1283 return;
1284 view->cury = 0;
1285 view->ln_no = view->page_top_ln_no;
1286 uint scroll, avail, scroll_this_line;
1287 if (view->wrap) {
1288 scroll = view->scroll_lines;
1289 ln_no = view->page_top_ln_no;
1290 while (scroll > 0) {
1291 get_line(view, ln_no);
1292 fmt_line(view);
1293 view->page_top_sl = (view->cur.sl_cnt > 1);
1294 if (view->page_top_sl == false) {
1295 scroll--;
1296 if (ln_no > 0)
1297 ln_no--;
1298 continue;
1299 }
1300 if (ln_no == view->page_top_ln_no && ln_no != view->ln_no_max) {
1301 view->cur.sl_idx = view->page_top_sl_idx;
1302 if (view->cur.sl_idx == 0) {
1303 if (ln_no > 0)
1304 ln_no--;
1305 continue;
1306 }
1307 avail = view->cur.sl_idx;
1308 } else
1309 avail = view->cur.sl_cnt;
1310 scroll_this_line = min(scroll, avail);
1311 scroll -= scroll_this_line;
1312 if (ln_no == view->page_top_ln_no && ln_no != view->ln_no_max)
1313 view->cur.sl_idx -= scroll_this_line;
1314 else
1315 view->cur.sl_idx = view->cur.sl_cnt - scroll_this_line;
1316 if (ln_no > 0)
1317 ln_no--;
1318 }
1319 ln_no++;
1320 view->page_top_sl_idx = view->cur.sl_idx;
1321 view->page_top_sl_cnt = view->cur.sl_cnt;
1322 view->page_top_ln_no = ln_no;
1323 view->ln_no = view->page_top_ln_no;
1324 view->page_top_sl = (view->page_top_sl_cnt > 1);
1325 } else {
1326 view->ln_no = view->page_top_ln_no;
1327 view->cury = 0;
1328 if (view->ln_no - view->scroll_lines >= 0)
1329 view->ln_no -= view->scroll_lines;
1330 else
1331 view->ln_no = 0;
1332 view->page_top_ln_no = view->ln_no;
1333 }
1334 page_next(view);
1335}
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:104
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, page_next(), 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_next()

void scroll_next ( 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.
nadd n to page line pointers, moving the scope of the view window toward the end of data (eod). __scroll_next

Definition at line 1521 of file view_engine.c.

1521 {
1522 uint scroll, scroll_this_line, avail;
1523 off_t ln_no;
1524 UiSurface *sfc = view->sfc;
1525 view->f_bod = false;
1526 view->ln_no = view->page_bot_ln_no;
1527 if (view->wrap) {
1528 // Set Top Line State
1529 scroll = n;
1530 ln_no = view->page_top_ln_no;
1531 while (scroll > 0) {
1532 get_line(view, ln_no);
1533 if (view->f_eod) {
1534 view->ln_no = ln_no;
1535 view->ln_no_max = ln_no;
1536 break;
1537 }
1538 fmt_line(view);
1539 view->page_top_sl = (view->cur.sl_cnt > 1);
1540 if (view->page_top_sl == false) {
1541 ln_no++;
1542 scroll--;
1543 continue;
1544 }
1545 if (ln_no == view->page_top_ln_no)
1546 view->cur.sl_idx = view->page_top_sl_idx;
1547 avail = view->cur.sl_cnt - 1 - view->cur.sl_idx;
1548 scroll_this_line = min(scroll, avail);
1549 scroll -= scroll_this_line;
1550 if (ln_no == view->page_top_ln_no)
1551 view->cur.sl_idx += scroll_this_line;
1552 else
1553 view->cur.sl_idx += scroll_this_line - 1;
1554 if (scroll != 0)
1555 ln_no++;
1556 }
1557 view->page_top_sl_idx = view->cur.sl_idx;
1558 view->page_top_sl_cnt = view->cur.sl_cnt;
1559 view->page_top_ln_no = ln_no;
1560 view->page_top_sl = (view->cur.sl_cnt > 1);
1561 // Set Bottom Line State
1562 scroll = n;
1563 ln_no = view->page_bot_ln_no;
1564 while (scroll > 0) {
1565 get_line(view, ln_no);
1566 if (view->f_eod) {
1567 view->ln_no_max = view->ln_no;
1568 break;
1569 }
1570 fmt_line(view);
1571 view->page_bot_sl = (view->cur.sl_cnt > 1);
1572 if (view->page_bot_sl == false) {
1573 ln_no++;
1574 scroll--;
1575 continue;
1576 }
1577 if (ln_no == view->page_bot_ln_no)
1578 view->cur.sl_idx = view->page_bot_sl_idx;
1579 avail = view->cur.sl_cnt - 1 - view->cur.sl_idx;
1580 if (avail == 0) {
1581 ln_no++;
1582 continue;
1583 }
1584 scroll_this_line = min(scroll, avail);
1585 scroll -= scroll_this_line;
1586 if (ln_no == view->page_bot_ln_no)
1587 view->cur.sl_idx += scroll_this_line;
1588 else
1589 view->cur.sl_idx += scroll_this_line - 1;
1590 view->page_bot_sl_idx = view->cur.sl_idx;
1591 view->page_bot_sl_cnt = view->cur.sl_cnt;
1592 view->page_bot_ln_no = ln_no;
1593 view->page_bot_sl = (view->cur.sl_cnt > 1);
1594 view->ln_no = view->page_bot_ln_no;
1595 if (view->f_ln)
1596 ui_wscrl(sfc, LNNO, 1);
1597 ui_wscrl(sfc, PAD, scroll_this_line);
1598 view->cury = view->scroll_lines - scroll_this_line;
1599 ui_cursor_move(sfc, PAD, view->cury, 0);
1601 if (scroll != 0)
1602 ln_no++;
1603 }
1604 } else {
1605 view->ln_no = view->page_bot_ln_no;
1606 if (view->ln_no_max > 0 && view->ln_no >= view->ln_no_max)
1607 return;
1608 if (view->f_eod) {
1609 view->ln_no_max = view->ln_no;
1610 return;
1611 }
1612 if (n > view->scroll_lines) {
1613 if (view->f_ln) {
1614 ui_cursor_move(sfc, LNNO, 0, 0);
1615 ui_wclrtobot(sfc, LNNO);
1616 }
1617 ui_cursor_move(sfc, PAD, 0, 0);
1618 ui_wclrtobot(sfc, PAD);
1619 } else {
1620 if (view->ln_no_max == 0 || view->ln_no < view->ln_no_max) {
1621 if (view->f_ln)
1622 ui_wscrl(sfc, LNNO, n);
1623 ui_wscrl(sfc, PAD, n);
1624 if (n < view->scroll_lines)
1625 view->cury = view->scroll_lines - n;
1626 }
1627 }
1628 view->page_top_ln_no += n;
1629 scroll = n;
1630 while (scroll > 0) {
1631 if (view->ln_no_max > 0 && view->ln_no >= view->ln_no_max)
1632 break;
1633 view->ln_no++;
1634 get_line(view, view->ln_no);
1635 if (view->f_eod) {
1636 view->ln_no--;
1637 view->ln_no_max = view->ln_no;
1638 break;
1639 }
1640 fmt_line(view);
1641 ui_cursor_move(sfc, PAD, view->cury, 0);
1643 if (view->cury == view->scroll_lines)
1644 break;
1645 }
1646 view->page_bot_ln_no = view->ln_no;
1647 }
1648 return;
1649}
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_wclrtobot(UiSurface *s, ss_t w)
Set the style of a surface window.
void display_line(View *)
Display Line on Padparam View *view data structure.

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, 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_prev()

void scroll_prev ( View * view,
uint n )

Move the view scope n lines toward the beginning of the file.

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.
nsubtract n from page line pointers, moving the scope of the view window toward the beginning of data (bod). __scroll_prev

Definition at line 1658 of file view_engine.c.

1658 {
1659 uint scroll, avail, scroll_this_line;
1660 off_t ln_no;
1661 view->f_eod = false;
1662 if (view->page_top_ln_no == 0) {
1663 if (view->wrap) {
1664 if (view->page_top_sl == false || view->page_top_sl_idx == 0)
1665 return;
1666 } else
1667 return;
1668 }
1669 UiSurface *sfc = view->sfc;
1670 if (n > view->scroll_lines) {
1671 if (view->f_ln) {
1672 ui_cursor_move(sfc, LNNO, 0, 0);
1673 ui_wclrtobot(sfc, LNNO);
1674 }
1675 ui_cursor_move(sfc, PAD, 0, 0);
1676 ui_wclrtobot(sfc, PAD);
1677 } else {
1678 if (view->f_ln)
1679 ui_wscrl(sfc, LNNO, -n);
1680 ui_wscrl(sfc, PAD, -n);
1681 view->page_bot_ln_no -= n;
1682 }
1683 ui_cursor_move(sfc, PAD, 0, 0);
1684 if (view->wrap) {
1685 scroll = n;
1686 ln_no = view->page_top_ln_no;
1687 while (scroll > 0) {
1688 get_line(view, ln_no);
1689 if (view->f_bod)
1690 break;
1691 fmt_line(view);
1692 view->page_top_sl = (view->cur.sl_cnt > 1);
1693 if (view->page_top_sl == false) {
1694 scroll--;
1695 if (ln_no > 0)
1696 ln_no--;
1697 continue;
1698 }
1699 if (ln_no == view->page_top_ln_no) {
1700 view->cur.sl_idx = view->page_top_sl_idx;
1701 if (view->cur.sl_idx == 0) {
1702 if (ln_no > 0)
1703 ln_no--;
1704 continue;
1705 }
1706 avail = view->cur.sl_idx;
1707 } else
1708 avail = view->cur.sl_cnt;
1709 scroll_this_line = min(scroll, avail);
1710 scroll -= scroll_this_line;
1711 if (ln_no == view->page_top_ln_no)
1712 view->cur.sl_idx -= scroll_this_line;
1713 else
1714 view->cur.sl_idx = view->cur.sl_cnt - scroll_this_line;
1715 if (scroll == 0)
1716 break;
1717 }
1718 view->page_top_sl_idx = view->cur.sl_idx;
1719 view->page_top_sl_cnt = view->cur.sl_cnt;
1720 view->page_top_ln_no = ln_no;
1721 view->page_top_sl = (view->page_top_sl_cnt > 1);
1722
1723 view->cury = 0;
1724 scroll = n;
1725 while (scroll > 0) {
1726 if (view->ln_no != view->page_top_ln_no) {
1727 get_line(view, view->ln_no);
1728 if (view->f_eod) {
1729 view->ln_no_max = view->ln_no;
1730 break;
1731 }
1732 fmt_line(view);
1733 }
1735 scroll--;
1736 view->ln_no++;
1737 }
1738 view->ln_no--;
1739
1740 // Set Bottom Line State
1741 scroll = n;
1742 ln_no = view->page_bot_ln_no;
1743 while (scroll > 0) {
1744 get_line(view, ln_no);
1745 if (view->f_bod)
1746 break;
1747 fmt_line(view);
1748 view->page_bot_sl = (view->cur.sl_cnt > 1);
1749 if (view->page_bot_sl == false) {
1750 scroll--;
1751 if (ln_no > 0)
1752 ln_no--;
1753 continue;
1754 }
1755 if (ln_no == view->page_bot_ln_no) {
1756 view->cur.sl_idx = view->page_bot_sl_idx;
1757 if (view->cur.sl_idx == 0) {
1758 ln_no--;
1759 continue;
1760 }
1761 avail = view->cur.sl_idx;
1762 } else
1763 avail = view->cur.sl_cnt;
1764 scroll_this_line = min(scroll, avail);
1765 scroll -= scroll_this_line;
1766 if (ln_no == view->page_bot_ln_no)
1767 view->cur.sl_idx -= scroll_this_line;
1768 else
1769 view->cur.sl_idx = view->cur.sl_cnt - scroll_this_line;
1770 if (ln_no > 0)
1771 ln_no--;
1772 }
1773 ln_no++;
1774 view->page_bot_sl_idx = view->cur.sl_idx;
1775 view->page_bot_sl_cnt = view->cur.sl_cnt;
1776 view->page_bot_ln_no = ln_no;
1777 view->page_bot_sl = (view->cur.sl_cnt > 1);
1778 } else {
1779 view->cury = 0;
1780 scroll = n;
1781 while (scroll > 0) {
1782 view->ln_no = view->page_top_ln_no - scroll;
1783 if (view->ln_no < 0)
1784 view->ln_no = 0;
1785 get_line(view, view->ln_no);
1786 if (view->f_eod) {
1787 view->ln_no_max = view->ln_no;
1788 break;
1789 }
1790 fmt_line(view);
1792 scroll--;
1793 view->ln_no++;
1794 }
1795 view->ln_no--;
1796 }
1797 return;
1798}

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, 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 __search

initialize iteration

get line to scan

non-matching page filler

Display matching lines

Definition at line 1102 of file view_engine.c.

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

References View::cmplx_buf, cp_nt_rev, 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, View::page_bot_ln_no, View::page_top_ln_no, 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(), ui_perror(), 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,
off_t ln_no )

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.

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 until it matches the file position. __sync_ln

Definition at line 2024 of file view_engine.c.

2024 {
2025 int c = 0;
2026 // Advance view->ln_no_max to view->ln_no if necessary
2027 if (ln_no < view->ln_no_max) {
2028 view->file_pos = view->ln_tbl[ln_no];
2029 view->ln_no = ln_no;
2030 return;
2031 }
2032 while (view->ln_no_max < ln_no) {
2033 get_next_char();
2034 if (view->f_eod)
2035 break;
2036 }
2037}
#define get_next_char()
read the next characater from the virtual file
Definition view_engine.c:52

References View::f_eod, View::file_pos, View::ln_no, View::ln_no_max, and View::ln_tbl.

Referenced by go_to_line(), and search().

Here is the caller graph for this function: