version 1.7, 2014/04/25 13:38:21 |
version 1.8, 2015/11/05 22:08:44 |
|
|
* |
* |
* For more information, see the README file. |
* For more information, see the README file. |
*/ |
*/ |
|
/* |
|
* Modified for use with illumos. |
|
* Copyright 2014 Garrett D'Amore <garrett@damore.org> |
|
*/ |
|
|
|
|
/* |
/* |
* High level routines dealing with getting lines of input |
* High level routines dealing with getting lines of input |
* from the file being viewed. |
* from the file being viewed. |
* |
* |
* When we speak of "lines" here, we mean PRINTABLE lines; |
* When we speak of "lines" here, we mean PRINTABLE lines; |
|
|
extern volatile sig_atomic_t sigs; |
extern volatile sig_atomic_t sigs; |
extern int ignore_eoi; |
extern int ignore_eoi; |
extern int status_col; |
extern int status_col; |
extern POSITION start_attnpos; |
extern off_t start_attnpos; |
extern POSITION end_attnpos; |
extern off_t end_attnpos; |
#if HILITE_SEARCH |
|
extern int hilite_search; |
extern int hilite_search; |
extern int size_linebuf; |
extern int size_linebuf; |
#endif |
|
|
|
/* |
/* |
* Get the next line. |
* Get the next line. |
|
|
* a line. The new position is the position of the first character |
* a line. The new position is the position of the first character |
* of the NEXT line. The line obtained is the line starting at curr_pos. |
* of the NEXT line. The line obtained is the line starting at curr_pos. |
*/ |
*/ |
public POSITION |
off_t |
forw_line(curr_pos) |
forw_line(off_t curr_pos) |
POSITION curr_pos; |
|
{ |
{ |
POSITION base_pos; |
off_t base_pos; |
POSITION new_pos; |
off_t new_pos; |
register int c; |
register int c; |
int blankline; |
int blankline; |
int endline; |
int endline; |
int backchars; |
int backchars; |
|
|
get_forw_line: |
get_forw_line: |
if (curr_pos == NULL_POSITION) |
if (curr_pos == -1) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
#if HILITE_SEARCH |
|
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) |
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) |
/* |
/* |
* If we are ignoring EOI (command F), only prepare |
* If we are ignoring EOI (command F), only prepare |
|
|
* If we're not ignoring EOI, we *could* do the same, but |
* If we're not ignoring EOI, we *could* do the same, but |
* for efficiency we prepare several lines ahead at once. |
* for efficiency we prepare several lines ahead at once. |
*/ |
*/ |
prep_hilite(curr_pos, curr_pos + 3*size_linebuf, |
prep_hilite(curr_pos, curr_pos + 3*size_linebuf, |
ignore_eoi ? 1 : -1); |
ignore_eoi ? 1 : -1); |
#endif |
if (ch_seek(curr_pos)) { |
if (ch_seek(curr_pos)) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
|
|
/* |
/* |
* Step back to the beginning of the line. |
* Step back to the beginning of the line. |
*/ |
*/ |
base_pos = curr_pos; |
base_pos = curr_pos; |
for (;;) |
for (;;) { |
{ |
if (ABORT_SIGS()) { |
if (ABORT_SIGS()) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
c = ch_back_get(); |
c = ch_back_get(); |
if (c == EOI) |
if (c == EOI) |
break; |
break; |
if (c == '\n') |
if (c == '\n') { |
{ |
|
(void) ch_forw_get(); |
(void) ch_forw_get(); |
break; |
break; |
} |
} |
|
|
/* |
/* |
* Read forward again to the position we should start at. |
* Read forward again to the position we should start at. |
*/ |
*/ |
prewind(); |
prewind(); |
plinenum(base_pos); |
plinenum(base_pos); |
(void) ch_seek(base_pos); |
(void) ch_seek(base_pos); |
new_pos = base_pos; |
new_pos = base_pos; |
while (new_pos < curr_pos) |
while (new_pos < curr_pos) { |
{ |
if (ABORT_SIGS()) { |
if (ABORT_SIGS()) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
c = ch_forw_get(); |
c = ch_forw_get(); |
backchars = pappend(c, new_pos); |
backchars = pappend(c, new_pos); |
new_pos++; |
new_pos++; |
if (backchars > 0) |
if (backchars > 0) { |
{ |
|
pshift_all(); |
pshift_all(); |
new_pos -= backchars; |
new_pos -= backchars; |
while (--backchars >= 0) |
while (--backchars >= 0) |
|
|
* Read the first character to display. |
* Read the first character to display. |
*/ |
*/ |
c = ch_forw_get(); |
c = ch_forw_get(); |
if (c == EOI) |
if (c == EOI) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
blankline = (c == '\n' || c == '\r'); |
blankline = (c == '\n' || c == '\r'); |
|
|
/* |
/* |
* Read each character in the line and append to the line buffer. |
* Read each character in the line and append to the line buffer. |
*/ |
*/ |
for (;;) |
for (;;) { |
{ |
if (ABORT_SIGS()) { |
if (ABORT_SIGS()) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
if (c == '\n' || c == EOI) |
if (c == '\n' || c == EOI) { |
{ |
|
/* |
/* |
* End of the line. |
* End of the line. |
*/ |
*/ |
backchars = pflushmbc(); |
backchars = pflushmbc(); |
new_pos = ch_tell(); |
new_pos = ch_tell(); |
if (backchars > 0 && !chopline && hshift == 0) |
if (backchars > 0 && !chopline && hshift == 0) { |
{ |
|
new_pos -= backchars + 1; |
new_pos -= backchars + 1; |
endline = FALSE; |
endline = FALSE; |
} else |
} else |
|
|
* Append the char to the line and get the next char. |
* Append the char to the line and get the next char. |
*/ |
*/ |
backchars = pappend(c, ch_tell()-1); |
backchars = pappend(c, ch_tell()-1); |
if (backchars > 0) |
if (backchars > 0) { |
{ |
|
/* |
/* |
* The char won't fit in the line; the line |
* The char won't fit in the line; the line |
* is too long to print in the screen width. |
* is too long to print in the screen width. |
* End the line here. |
* End the line here. |
*/ |
*/ |
if (chopline || hshift > 0) |
if (chopline || hshift > 0) { |
{ |
do { |
do |
if (ABORT_SIGS()) { |
{ |
|
if (ABORT_SIGS()) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
c = ch_forw_get(); |
c = ch_forw_get(); |
} while (c != '\n' && c != EOI); |
} while (c != '\n' && c != EOI); |
new_pos = ch_tell(); |
new_pos = ch_tell(); |
endline = TRUE; |
endline = TRUE; |
quit_if_one_screen = FALSE; |
quit_if_one_screen = FALSE; |
} else |
} else { |
{ |
|
new_pos = ch_tell() - backchars; |
new_pos = ch_tell() - backchars; |
endline = FALSE; |
endline = FALSE; |
} |
} |
|
|
|
|
pdone(endline, 1); |
pdone(endline, 1); |
|
|
#if HILITE_SEARCH |
if (is_filtered(base_pos)) { |
if (is_filtered(base_pos)) |
|
{ |
|
/* |
/* |
* We don't want to display this line. |
* We don't want to display this line. |
* Get the next line. |
* Get the next line. |
|
|
|
|
if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) |
if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) |
set_status_col('*'); |
set_status_col('*'); |
#endif |
|
|
|
if (squeeze && blankline) |
if (squeeze && blankline) { |
{ |
|
/* |
/* |
* This line is blank. |
* This line is blank. |
* Skip down to the last contiguous blank line |
* Skip down to the last contiguous blank line |
* and pretend it is the one which we are returning. |
* and pretend it is the one which we are returning. |
*/ |
*/ |
while ((c = ch_forw_get()) == '\n' || c == '\r') |
while ((c = ch_forw_get()) == '\n' || c == '\r') |
if (ABORT_SIGS()) |
if (ABORT_SIGS()) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
if (c != EOI) |
if (c != EOI) |
(void) ch_back_get(); |
(void) ch_back_get(); |
|
|
* a line. The new position is the position of the first character |
* a line. The new position is the position of the first character |
* of the PREVIOUS line. The line obtained is the one starting at new_pos. |
* of the PREVIOUS line. The line obtained is the one starting at new_pos. |
*/ |
*/ |
public POSITION |
off_t |
back_line(curr_pos) |
back_line(off_t curr_pos) |
POSITION curr_pos; |
|
{ |
{ |
POSITION new_pos, begin_new_pos, base_pos; |
off_t new_pos, begin_new_pos, base_pos; |
int c; |
int c; |
int endline; |
int endline; |
int backchars; |
int backchars; |
|
|
get_back_line: |
get_back_line: |
if (curr_pos == NULL_POSITION || curr_pos <= ch_zero()) |
if (curr_pos == -1 || curr_pos <= ch_zero()) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
#if HILITE_SEARCH |
|
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) |
if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) |
prep_hilite((curr_pos < 3*size_linebuf) ? |
prep_hilite((curr_pos < 3*size_linebuf) ? |
0 : curr_pos - 3*size_linebuf, curr_pos, -1); |
0 : curr_pos - 3*size_linebuf, curr_pos, -1); |
#endif |
if (ch_seek(curr_pos-1)) { |
if (ch_seek(curr_pos-1)) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
|
|
if (squeeze) |
if (squeeze) { |
{ |
|
/* |
/* |
* Find out if the "current" line was blank. |
* Find out if the "current" line was blank. |
*/ |
*/ |
(void) ch_forw_get(); /* Skip the newline */ |
(void) ch_forw_get(); /* Skip the newline */ |
c = ch_forw_get(); /* First char of "current" line */ |
c = ch_forw_get(); /* First char of "current" line */ |
(void) ch_back_get(); /* Restore our position */ |
(void) ch_back_get(); /* Restore our position */ |
(void) ch_back_get(); |
(void) ch_back_get(); |
|
|
if (c == '\n' || c == '\r') |
if (c == '\n' || c == '\r') { |
{ |
|
/* |
/* |
* The "current" line was blank. |
* The "current" line was blank. |
* Skip over any preceding blank lines, |
* Skip over any preceding blank lines, |
* since we skipped them in forw_line(). |
* since we skipped them in forw_line(). |
*/ |
*/ |
while ((c = ch_back_get()) == '\n' || c == '\r') |
while ((c = ch_back_get()) == '\n' || c == '\r') |
if (ABORT_SIGS()) |
if (ABORT_SIGS()) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
if (c == EOI) |
if (c == EOI) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
(void) ch_forw_get(); |
(void) ch_forw_get(); |
} |
} |
|
|
/* |
/* |
* Scan backwards until we hit the beginning of the line. |
* Scan backwards until we hit the beginning of the line. |
*/ |
*/ |
for (;;) |
for (;;) { |
{ |
if (ABORT_SIGS()) { |
if (ABORT_SIGS()) |
|
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
c = ch_back_get(); |
c = ch_back_get(); |
if (c == '\n') |
if (c == '\n') { |
{ |
|
/* |
/* |
* This is the newline ending the previous line. |
* This is the newline ending the previous line. |
* We have hit the beginning of the line. |
* We have hit the beginning of the line. |
|
|
base_pos = ch_tell() + 1; |
base_pos = ch_tell() + 1; |
break; |
break; |
} |
} |
if (c == EOI) |
if (c == EOI) { |
{ |
|
/* |
/* |
* We have hit the beginning of the file. |
* We have hit the beginning of the file. |
* This must be the first line in the file. |
* This must be the first line in the file. |
|
|
* until we reach the curr_pos. |
* until we reach the curr_pos. |
* |
* |
* {{ This algorithm is pretty inefficient if the lines |
* {{ This algorithm is pretty inefficient if the lines |
* are much longer than the screen width, |
* are much longer than the screen width, |
* but I don't know of any better way. }} |
* but I don't know of any better way. }} |
*/ |
*/ |
new_pos = base_pos; |
new_pos = base_pos; |
if (ch_seek(new_pos)) |
if (ch_seek(new_pos)) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
endline = FALSE; |
endline = FALSE; |
prewind(); |
prewind(); |
plinenum(new_pos); |
plinenum(new_pos); |
loop: |
loop: |
begin_new_pos = new_pos; |
begin_new_pos = new_pos; |
(void) ch_seek(new_pos); |
(void) ch_seek(new_pos); |
|
|
do |
do { |
{ |
|
c = ch_forw_get(); |
c = ch_forw_get(); |
if (c == EOI || ABORT_SIGS()) |
if (c == EOI || ABORT_SIGS()) { |
{ |
|
null_line(); |
null_line(); |
return (NULL_POSITION); |
return (-1); |
} |
} |
new_pos++; |
new_pos++; |
if (c == '\n') |
if (c == '\n') { |
{ |
|
backchars = pflushmbc(); |
backchars = pflushmbc(); |
if (backchars > 0 && !chopline && hshift == 0) |
if (backchars > 0 && !chopline && hshift == 0) { |
{ |
|
backchars++; |
backchars++; |
goto shift; |
goto shift; |
} |
} |
|
|
break; |
break; |
} |
} |
backchars = pappend(c, ch_tell()-1); |
backchars = pappend(c, ch_tell()-1); |
if (backchars > 0) |
if (backchars > 0) { |
{ |
|
/* |
/* |
* Got a full printable line, but we haven't |
* Got a full printable line, but we haven't |
* reached our curr_pos yet. Discard the line |
* reached our curr_pos yet. Discard the line |
* and start a new one. |
* and start a new one. |
*/ |
*/ |
if (chopline || hshift > 0) |
if (chopline || hshift > 0) { |
{ |
|
endline = TRUE; |
endline = TRUE; |
quit_if_one_screen = FALSE; |
quit_if_one_screen = FALSE; |
break; |
break; |
} |
} |
shift: |
shift: |
pshift_all(); |
pshift_all(); |
while (backchars-- > 0) |
while (backchars-- > 0) { |
{ |
|
(void) ch_back_get(); |
(void) ch_back_get(); |
new_pos--; |
new_pos--; |
} |
} |
|
|
|
|
pdone(endline, 0); |
pdone(endline, 0); |
|
|
#if HILITE_SEARCH |
if (is_filtered(base_pos)) { |
if (is_filtered(base_pos)) |
|
{ |
|
/* |
/* |
* We don't want to display this line. |
* We don't want to display this line. |
* Get the previous line. |
* Get the previous line. |
|
|
goto get_back_line; |
goto get_back_line; |
} |
} |
|
|
if (status_col && curr_pos > 0 && is_hilited(base_pos, curr_pos-1, 1, NULL)) |
if (status_col && curr_pos > 0 && |
|
is_hilited(base_pos, curr_pos-1, 1, NULL)) |
set_status_col('*'); |
set_status_col('*'); |
#endif |
|
|
|
return (begin_new_pos); |
return (begin_new_pos); |
} |
} |
|
|
/* |
/* |
* Set attnpos. |
* Set attnpos. |
*/ |
*/ |
public void |
void |
set_attnpos(pos) |
set_attnpos(off_t pos) |
POSITION pos; |
|
{ |
{ |
int c; |
int c; |
|
|
if (pos != NULL_POSITION) |
if (pos != -1) { |
{ |
|
if (ch_seek(pos)) |
if (ch_seek(pos)) |
return; |
return; |
for (;;) |
for (;;) { |
{ |
|
c = ch_forw_get(); |
c = ch_forw_get(); |
if (c == EOI) |
if (c == EOI) |
return; |
return; |
|
|
} |
} |
} |
} |
start_attnpos = pos; |
start_attnpos = pos; |
for (;;) |
for (;;) { |
{ |
|
c = ch_forw_get(); |
c = ch_forw_get(); |
pos++; |
pos++; |
if (c == EOI || c == '\n' || c == '\r') |
if (c == EOI || c == '\n' || c == '\r') |