1a5f0fb15SPaul Saab /* 2*d713e089SXin LI * Copyright (C) 1984-2023 Mark Nudelman 3a5f0fb15SPaul Saab * 4a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 5a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 6a5f0fb15SPaul Saab * 796e55cc7SXin LI * For more information, see the README file. 8a5f0fb15SPaul Saab */ 9a5f0fb15SPaul Saab 10a5f0fb15SPaul Saab /* 11a5f0fb15SPaul Saab * High level routines dealing with getting lines of input 12a5f0fb15SPaul Saab * from the file being viewed. 13a5f0fb15SPaul Saab * 14a5f0fb15SPaul Saab * When we speak of "lines" here, we mean PRINTABLE lines; 15a5f0fb15SPaul Saab * lines processed with respect to the screen width. 16a5f0fb15SPaul Saab * We use the term "raw line" to refer to lines simply 17a5f0fb15SPaul Saab * delimited by newlines; not processed with respect to screen width. 18a5f0fb15SPaul Saab */ 19a5f0fb15SPaul Saab 20a5f0fb15SPaul Saab #include "less.h" 21a5f0fb15SPaul Saab 22a5f0fb15SPaul Saab extern int squeeze; 238ed69c6fSPaul Saab extern int hshift; 24a5f0fb15SPaul Saab extern int quit_if_one_screen; 25a5f0fb15SPaul Saab extern int sigs; 26a5f0fb15SPaul Saab extern int ignore_eoi; 276dcb072bSXin LI extern int status_col; 28*d713e089SXin LI extern int wordwrap; 29a5f0fb15SPaul Saab extern POSITION start_attnpos; 30a5f0fb15SPaul Saab extern POSITION end_attnpos; 31a5f0fb15SPaul Saab #if HILITE_SEARCH 32a5f0fb15SPaul Saab extern int hilite_search; 33a5f0fb15SPaul Saab extern int size_linebuf; 342235c7feSXin LI extern int show_attn; 35a5f0fb15SPaul Saab #endif 36a5f0fb15SPaul Saab 37a5f0fb15SPaul Saab /* 38*d713e089SXin LI * Set the status column. 39*d713e089SXin LI * base Position of first char in line. 40*d713e089SXin LI * disp First visible char. 41*d713e089SXin LI * Different than base_pos if line is shifted. 42*d713e089SXin LI * edisp Last visible char. 43*d713e089SXin LI * eol End of line. Normally the newline. 44*d713e089SXin LI * Different than edisp if line is chopped. 45*d713e089SXin LI */ 46*d713e089SXin LI static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos) 47*d713e089SXin LI { 48*d713e089SXin LI int hl_before = (chop_line() && disp_pos != NULL_POSITION) ? 49*d713e089SXin LI is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0; 50*d713e089SXin LI int hl_after = (chop_line()) ? 51*d713e089SXin LI is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0; 52*d713e089SXin LI int attr; 53*d713e089SXin LI char ch; 54*d713e089SXin LI 55*d713e089SXin LI if (hl_before && hl_after) 56*d713e089SXin LI { 57*d713e089SXin LI attr = hl_after; 58*d713e089SXin LI ch = '='; 59*d713e089SXin LI } else if (hl_before) 60*d713e089SXin LI { 61*d713e089SXin LI attr = hl_before; 62*d713e089SXin LI ch = '<'; 63*d713e089SXin LI } else if (hl_after) 64*d713e089SXin LI { 65*d713e089SXin LI attr = hl_after; 66*d713e089SXin LI ch = '>'; 67*d713e089SXin LI } else 68*d713e089SXin LI { 69*d713e089SXin LI attr = is_hilited_attr(base_pos, eol_pos, TRUE, NULL); 70*d713e089SXin LI ch = '*'; 71*d713e089SXin LI } 72*d713e089SXin LI if (attr) 73*d713e089SXin LI set_status_col(ch, attr); 74*d713e089SXin LI } 75*d713e089SXin LI 76*d713e089SXin LI /* 77a5f0fb15SPaul Saab * Get the next line. 78a5f0fb15SPaul Saab * A "current" position is passed and a "new" position is returned. 79a5f0fb15SPaul Saab * The current position is the position of the first character of 80a5f0fb15SPaul Saab * a line. The new position is the position of the first character 81a5f0fb15SPaul Saab * of the NEXT line. The line obtained is the line starting at curr_pos. 82a5f0fb15SPaul Saab */ 83*d713e089SXin LI public POSITION forw_line_seg(POSITION curr_pos, int skipeol, int rscroll, int nochop) 84a5f0fb15SPaul Saab { 856dcb072bSXin LI POSITION base_pos; 86a5f0fb15SPaul Saab POSITION new_pos; 87*d713e089SXin LI POSITION edisp_pos; 881ea31627SRobert Watson int c; 89a5f0fb15SPaul Saab int blankline; 90a5f0fb15SPaul Saab int endline; 91b2ea2440SXin LI int chopped; 926dcb072bSXin LI int backchars; 93*d713e089SXin LI POSITION wrap_pos; 94*d713e089SXin LI int skipped_leading; 95a5f0fb15SPaul Saab 967374caaaSXin LI get_forw_line: 97a5f0fb15SPaul Saab if (curr_pos == NULL_POSITION) 98a5f0fb15SPaul Saab { 99a5f0fb15SPaul Saab null_line(); 100a5f0fb15SPaul Saab return (NULL_POSITION); 101a5f0fb15SPaul Saab } 102a5f0fb15SPaul Saab #if HILITE_SEARCH 1037374caaaSXin LI if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) 104a15691bfSXin LI { 105a5f0fb15SPaul Saab /* 106a5f0fb15SPaul Saab * If we are ignoring EOI (command F), only prepare 107a5f0fb15SPaul Saab * one line ahead, to avoid getting stuck waiting for 108a5f0fb15SPaul Saab * slow data without displaying the data we already have. 109a5f0fb15SPaul Saab * If we're not ignoring EOI, we *could* do the same, but 110a5f0fb15SPaul Saab * for efficiency we prepare several lines ahead at once. 111a5f0fb15SPaul Saab */ 112a5f0fb15SPaul Saab prep_hilite(curr_pos, curr_pos + 3*size_linebuf, 113a5f0fb15SPaul Saab ignore_eoi ? 1 : -1); 114a15691bfSXin LI curr_pos = next_unfiltered(curr_pos); 115a15691bfSXin LI } 116a5f0fb15SPaul Saab #endif 117a5f0fb15SPaul Saab if (ch_seek(curr_pos)) 118a5f0fb15SPaul Saab { 119a5f0fb15SPaul Saab null_line(); 120a5f0fb15SPaul Saab return (NULL_POSITION); 121a5f0fb15SPaul Saab } 122a5f0fb15SPaul Saab 1237374caaaSXin LI /* 1247374caaaSXin LI * Step back to the beginning of the line. 1257374caaaSXin LI */ 1266dcb072bSXin LI base_pos = curr_pos; 1276dcb072bSXin LI for (;;) 1286dcb072bSXin LI { 1296dcb072bSXin LI if (ABORT_SIGS()) 1306dcb072bSXin LI { 1316dcb072bSXin LI null_line(); 1326dcb072bSXin LI return (NULL_POSITION); 1336dcb072bSXin LI } 1346dcb072bSXin LI c = ch_back_get(); 1356dcb072bSXin LI if (c == EOI) 1366dcb072bSXin LI break; 1376dcb072bSXin LI if (c == '\n') 1386dcb072bSXin LI { 1396dcb072bSXin LI (void) ch_forw_get(); 1406dcb072bSXin LI break; 1416dcb072bSXin LI } 1426dcb072bSXin LI --base_pos; 1436dcb072bSXin LI } 1446dcb072bSXin LI 1457374caaaSXin LI /* 1467374caaaSXin LI * Read forward again to the position we should start at. 1477374caaaSXin LI */ 148a5f0fb15SPaul Saab prewind(); 1492235c7feSXin LI plinestart(base_pos); 1506dcb072bSXin LI (void) ch_seek(base_pos); 1517374caaaSXin LI new_pos = base_pos; 1527374caaaSXin LI while (new_pos < curr_pos) 1536dcb072bSXin LI { 1546dcb072bSXin LI if (ABORT_SIGS()) 1556dcb072bSXin LI { 1566dcb072bSXin LI null_line(); 1576dcb072bSXin LI return (NULL_POSITION); 1586dcb072bSXin LI } 1596dcb072bSXin LI c = ch_forw_get(); 1607374caaaSXin LI backchars = pappend(c, new_pos); 1617374caaaSXin LI new_pos++; 1626dcb072bSXin LI if (backchars > 0) 1636dcb072bSXin LI { 1646dcb072bSXin LI pshift_all(); 165*d713e089SXin LI if (wordwrap && (c == ' ' || c == '\t')) 166*d713e089SXin LI { 167*d713e089SXin LI do 168*d713e089SXin LI { 169*d713e089SXin LI new_pos++; 170*d713e089SXin LI c = ch_forw_get(); 171*d713e089SXin LI } while (c == ' ' || c == '\t'); 172*d713e089SXin LI backchars = 1; 173*d713e089SXin LI } 1747374caaaSXin LI new_pos -= backchars; 1756dcb072bSXin LI while (--backchars >= 0) 1766dcb072bSXin LI (void) ch_back_get(); 1776dcb072bSXin LI } 1786dcb072bSXin LI } 1796dcb072bSXin LI (void) pflushmbc(); 1806dcb072bSXin LI pshift_all(); 181a5f0fb15SPaul Saab 1827374caaaSXin LI /* 1837374caaaSXin LI * Read the first character to display. 1847374caaaSXin LI */ 185a5f0fb15SPaul Saab c = ch_forw_get(); 186a5f0fb15SPaul Saab if (c == EOI) 187a5f0fb15SPaul Saab { 188a5f0fb15SPaul Saab null_line(); 189a5f0fb15SPaul Saab return (NULL_POSITION); 190a5f0fb15SPaul Saab } 191a5f0fb15SPaul Saab blankline = (c == '\n' || c == '\r'); 192*d713e089SXin LI wrap_pos = NULL_POSITION; 193*d713e089SXin LI skipped_leading = FALSE; 194a5f0fb15SPaul Saab 1957374caaaSXin LI /* 1967374caaaSXin LI * Read each character in the line and append to the line buffer. 1977374caaaSXin LI */ 198b2ea2440SXin LI chopped = FALSE; 199a5f0fb15SPaul Saab for (;;) 200a5f0fb15SPaul Saab { 201a5f0fb15SPaul Saab if (ABORT_SIGS()) 202a5f0fb15SPaul Saab { 203a5f0fb15SPaul Saab null_line(); 204a5f0fb15SPaul Saab return (NULL_POSITION); 205a5f0fb15SPaul Saab } 206a5f0fb15SPaul Saab if (c == '\n' || c == EOI) 207a5f0fb15SPaul Saab { 208a5f0fb15SPaul Saab /* 209a5f0fb15SPaul Saab * End of the line. 210a5f0fb15SPaul Saab */ 2116dcb072bSXin LI backchars = pflushmbc(); 212a5f0fb15SPaul Saab new_pos = ch_tell(); 21395270f73SXin LI if (backchars > 0 && (nochop || !chop_line()) && hshift == 0) 2146dcb072bSXin LI { 2156dcb072bSXin LI new_pos -= backchars + 1; 2166dcb072bSXin LI endline = FALSE; 2176dcb072bSXin LI } else 218a5f0fb15SPaul Saab endline = TRUE; 219*d713e089SXin LI edisp_pos = new_pos; 220a5f0fb15SPaul Saab break; 221a5f0fb15SPaul Saab } 2226dcb072bSXin LI if (c != '\r') 2236dcb072bSXin LI blankline = 0; 224a5f0fb15SPaul Saab 225a5f0fb15SPaul Saab /* 226a5f0fb15SPaul Saab * Append the char to the line and get the next char. 227a5f0fb15SPaul Saab */ 2286dcb072bSXin LI backchars = pappend(c, ch_tell()-1); 2296dcb072bSXin LI if (backchars > 0) 230a5f0fb15SPaul Saab { 231a5f0fb15SPaul Saab /* 232a5f0fb15SPaul Saab * The char won't fit in the line; the line 233a5f0fb15SPaul Saab * is too long to print in the screen width. 234a5f0fb15SPaul Saab * End the line here. 235a5f0fb15SPaul Saab */ 23695270f73SXin LI if (skipeol) 237a5f0fb15SPaul Saab { 2382235c7feSXin LI /* Read to end of line. */ 239*d713e089SXin LI edisp_pos = ch_tell(); 240a5f0fb15SPaul Saab do 241a5f0fb15SPaul Saab { 24233096f16SXin LI if (ABORT_SIGS()) 24333096f16SXin LI { 24433096f16SXin LI null_line(); 24533096f16SXin LI return (NULL_POSITION); 24633096f16SXin LI } 247a5f0fb15SPaul Saab c = ch_forw_get(); 248a5f0fb15SPaul Saab } while (c != '\n' && c != EOI); 249a5f0fb15SPaul Saab new_pos = ch_tell(); 250a5f0fb15SPaul Saab endline = TRUE; 251a5f0fb15SPaul Saab quit_if_one_screen = FALSE; 252b2ea2440SXin LI chopped = TRUE; 253a5f0fb15SPaul Saab } else 254a5f0fb15SPaul Saab { 255*d713e089SXin LI if (!wordwrap) 2566dcb072bSXin LI new_pos = ch_tell() - backchars; 257*d713e089SXin LI else 258*d713e089SXin LI { 259*d713e089SXin LI /* 260*d713e089SXin LI * We're word-wrapping, so go back to the last space. 261*d713e089SXin LI * However, if it's the space itself that couldn't fit, 262*d713e089SXin LI * simply ignore it and any subsequent spaces. 263*d713e089SXin LI */ 264*d713e089SXin LI if (c == ' ' || c == '\t') 265*d713e089SXin LI { 266*d713e089SXin LI do 267*d713e089SXin LI { 268*d713e089SXin LI new_pos = ch_tell(); 269*d713e089SXin LI c = ch_forw_get(); 270*d713e089SXin LI } while (c == ' ' || c == '\t'); 271*d713e089SXin LI if (c == '\r') 272*d713e089SXin LI c = ch_forw_get(); 273*d713e089SXin LI if (c == '\n') 274*d713e089SXin LI new_pos = ch_tell(); 275*d713e089SXin LI } else if (wrap_pos == NULL_POSITION) 276*d713e089SXin LI new_pos = ch_tell() - backchars; 277*d713e089SXin LI else 278*d713e089SXin LI { 279*d713e089SXin LI new_pos = wrap_pos; 280*d713e089SXin LI loadc(); 281*d713e089SXin LI } 282*d713e089SXin LI } 283a5f0fb15SPaul Saab endline = FALSE; 284a5f0fb15SPaul Saab } 285a5f0fb15SPaul Saab break; 286a5f0fb15SPaul Saab } 287*d713e089SXin LI if (wordwrap) 288*d713e089SXin LI { 289*d713e089SXin LI if (c == ' ' || c == '\t') 290*d713e089SXin LI { 291*d713e089SXin LI if (skipped_leading) 292*d713e089SXin LI { 293*d713e089SXin LI wrap_pos = ch_tell(); 294*d713e089SXin LI savec(); 295*d713e089SXin LI } 296*d713e089SXin LI } else 297*d713e089SXin LI skipped_leading = TRUE; 298*d713e089SXin LI } 299a5f0fb15SPaul Saab c = ch_forw_get(); 300a5f0fb15SPaul Saab } 3017374caaaSXin LI 3022235c7feSXin LI #if HILITE_SEARCH 3032235c7feSXin LI if (blankline && show_attn) 3042235c7feSXin LI { 3052235c7feSXin LI /* Add spurious space to carry possible attn hilite. */ 3062235c7feSXin LI pappend(' ', ch_tell()-1); 3072235c7feSXin LI } 3082235c7feSXin LI #endif 30995270f73SXin LI pdone(endline, rscroll && chopped, 1); 3107374caaaSXin LI 3117374caaaSXin LI #if HILITE_SEARCH 3127374caaaSXin LI if (is_filtered(base_pos)) 3137374caaaSXin LI { 3147374caaaSXin LI /* 3157374caaaSXin LI * We don't want to display this line. 3167374caaaSXin LI * Get the next line. 3177374caaaSXin LI */ 3187374caaaSXin LI curr_pos = new_pos; 3197374caaaSXin LI goto get_forw_line; 3207374caaaSXin LI } 3212235c7feSXin LI if (status_col) 322*d713e089SXin LI init_status_col(base_pos, line_position(), edisp_pos, new_pos); 3237374caaaSXin LI #endif 324a5f0fb15SPaul Saab 325a5f0fb15SPaul Saab if (squeeze && blankline) 326a5f0fb15SPaul Saab { 327a5f0fb15SPaul Saab /* 328a5f0fb15SPaul Saab * This line is blank. 329a5f0fb15SPaul Saab * Skip down to the last contiguous blank line 330a5f0fb15SPaul Saab * and pretend it is the one which we are returning. 331a5f0fb15SPaul Saab */ 332a5f0fb15SPaul Saab while ((c = ch_forw_get()) == '\n' || c == '\r') 333a5f0fb15SPaul Saab if (ABORT_SIGS()) 334a5f0fb15SPaul Saab { 335a5f0fb15SPaul Saab null_line(); 336a5f0fb15SPaul Saab return (NULL_POSITION); 337a5f0fb15SPaul Saab } 338a5f0fb15SPaul Saab if (c != EOI) 339a5f0fb15SPaul Saab (void) ch_back_get(); 340a5f0fb15SPaul Saab new_pos = ch_tell(); 341a5f0fb15SPaul Saab } 342a5f0fb15SPaul Saab 343a5f0fb15SPaul Saab return (new_pos); 344a5f0fb15SPaul Saab } 345a5f0fb15SPaul Saab 346*d713e089SXin LI public POSITION forw_line(POSITION curr_pos) 3472235c7feSXin LI { 34895270f73SXin LI 34995270f73SXin LI return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE); 3502235c7feSXin LI } 3512235c7feSXin LI 352a5f0fb15SPaul Saab /* 353a5f0fb15SPaul Saab * Get the previous line. 354a5f0fb15SPaul Saab * A "current" position is passed and a "new" position is returned. 355a5f0fb15SPaul Saab * The current position is the position of the first character of 356a5f0fb15SPaul Saab * a line. The new position is the position of the first character 357a5f0fb15SPaul Saab * of the PREVIOUS line. The line obtained is the one starting at new_pos. 358a5f0fb15SPaul Saab */ 359*d713e089SXin LI public POSITION back_line(POSITION curr_pos) 360a5f0fb15SPaul Saab { 361*d713e089SXin LI POSITION base_pos; 362*d713e089SXin LI POSITION new_pos; 363*d713e089SXin LI POSITION edisp_pos; 364*d713e089SXin LI POSITION begin_new_pos; 365a5f0fb15SPaul Saab int c; 366a5f0fb15SPaul Saab int endline; 367b2ea2440SXin LI int chopped; 3686dcb072bSXin LI int backchars; 369*d713e089SXin LI POSITION wrap_pos; 370*d713e089SXin LI int skipped_leading; 371a5f0fb15SPaul Saab 3727374caaaSXin LI get_back_line: 373a5f0fb15SPaul Saab if (curr_pos == NULL_POSITION || curr_pos <= ch_zero()) 374a5f0fb15SPaul Saab { 375a5f0fb15SPaul Saab null_line(); 376a5f0fb15SPaul Saab return (NULL_POSITION); 377a5f0fb15SPaul Saab } 378a5f0fb15SPaul Saab #if HILITE_SEARCH 3797374caaaSXin LI if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) 380a5f0fb15SPaul Saab prep_hilite((curr_pos < 3*size_linebuf) ? 381a5f0fb15SPaul Saab 0 : curr_pos - 3*size_linebuf, curr_pos, -1); 382a5f0fb15SPaul Saab #endif 383a5f0fb15SPaul Saab if (ch_seek(curr_pos-1)) 384a5f0fb15SPaul Saab { 385a5f0fb15SPaul Saab null_line(); 386a5f0fb15SPaul Saab return (NULL_POSITION); 387a5f0fb15SPaul Saab } 388a5f0fb15SPaul Saab 389a5f0fb15SPaul Saab if (squeeze) 390a5f0fb15SPaul Saab { 391a5f0fb15SPaul Saab /* 392a5f0fb15SPaul Saab * Find out if the "current" line was blank. 393a5f0fb15SPaul Saab */ 394a5f0fb15SPaul Saab (void) ch_forw_get(); /* Skip the newline */ 395a5f0fb15SPaul Saab c = ch_forw_get(); /* First char of "current" line */ 396a5f0fb15SPaul Saab (void) ch_back_get(); /* Restore our position */ 397a5f0fb15SPaul Saab (void) ch_back_get(); 398a5f0fb15SPaul Saab 399a5f0fb15SPaul Saab if (c == '\n' || c == '\r') 400a5f0fb15SPaul Saab { 401a5f0fb15SPaul Saab /* 402a5f0fb15SPaul Saab * The "current" line was blank. 403a5f0fb15SPaul Saab * Skip over any preceding blank lines, 404a5f0fb15SPaul Saab * since we skipped them in forw_line(). 405a5f0fb15SPaul Saab */ 406a5f0fb15SPaul Saab while ((c = ch_back_get()) == '\n' || c == '\r') 407a5f0fb15SPaul Saab if (ABORT_SIGS()) 408a5f0fb15SPaul Saab { 409a5f0fb15SPaul Saab null_line(); 410a5f0fb15SPaul Saab return (NULL_POSITION); 411a5f0fb15SPaul Saab } 412a5f0fb15SPaul Saab if (c == EOI) 413a5f0fb15SPaul Saab { 414a5f0fb15SPaul Saab null_line(); 415a5f0fb15SPaul Saab return (NULL_POSITION); 416a5f0fb15SPaul Saab } 417a5f0fb15SPaul Saab (void) ch_forw_get(); 418a5f0fb15SPaul Saab } 419a5f0fb15SPaul Saab } 420a5f0fb15SPaul Saab 421a5f0fb15SPaul Saab /* 422a5f0fb15SPaul Saab * Scan backwards until we hit the beginning of the line. 423a5f0fb15SPaul Saab */ 424a5f0fb15SPaul Saab for (;;) 425a5f0fb15SPaul Saab { 426a5f0fb15SPaul Saab if (ABORT_SIGS()) 427a5f0fb15SPaul Saab { 428a5f0fb15SPaul Saab null_line(); 429a5f0fb15SPaul Saab return (NULL_POSITION); 430a5f0fb15SPaul Saab } 431a5f0fb15SPaul Saab c = ch_back_get(); 432a5f0fb15SPaul Saab if (c == '\n') 433a5f0fb15SPaul Saab { 434a5f0fb15SPaul Saab /* 435a5f0fb15SPaul Saab * This is the newline ending the previous line. 436a5f0fb15SPaul Saab * We have hit the beginning of the line. 437a5f0fb15SPaul Saab */ 4387374caaaSXin LI base_pos = ch_tell() + 1; 439a5f0fb15SPaul Saab break; 440a5f0fb15SPaul Saab } 441a5f0fb15SPaul Saab if (c == EOI) 442a5f0fb15SPaul Saab { 443a5f0fb15SPaul Saab /* 444a5f0fb15SPaul Saab * We have hit the beginning of the file. 445a5f0fb15SPaul Saab * This must be the first line in the file. 446a5f0fb15SPaul Saab * This must, of course, be the beginning of the line. 447a5f0fb15SPaul Saab */ 4487374caaaSXin LI base_pos = ch_tell(); 449a5f0fb15SPaul Saab break; 450a5f0fb15SPaul Saab } 451a5f0fb15SPaul Saab } 452a5f0fb15SPaul Saab 453a5f0fb15SPaul Saab /* 454a5f0fb15SPaul Saab * Now scan forwards from the beginning of this line. 455a5f0fb15SPaul Saab * We keep discarding "printable lines" (based on screen width) 456a5f0fb15SPaul Saab * until we reach the curr_pos. 457a5f0fb15SPaul Saab * 458a5f0fb15SPaul Saab * {{ This algorithm is pretty inefficient if the lines 459a5f0fb15SPaul Saab * are much longer than the screen width, 460a5f0fb15SPaul Saab * but I don't know of any better way. }} 461a5f0fb15SPaul Saab */ 4627374caaaSXin LI new_pos = base_pos; 463a5f0fb15SPaul Saab if (ch_seek(new_pos)) 464a5f0fb15SPaul Saab { 465a5f0fb15SPaul Saab null_line(); 466a5f0fb15SPaul Saab return (NULL_POSITION); 467a5f0fb15SPaul Saab } 468a5f0fb15SPaul Saab endline = FALSE; 469a5f0fb15SPaul Saab prewind(); 4702235c7feSXin LI plinestart(new_pos); 4716dcb072bSXin LI loop: 472*d713e089SXin LI wrap_pos = NULL_POSITION; 473*d713e089SXin LI skipped_leading = FALSE; 4746dcb072bSXin LI begin_new_pos = new_pos; 475a5f0fb15SPaul Saab (void) ch_seek(new_pos); 476b2ea2440SXin LI chopped = FALSE; 477a5f0fb15SPaul Saab 478*d713e089SXin LI for (;;) 479a5f0fb15SPaul Saab { 480a5f0fb15SPaul Saab c = ch_forw_get(); 481a5f0fb15SPaul Saab if (c == EOI || ABORT_SIGS()) 482a5f0fb15SPaul Saab { 483a5f0fb15SPaul Saab null_line(); 484a5f0fb15SPaul Saab return (NULL_POSITION); 485a5f0fb15SPaul Saab } 486a5f0fb15SPaul Saab new_pos++; 487a5f0fb15SPaul Saab if (c == '\n') 488a5f0fb15SPaul Saab { 4896dcb072bSXin LI backchars = pflushmbc(); 49095270f73SXin LI if (backchars > 0 && !chop_line() && hshift == 0) 4916dcb072bSXin LI { 4926dcb072bSXin LI backchars++; 4936dcb072bSXin LI goto shift; 4946dcb072bSXin LI } 495a5f0fb15SPaul Saab endline = TRUE; 496*d713e089SXin LI edisp_pos = new_pos; 497a5f0fb15SPaul Saab break; 498a5f0fb15SPaul Saab } 4996dcb072bSXin LI backchars = pappend(c, ch_tell()-1); 5006dcb072bSXin LI if (backchars > 0) 501a5f0fb15SPaul Saab { 502a5f0fb15SPaul Saab /* 503a5f0fb15SPaul Saab * Got a full printable line, but we haven't 504a5f0fb15SPaul Saab * reached our curr_pos yet. Discard the line 505a5f0fb15SPaul Saab * and start a new one. 506a5f0fb15SPaul Saab */ 50795270f73SXin LI if (chop_line() || hshift > 0) 508a5f0fb15SPaul Saab { 509a5f0fb15SPaul Saab endline = TRUE; 510b2ea2440SXin LI chopped = TRUE; 511a5f0fb15SPaul Saab quit_if_one_screen = FALSE; 512*d713e089SXin LI edisp_pos = new_pos; 513a5f0fb15SPaul Saab break; 514a5f0fb15SPaul Saab } 5156dcb072bSXin LI shift: 516*d713e089SXin LI if (!wordwrap) 5176dcb072bSXin LI { 518*d713e089SXin LI pshift_all(); 519*d713e089SXin LI new_pos -= backchars; 520*d713e089SXin LI } else 521*d713e089SXin LI { 522*d713e089SXin LI if (c == ' ' || c == '\t') 523*d713e089SXin LI { 524*d713e089SXin LI for (;;) 525*d713e089SXin LI { 526*d713e089SXin LI c = ch_forw_get(); 527*d713e089SXin LI if (c == ' ' || c == '\t') 528*d713e089SXin LI new_pos++; 529*d713e089SXin LI else 530*d713e089SXin LI { 531*d713e089SXin LI if (c == '\r') 532*d713e089SXin LI { 533*d713e089SXin LI c = ch_forw_get(); 534*d713e089SXin LI if (c == '\n') 535*d713e089SXin LI new_pos++; 536*d713e089SXin LI } 537*d713e089SXin LI if (c == '\n') 538*d713e089SXin LI new_pos++; 539*d713e089SXin LI break; 540*d713e089SXin LI } 541*d713e089SXin LI } 542*d713e089SXin LI if (new_pos >= curr_pos) 543*d713e089SXin LI break; 544*d713e089SXin LI pshift_all(); 545*d713e089SXin LI } else 546*d713e089SXin LI { 547*d713e089SXin LI pshift_all(); 548*d713e089SXin LI if (wrap_pos == NULL_POSITION) 549*d713e089SXin LI new_pos -= backchars; 550*d713e089SXin LI else 551*d713e089SXin LI new_pos = wrap_pos; 552*d713e089SXin LI } 5536dcb072bSXin LI } 554a5f0fb15SPaul Saab goto loop; 555a5f0fb15SPaul Saab } 556*d713e089SXin LI if (wordwrap) 557*d713e089SXin LI { 558*d713e089SXin LI if (c == ' ' || c == '\t') 559*d713e089SXin LI { 560*d713e089SXin LI if (skipped_leading) 561*d713e089SXin LI wrap_pos = new_pos; 562*d713e089SXin LI } else 563*d713e089SXin LI skipped_leading = TRUE; 564*d713e089SXin LI } 565*d713e089SXin LI if (new_pos >= curr_pos) 566*d713e089SXin LI { 567*d713e089SXin LI edisp_pos = new_pos; 568*d713e089SXin LI break; 569*d713e089SXin LI } 570*d713e089SXin LI } 571a5f0fb15SPaul Saab 572b2ea2440SXin LI pdone(endline, chopped, 0); 5737374caaaSXin LI 5747374caaaSXin LI #if HILITE_SEARCH 5757374caaaSXin LI if (is_filtered(base_pos)) 5767374caaaSXin LI { 5777374caaaSXin LI /* 5787374caaaSXin LI * We don't want to display this line. 5797374caaaSXin LI * Get the previous line. 5807374caaaSXin LI */ 5817374caaaSXin LI curr_pos = begin_new_pos; 5827374caaaSXin LI goto get_back_line; 5837374caaaSXin LI } 584*d713e089SXin LI if (status_col) 585*d713e089SXin LI init_status_col(base_pos, line_position(), edisp_pos, new_pos); 5867374caaaSXin LI #endif 587a5f0fb15SPaul Saab 588a5f0fb15SPaul Saab return (begin_new_pos); 589a5f0fb15SPaul Saab } 590a5f0fb15SPaul Saab 591a5f0fb15SPaul Saab /* 592a5f0fb15SPaul Saab * Set attnpos. 593a5f0fb15SPaul Saab */ 594*d713e089SXin LI public void set_attnpos(POSITION pos) 595a5f0fb15SPaul Saab { 596a5f0fb15SPaul Saab int c; 597a5f0fb15SPaul Saab 598a5f0fb15SPaul Saab if (pos != NULL_POSITION) 599a5f0fb15SPaul Saab { 600a5f0fb15SPaul Saab if (ch_seek(pos)) 601a5f0fb15SPaul Saab return; 602a5f0fb15SPaul Saab for (;;) 603a5f0fb15SPaul Saab { 604a5f0fb15SPaul Saab c = ch_forw_get(); 605a5f0fb15SPaul Saab if (c == EOI) 606a5f0fb15SPaul Saab break; 607a15691bfSXin LI if (c == '\n' || c == '\r') 608a15691bfSXin LI { 609a15691bfSXin LI (void) ch_back_get(); 610a15691bfSXin LI break; 611a15691bfSXin LI } 612a5f0fb15SPaul Saab pos++; 613a5f0fb15SPaul Saab } 614a15691bfSXin LI end_attnpos = pos; 615a15691bfSXin LI for (;;) 616a15691bfSXin LI { 617a15691bfSXin LI c = ch_back_get(); 618a15691bfSXin LI if (c == EOI || c == '\n' || c == '\r') 619a15691bfSXin LI break; 620a15691bfSXin LI pos--; 621a15691bfSXin LI } 622a5f0fb15SPaul Saab } 623a5f0fb15SPaul Saab start_attnpos = pos; 624a5f0fb15SPaul Saab } 625