1a5f0fb15SPaul Saab /* 2*c77c4889SXin LI * Copyright (C) 1984-2024 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 ignore_eoi; 266dcb072bSXin LI extern int status_col; 27d713e089SXin LI extern int wordwrap; 28a5f0fb15SPaul Saab extern POSITION start_attnpos; 29a5f0fb15SPaul Saab extern POSITION end_attnpos; 30a5f0fb15SPaul Saab #if HILITE_SEARCH 31a5f0fb15SPaul Saab extern int hilite_search; 32*c77c4889SXin LI extern size_t size_linebuf; 332235c7feSXin LI extern int show_attn; 34a5f0fb15SPaul Saab #endif 35a5f0fb15SPaul Saab 36a5f0fb15SPaul Saab /* 37d713e089SXin LI * Set the status column. 38d713e089SXin LI * base Position of first char in line. 39d713e089SXin LI * disp First visible char. 40d713e089SXin LI * Different than base_pos if line is shifted. 41d713e089SXin LI * edisp Last visible char. 42d713e089SXin LI * eol End of line. Normally the newline. 43d713e089SXin LI * Different than edisp if line is chopped. 44d713e089SXin LI */ 45d713e089SXin LI static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp_pos, POSITION eol_pos) 46d713e089SXin LI { 47d713e089SXin LI int hl_before = (chop_line() && disp_pos != NULL_POSITION) ? 48d713e089SXin LI is_hilited_attr(base_pos, disp_pos, TRUE, NULL) : 0; 49*c77c4889SXin LI int hl_after = (chop_line() && edisp_pos != NULL_POSITION) ? 50d713e089SXin LI is_hilited_attr(edisp_pos, eol_pos, TRUE, NULL) : 0; 51d713e089SXin LI int attr; 52d713e089SXin LI char ch; 53d713e089SXin LI 54d713e089SXin LI if (hl_before && hl_after) 55d713e089SXin LI { 56d713e089SXin LI attr = hl_after; 57d713e089SXin LI ch = '='; 58d713e089SXin LI } else if (hl_before) 59d713e089SXin LI { 60d713e089SXin LI attr = hl_before; 61d713e089SXin LI ch = '<'; 62d713e089SXin LI } else if (hl_after) 63d713e089SXin LI { 64d713e089SXin LI attr = hl_after; 65d713e089SXin LI ch = '>'; 66*c77c4889SXin LI } else if (disp_pos != NULL_POSITION) 67*c77c4889SXin LI { 68*c77c4889SXin LI attr = is_hilited_attr(disp_pos, edisp_pos, TRUE, NULL); 69*c77c4889SXin LI ch = '*'; 70d713e089SXin LI } else 71d713e089SXin LI { 72*c77c4889SXin LI attr = 0; 73d713e089SXin LI } 74d713e089SXin LI if (attr) 75d713e089SXin LI set_status_col(ch, attr); 76d713e089SXin LI } 77d713e089SXin LI 78d713e089SXin LI /* 79a5f0fb15SPaul Saab * Get the next line. 80a5f0fb15SPaul Saab * A "current" position is passed and a "new" position is returned. 81a5f0fb15SPaul Saab * The current position is the position of the first character of 82a5f0fb15SPaul Saab * a line. The new position is the position of the first character 83a5f0fb15SPaul Saab * of the NEXT line. The line obtained is the line starting at curr_pos. 84a5f0fb15SPaul Saab */ 85*c77c4889SXin LI public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop) 86a5f0fb15SPaul Saab { 876dcb072bSXin LI POSITION base_pos; 88a5f0fb15SPaul Saab POSITION new_pos; 89d713e089SXin LI POSITION edisp_pos; 901ea31627SRobert Watson int c; 91*c77c4889SXin LI lbool blankline; 92*c77c4889SXin LI lbool endline; 93*c77c4889SXin LI lbool chopped; 946dcb072bSXin LI int backchars; 95d713e089SXin LI POSITION wrap_pos; 96*c77c4889SXin LI lbool skipped_leading; 97a5f0fb15SPaul Saab 987374caaaSXin LI get_forw_line: 99a5f0fb15SPaul Saab if (curr_pos == NULL_POSITION) 100a5f0fb15SPaul Saab { 101a5f0fb15SPaul Saab null_line(); 102a5f0fb15SPaul Saab return (NULL_POSITION); 103a5f0fb15SPaul Saab } 104a5f0fb15SPaul Saab #if HILITE_SEARCH 1057374caaaSXin LI if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) 106a15691bfSXin LI { 107a5f0fb15SPaul Saab /* 108a5f0fb15SPaul Saab * If we are ignoring EOI (command F), only prepare 109a5f0fb15SPaul Saab * one line ahead, to avoid getting stuck waiting for 110a5f0fb15SPaul Saab * slow data without displaying the data we already have. 111a5f0fb15SPaul Saab * If we're not ignoring EOI, we *could* do the same, but 112a5f0fb15SPaul Saab * for efficiency we prepare several lines ahead at once. 113a5f0fb15SPaul Saab */ 114*c77c4889SXin LI prep_hilite(curr_pos, curr_pos + (POSITION) (3*size_linebuf), ignore_eoi ? 1 : -1); 115a15691bfSXin LI curr_pos = next_unfiltered(curr_pos); 116a15691bfSXin LI } 117a5f0fb15SPaul Saab #endif 118a5f0fb15SPaul Saab if (ch_seek(curr_pos)) 119a5f0fb15SPaul Saab { 120a5f0fb15SPaul Saab null_line(); 121a5f0fb15SPaul Saab return (NULL_POSITION); 122a5f0fb15SPaul Saab } 123a5f0fb15SPaul Saab 1247374caaaSXin LI /* 1257374caaaSXin LI * Step back to the beginning of the line. 1267374caaaSXin LI */ 1276dcb072bSXin LI base_pos = curr_pos; 1286dcb072bSXin LI for (;;) 1296dcb072bSXin LI { 1306dcb072bSXin LI c = ch_back_get(); 1316dcb072bSXin LI if (c == EOI) 1326dcb072bSXin LI break; 1336dcb072bSXin LI if (c == '\n') 1346dcb072bSXin LI { 1356dcb072bSXin LI (void) ch_forw_get(); 1366dcb072bSXin LI break; 1376dcb072bSXin LI } 1386dcb072bSXin LI --base_pos; 1396dcb072bSXin LI } 1406dcb072bSXin LI 1417374caaaSXin LI /* 1427374caaaSXin LI * Read forward again to the position we should start at. 1437374caaaSXin LI */ 144a5f0fb15SPaul Saab prewind(); 1452235c7feSXin LI plinestart(base_pos); 1466dcb072bSXin LI (void) ch_seek(base_pos); 1477374caaaSXin LI new_pos = base_pos; 1487374caaaSXin LI while (new_pos < curr_pos) 1496dcb072bSXin LI { 150*c77c4889SXin LI c = ch_forw_get(); 151*c77c4889SXin LI if (c == EOI) 1526dcb072bSXin LI { 1536dcb072bSXin LI null_line(); 1546dcb072bSXin LI return (NULL_POSITION); 1556dcb072bSXin LI } 156*c77c4889SXin LI backchars = pappend((char) c, new_pos); 1577374caaaSXin LI new_pos++; 1586dcb072bSXin LI if (backchars > 0) 1596dcb072bSXin LI { 1606dcb072bSXin LI pshift_all(); 161d713e089SXin LI if (wordwrap && (c == ' ' || c == '\t')) 162d713e089SXin LI { 163d713e089SXin LI do 164d713e089SXin LI { 165d713e089SXin LI new_pos++; 166*c77c4889SXin LI c = ch_forw_get(); /* {{ what if c == EOI? }} */ 167d713e089SXin LI } while (c == ' ' || c == '\t'); 168d713e089SXin LI backchars = 1; 169d713e089SXin LI } 1707374caaaSXin LI new_pos -= backchars; 1716dcb072bSXin LI while (--backchars >= 0) 1726dcb072bSXin LI (void) ch_back_get(); 1736dcb072bSXin LI } 1746dcb072bSXin LI } 1756dcb072bSXin LI (void) pflushmbc(); 1766dcb072bSXin LI pshift_all(); 177a5f0fb15SPaul Saab 1787374caaaSXin LI /* 1797374caaaSXin LI * Read the first character to display. 1807374caaaSXin LI */ 181a5f0fb15SPaul Saab c = ch_forw_get(); 182a5f0fb15SPaul Saab if (c == EOI) 183a5f0fb15SPaul Saab { 184a5f0fb15SPaul Saab null_line(); 185a5f0fb15SPaul Saab return (NULL_POSITION); 186a5f0fb15SPaul Saab } 187a5f0fb15SPaul Saab blankline = (c == '\n' || c == '\r'); 188d713e089SXin LI wrap_pos = NULL_POSITION; 189d713e089SXin LI skipped_leading = FALSE; 190a5f0fb15SPaul Saab 1917374caaaSXin LI /* 1927374caaaSXin LI * Read each character in the line and append to the line buffer. 1937374caaaSXin LI */ 194b2ea2440SXin LI chopped = FALSE; 195a5f0fb15SPaul Saab for (;;) 196a5f0fb15SPaul Saab { 197a5f0fb15SPaul Saab if (c == '\n' || c == EOI) 198a5f0fb15SPaul Saab { 199a5f0fb15SPaul Saab /* 200a5f0fb15SPaul Saab * End of the line. 201a5f0fb15SPaul Saab */ 2026dcb072bSXin LI backchars = pflushmbc(); 203a5f0fb15SPaul Saab new_pos = ch_tell(); 20495270f73SXin LI if (backchars > 0 && (nochop || !chop_line()) && hshift == 0) 2056dcb072bSXin LI { 2066dcb072bSXin LI new_pos -= backchars + 1; 2076dcb072bSXin LI endline = FALSE; 2086dcb072bSXin LI } else 209a5f0fb15SPaul Saab endline = TRUE; 210d713e089SXin LI edisp_pos = new_pos; 211a5f0fb15SPaul Saab break; 212a5f0fb15SPaul Saab } 2136dcb072bSXin LI if (c != '\r') 214*c77c4889SXin LI blankline = FALSE; 215a5f0fb15SPaul Saab 216a5f0fb15SPaul Saab /* 217a5f0fb15SPaul Saab * Append the char to the line and get the next char. 218a5f0fb15SPaul Saab */ 219*c77c4889SXin LI backchars = pappend((char) c, ch_tell()-1); 2206dcb072bSXin LI if (backchars > 0) 221a5f0fb15SPaul Saab { 222a5f0fb15SPaul Saab /* 223a5f0fb15SPaul Saab * The char won't fit in the line; the line 224a5f0fb15SPaul Saab * is too long to print in the screen width. 225a5f0fb15SPaul Saab * End the line here. 226a5f0fb15SPaul Saab */ 22795270f73SXin LI if (skipeol) 228a5f0fb15SPaul Saab { 2292235c7feSXin LI /* Read to end of line. */ 230*c77c4889SXin LI edisp_pos = ch_tell() - backchars; 231a5f0fb15SPaul Saab do 232a5f0fb15SPaul Saab { 233a5f0fb15SPaul Saab c = ch_forw_get(); 234a5f0fb15SPaul Saab } while (c != '\n' && c != EOI); 235a5f0fb15SPaul Saab new_pos = ch_tell(); 236a5f0fb15SPaul Saab endline = TRUE; 237a5f0fb15SPaul Saab quit_if_one_screen = FALSE; 238b2ea2440SXin LI chopped = TRUE; 239a5f0fb15SPaul Saab } else 240a5f0fb15SPaul Saab { 241d713e089SXin LI if (!wordwrap) 2426dcb072bSXin LI new_pos = ch_tell() - backchars; 243d713e089SXin LI else 244d713e089SXin LI { 245d713e089SXin LI /* 246d713e089SXin LI * We're word-wrapping, so go back to the last space. 247d713e089SXin LI * However, if it's the space itself that couldn't fit, 248d713e089SXin LI * simply ignore it and any subsequent spaces. 249d713e089SXin LI */ 250d713e089SXin LI if (c == ' ' || c == '\t') 251d713e089SXin LI { 252d713e089SXin LI do 253d713e089SXin LI { 254d713e089SXin LI new_pos = ch_tell(); 255*c77c4889SXin LI c = ch_forw_get(); /* {{ what if c == EOI? }} */ 256d713e089SXin LI } while (c == ' ' || c == '\t'); 257d713e089SXin LI if (c == '\r') 258*c77c4889SXin LI c = ch_forw_get(); /* {{ what if c == EOI? }} */ 259d713e089SXin LI if (c == '\n') 260d713e089SXin LI new_pos = ch_tell(); 261d713e089SXin LI } else if (wrap_pos == NULL_POSITION) 262d713e089SXin LI new_pos = ch_tell() - backchars; 263d713e089SXin LI else 264d713e089SXin LI { 265d713e089SXin LI new_pos = wrap_pos; 266d713e089SXin LI loadc(); 267d713e089SXin LI } 268d713e089SXin LI } 269a5f0fb15SPaul Saab endline = FALSE; 270*c77c4889SXin LI edisp_pos = new_pos; 271a5f0fb15SPaul Saab } 272a5f0fb15SPaul Saab break; 273a5f0fb15SPaul Saab } 274d713e089SXin LI if (wordwrap) 275d713e089SXin LI { 276d713e089SXin LI if (c == ' ' || c == '\t') 277d713e089SXin LI { 278d713e089SXin LI if (skipped_leading) 279d713e089SXin LI { 280d713e089SXin LI wrap_pos = ch_tell(); 281d713e089SXin LI savec(); 282d713e089SXin LI } 283d713e089SXin LI } else 284d713e089SXin LI skipped_leading = TRUE; 285d713e089SXin LI } 286a5f0fb15SPaul Saab c = ch_forw_get(); 287a5f0fb15SPaul Saab } 2887374caaaSXin LI 2892235c7feSXin LI #if HILITE_SEARCH 2902235c7feSXin LI if (blankline && show_attn) 2912235c7feSXin LI { 292*c77c4889SXin LI /* Add spurious space to carry possible attn hilite. 293*c77c4889SXin LI * Use pappend_b so that if line ended with \r\n, 294*c77c4889SXin LI * we insert the space before the \r. */ 295*c77c4889SXin LI pappend_b(' ', ch_tell()-1, TRUE); 2962235c7feSXin LI } 2972235c7feSXin LI #endif 29895270f73SXin LI pdone(endline, rscroll && chopped, 1); 2997374caaaSXin LI 3007374caaaSXin LI #if HILITE_SEARCH 3017374caaaSXin LI if (is_filtered(base_pos)) 3027374caaaSXin LI { 3037374caaaSXin LI /* 3047374caaaSXin LI * We don't want to display this line. 3057374caaaSXin LI * Get the next line. 3067374caaaSXin LI */ 3077374caaaSXin LI curr_pos = new_pos; 3087374caaaSXin LI goto get_forw_line; 3097374caaaSXin LI } 3102235c7feSXin LI if (status_col) 311d713e089SXin LI init_status_col(base_pos, line_position(), edisp_pos, new_pos); 3127374caaaSXin LI #endif 313a5f0fb15SPaul Saab 314a5f0fb15SPaul Saab if (squeeze && blankline) 315a5f0fb15SPaul Saab { 316a5f0fb15SPaul Saab /* 317a5f0fb15SPaul Saab * This line is blank. 318a5f0fb15SPaul Saab * Skip down to the last contiguous blank line 319a5f0fb15SPaul Saab * and pretend it is the one which we are returning. 320a5f0fb15SPaul Saab */ 321a5f0fb15SPaul Saab while ((c = ch_forw_get()) == '\n' || c == '\r') 322*c77c4889SXin LI continue; 323a5f0fb15SPaul Saab if (c != EOI) 324a5f0fb15SPaul Saab (void) ch_back_get(); 325a5f0fb15SPaul Saab new_pos = ch_tell(); 326a5f0fb15SPaul Saab } 327a5f0fb15SPaul Saab 328a5f0fb15SPaul Saab return (new_pos); 329a5f0fb15SPaul Saab } 330a5f0fb15SPaul Saab 331d713e089SXin LI public POSITION forw_line(POSITION curr_pos) 3322235c7feSXin LI { 33395270f73SXin LI 33495270f73SXin LI return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE); 3352235c7feSXin LI } 3362235c7feSXin LI 337a5f0fb15SPaul Saab /* 338a5f0fb15SPaul Saab * Get the previous line. 339a5f0fb15SPaul Saab * A "current" position is passed and a "new" position is returned. 340a5f0fb15SPaul Saab * The current position is the position of the first character of 341a5f0fb15SPaul Saab * a line. The new position is the position of the first character 342a5f0fb15SPaul Saab * of the PREVIOUS line. The line obtained is the one starting at new_pos. 343a5f0fb15SPaul Saab */ 344d713e089SXin LI public POSITION back_line(POSITION curr_pos) 345a5f0fb15SPaul Saab { 346d713e089SXin LI POSITION base_pos; 347d713e089SXin LI POSITION new_pos; 348d713e089SXin LI POSITION edisp_pos; 349d713e089SXin LI POSITION begin_new_pos; 350a5f0fb15SPaul Saab int c; 351*c77c4889SXin LI lbool endline; 352*c77c4889SXin LI lbool chopped; 3536dcb072bSXin LI int backchars; 354d713e089SXin LI POSITION wrap_pos; 355*c77c4889SXin LI lbool skipped_leading; 356a5f0fb15SPaul Saab 3577374caaaSXin LI get_back_line: 358a5f0fb15SPaul Saab if (curr_pos == NULL_POSITION || curr_pos <= ch_zero()) 359a5f0fb15SPaul Saab { 360a5f0fb15SPaul Saab null_line(); 361a5f0fb15SPaul Saab return (NULL_POSITION); 362a5f0fb15SPaul Saab } 363a5f0fb15SPaul Saab #if HILITE_SEARCH 3647374caaaSXin LI if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) 365*c77c4889SXin LI prep_hilite((curr_pos < (POSITION) (3*size_linebuf)) ? 0 : 366*c77c4889SXin LI curr_pos - (POSITION) (3*size_linebuf), curr_pos, -1); 367a5f0fb15SPaul Saab #endif 368a5f0fb15SPaul Saab if (ch_seek(curr_pos-1)) 369a5f0fb15SPaul Saab { 370a5f0fb15SPaul Saab null_line(); 371a5f0fb15SPaul Saab return (NULL_POSITION); 372a5f0fb15SPaul Saab } 373a5f0fb15SPaul Saab 374a5f0fb15SPaul Saab if (squeeze) 375a5f0fb15SPaul Saab { 376a5f0fb15SPaul Saab /* 377a5f0fb15SPaul Saab * Find out if the "current" line was blank. 378a5f0fb15SPaul Saab */ 379a5f0fb15SPaul Saab (void) ch_forw_get(); /* Skip the newline */ 380a5f0fb15SPaul Saab c = ch_forw_get(); /* First char of "current" line */ 381*c77c4889SXin LI /* {{ what if c == EOI? }} */ 382a5f0fb15SPaul Saab (void) ch_back_get(); /* Restore our position */ 383a5f0fb15SPaul Saab (void) ch_back_get(); 384a5f0fb15SPaul Saab 385a5f0fb15SPaul Saab if (c == '\n' || c == '\r') 386a5f0fb15SPaul Saab { 387a5f0fb15SPaul Saab /* 388a5f0fb15SPaul Saab * The "current" line was blank. 389a5f0fb15SPaul Saab * Skip over any preceding blank lines, 390a5f0fb15SPaul Saab * since we skipped them in forw_line(). 391a5f0fb15SPaul Saab */ 392a5f0fb15SPaul Saab while ((c = ch_back_get()) == '\n' || c == '\r') 393*c77c4889SXin LI continue; 394a5f0fb15SPaul Saab if (c == EOI) 395a5f0fb15SPaul Saab { 396a5f0fb15SPaul Saab null_line(); 397a5f0fb15SPaul Saab return (NULL_POSITION); 398a5f0fb15SPaul Saab } 399a5f0fb15SPaul Saab (void) ch_forw_get(); 400a5f0fb15SPaul Saab } 401a5f0fb15SPaul Saab } 402a5f0fb15SPaul Saab 403a5f0fb15SPaul Saab /* 404a5f0fb15SPaul Saab * Scan backwards until we hit the beginning of the line. 405a5f0fb15SPaul Saab */ 406a5f0fb15SPaul Saab for (;;) 407a5f0fb15SPaul Saab { 408a5f0fb15SPaul Saab c = ch_back_get(); 409a5f0fb15SPaul Saab if (c == '\n') 410a5f0fb15SPaul Saab { 411a5f0fb15SPaul Saab /* 412a5f0fb15SPaul Saab * This is the newline ending the previous line. 413a5f0fb15SPaul Saab * We have hit the beginning of the line. 414a5f0fb15SPaul Saab */ 4157374caaaSXin LI base_pos = ch_tell() + 1; 416a5f0fb15SPaul Saab break; 417a5f0fb15SPaul Saab } 418a5f0fb15SPaul Saab if (c == EOI) 419a5f0fb15SPaul Saab { 420a5f0fb15SPaul Saab /* 421a5f0fb15SPaul Saab * We have hit the beginning of the file. 422a5f0fb15SPaul Saab * This must be the first line in the file. 423a5f0fb15SPaul Saab * This must, of course, be the beginning of the line. 424a5f0fb15SPaul Saab */ 4257374caaaSXin LI base_pos = ch_tell(); 426a5f0fb15SPaul Saab break; 427a5f0fb15SPaul Saab } 428a5f0fb15SPaul Saab } 429a5f0fb15SPaul Saab 430a5f0fb15SPaul Saab /* 431a5f0fb15SPaul Saab * Now scan forwards from the beginning of this line. 432a5f0fb15SPaul Saab * We keep discarding "printable lines" (based on screen width) 433a5f0fb15SPaul Saab * until we reach the curr_pos. 434a5f0fb15SPaul Saab * 435a5f0fb15SPaul Saab * {{ This algorithm is pretty inefficient if the lines 436a5f0fb15SPaul Saab * are much longer than the screen width, 437a5f0fb15SPaul Saab * but I don't know of any better way. }} 438a5f0fb15SPaul Saab */ 4397374caaaSXin LI new_pos = base_pos; 440a5f0fb15SPaul Saab if (ch_seek(new_pos)) 441a5f0fb15SPaul Saab { 442a5f0fb15SPaul Saab null_line(); 443a5f0fb15SPaul Saab return (NULL_POSITION); 444a5f0fb15SPaul Saab } 445a5f0fb15SPaul Saab endline = FALSE; 446a5f0fb15SPaul Saab prewind(); 4472235c7feSXin LI plinestart(new_pos); 4486dcb072bSXin LI loop: 449d713e089SXin LI wrap_pos = NULL_POSITION; 450d713e089SXin LI skipped_leading = FALSE; 4516dcb072bSXin LI begin_new_pos = new_pos; 452a5f0fb15SPaul Saab (void) ch_seek(new_pos); 453b2ea2440SXin LI chopped = FALSE; 454a5f0fb15SPaul Saab 455d713e089SXin LI for (;;) 456a5f0fb15SPaul Saab { 457a5f0fb15SPaul Saab c = ch_forw_get(); 458*c77c4889SXin LI if (c == EOI) 459a5f0fb15SPaul Saab { 460a5f0fb15SPaul Saab null_line(); 461a5f0fb15SPaul Saab return (NULL_POSITION); 462a5f0fb15SPaul Saab } 463a5f0fb15SPaul Saab new_pos++; 464a5f0fb15SPaul Saab if (c == '\n') 465a5f0fb15SPaul Saab { 4666dcb072bSXin LI backchars = pflushmbc(); 46795270f73SXin LI if (backchars > 0 && !chop_line() && hshift == 0) 4686dcb072bSXin LI { 4696dcb072bSXin LI backchars++; 4706dcb072bSXin LI goto shift; 4716dcb072bSXin LI } 472a5f0fb15SPaul Saab endline = TRUE; 473d713e089SXin LI edisp_pos = new_pos; 474a5f0fb15SPaul Saab break; 475a5f0fb15SPaul Saab } 476*c77c4889SXin LI backchars = pappend((char) c, ch_tell()-1); 4776dcb072bSXin LI if (backchars > 0) 478a5f0fb15SPaul Saab { 479a5f0fb15SPaul Saab /* 480a5f0fb15SPaul Saab * Got a full printable line, but we haven't 481a5f0fb15SPaul Saab * reached our curr_pos yet. Discard the line 482a5f0fb15SPaul Saab * and start a new one. 483a5f0fb15SPaul Saab */ 48495270f73SXin LI if (chop_line() || hshift > 0) 485a5f0fb15SPaul Saab { 486a5f0fb15SPaul Saab endline = TRUE; 487b2ea2440SXin LI chopped = TRUE; 488a5f0fb15SPaul Saab quit_if_one_screen = FALSE; 489d713e089SXin LI edisp_pos = new_pos; 490a5f0fb15SPaul Saab break; 491a5f0fb15SPaul Saab } 4926dcb072bSXin LI shift: 493d713e089SXin LI if (!wordwrap) 4946dcb072bSXin LI { 495d713e089SXin LI pshift_all(); 496d713e089SXin LI new_pos -= backchars; 497d713e089SXin LI } else 498d713e089SXin LI { 499d713e089SXin LI if (c == ' ' || c == '\t') 500d713e089SXin LI { 501d713e089SXin LI for (;;) 502d713e089SXin LI { 503*c77c4889SXin LI c = ch_forw_get(); /* {{ what if c == EOI? }} */ 504d713e089SXin LI if (c == ' ' || c == '\t') 505d713e089SXin LI new_pos++; 506d713e089SXin LI else 507d713e089SXin LI { 508d713e089SXin LI if (c == '\r') 509d713e089SXin LI { 510*c77c4889SXin LI c = ch_forw_get(); /* {{ what if c == EOI? }} */ 511d713e089SXin LI if (c == '\n') 512d713e089SXin LI new_pos++; 513d713e089SXin LI } 514d713e089SXin LI if (c == '\n') 515d713e089SXin LI new_pos++; 516*c77c4889SXin LI edisp_pos = new_pos; 517d713e089SXin LI break; 518d713e089SXin LI } 519d713e089SXin LI } 520d713e089SXin LI if (new_pos >= curr_pos) 521*c77c4889SXin LI { 522*c77c4889SXin LI edisp_pos = new_pos; 523d713e089SXin LI break; 524*c77c4889SXin LI } 525d713e089SXin LI pshift_all(); 526d713e089SXin LI } else 527d713e089SXin LI { 528d713e089SXin LI pshift_all(); 529d713e089SXin LI if (wrap_pos == NULL_POSITION) 530d713e089SXin LI new_pos -= backchars; 531d713e089SXin LI else 532d713e089SXin LI new_pos = wrap_pos; 533d713e089SXin LI } 5346dcb072bSXin LI } 535a5f0fb15SPaul Saab goto loop; 536a5f0fb15SPaul Saab } 537d713e089SXin LI if (wordwrap) 538d713e089SXin LI { 539d713e089SXin LI if (c == ' ' || c == '\t') 540d713e089SXin LI { 541d713e089SXin LI if (skipped_leading) 542d713e089SXin LI wrap_pos = new_pos; 543d713e089SXin LI } else 544d713e089SXin LI skipped_leading = TRUE; 545d713e089SXin LI } 546d713e089SXin LI if (new_pos >= curr_pos) 547d713e089SXin LI { 548d713e089SXin LI edisp_pos = new_pos; 549d713e089SXin LI break; 550d713e089SXin LI } 551d713e089SXin LI } 552a5f0fb15SPaul Saab 553b2ea2440SXin LI pdone(endline, chopped, 0); 5547374caaaSXin LI 5557374caaaSXin LI #if HILITE_SEARCH 5567374caaaSXin LI if (is_filtered(base_pos)) 5577374caaaSXin LI { 5587374caaaSXin LI /* 5597374caaaSXin LI * We don't want to display this line. 5607374caaaSXin LI * Get the previous line. 5617374caaaSXin LI */ 5627374caaaSXin LI curr_pos = begin_new_pos; 5637374caaaSXin LI goto get_back_line; 5647374caaaSXin LI } 565d713e089SXin LI if (status_col) 566d713e089SXin LI init_status_col(base_pos, line_position(), edisp_pos, new_pos); 5677374caaaSXin LI #endif 568a5f0fb15SPaul Saab 569a5f0fb15SPaul Saab return (begin_new_pos); 570a5f0fb15SPaul Saab } 571a5f0fb15SPaul Saab 572a5f0fb15SPaul Saab /* 573a5f0fb15SPaul Saab * Set attnpos. 574a5f0fb15SPaul Saab */ 575d713e089SXin LI public void set_attnpos(POSITION pos) 576a5f0fb15SPaul Saab { 577a5f0fb15SPaul Saab int c; 578a5f0fb15SPaul Saab 579a5f0fb15SPaul Saab if (pos != NULL_POSITION) 580a5f0fb15SPaul Saab { 581a5f0fb15SPaul Saab if (ch_seek(pos)) 582a5f0fb15SPaul Saab return; 583a5f0fb15SPaul Saab for (;;) 584a5f0fb15SPaul Saab { 585a5f0fb15SPaul Saab c = ch_forw_get(); 586a5f0fb15SPaul Saab if (c == EOI) 587a5f0fb15SPaul Saab break; 588a15691bfSXin LI if (c == '\n' || c == '\r') 589a15691bfSXin LI { 590a15691bfSXin LI (void) ch_back_get(); 591a15691bfSXin LI break; 592a15691bfSXin LI } 593a5f0fb15SPaul Saab pos++; 594a5f0fb15SPaul Saab } 595a15691bfSXin LI end_attnpos = pos; 596a15691bfSXin LI for (;;) 597a15691bfSXin LI { 598a15691bfSXin LI c = ch_back_get(); 599a15691bfSXin LI if (c == EOI || c == '\n' || c == '\r') 600a15691bfSXin LI break; 601a15691bfSXin LI pos--; 602a15691bfSXin LI } 603a5f0fb15SPaul Saab } 604a5f0fb15SPaul Saab start_attnpos = pos; 605a5f0fb15SPaul Saab } 606