1: /* 2: * High level routines dealing with getting lines of input 3: * from the file being viewed. 4: * 5: * When we speak of "lines" here, we mean PRINTABLE lines; 6: * lines processed with respect to the screen width. 7: * We use the term "raw line" to refer to lines simply 8: * delimited by newlines; not processed with respect to screen width. 9: */ 10: 11: #include "less.h" 12: 13: extern int do_bs; 14: extern int squeeze; 15: extern char *line; 16: 17: /* 18: * Get the next line. 19: * A "current" position is passed and a "new" position is returned. 20: * The current position is the position of the first character of 21: * a line. The new position is the position of the first character 22: * of the NEXT line. The line obtained is the line starting at curr_pos. 23: */ 24: public POSITION 25: forw_line(curr_pos) 26: POSITION curr_pos; 27: { 28: POSITION new_pos; 29: register int c; 30: 31: if (curr_pos == NULL_POSITION || ch_seek(curr_pos)) 32: return (NULL_POSITION); 33: 34: c = ch_forw_get(); 35: if (c == EOF) 36: return (NULL_POSITION); 37: 38: prewind(); 39: for (;;) 40: { 41: if (c == '\n' || c == EOF) 42: { 43: /* 44: * End of the line. 45: */ 46: new_pos = ch_tell(); 47: break; 48: } 49: 50: /* 51: * Append the char to the line and get the next char. 52: */ 53: if (pappend(c)) 54: { 55: /* 56: * The char won't fit in the line; the line 57: * is too long to print in the screen width. 58: * End the line here. 59: */ 60: new_pos = ch_tell() - 1; 61: break; 62: } 63: c = ch_forw_get(); 64: } 65: (void) pappend('\0'); 66: 67: if (squeeze && *line == '\0') 68: { 69: /* 70: * This line is blank. 71: * Skip down to the last contiguous blank line 72: * and pretend it is the one which we are returning. 73: */ 74: while ((c = ch_forw_get()) == '\n') 75: ; 76: if (c != EOF) 77: (void) ch_back_get(); 78: new_pos = ch_tell(); 79: } 80: 81: return (new_pos); 82: } 83: 84: /* 85: * Get the previous line. 86: * A "current" position is passed and a "new" position is returned. 87: * The current position is the position of the first character of 88: * a line. The new position is the position of the first character 89: * of the PREVIOUS line. The line obtained is the one starting at new_pos. 90: */ 91: public POSITION 92: back_line(curr_pos) 93: POSITION curr_pos; 94: { 95: POSITION new_pos, begin_new_pos; 96: int c; 97: 98: if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 || 99: ch_seek(curr_pos-1)) 100: return (NULL_POSITION); 101: 102: if (squeeze) 103: { 104: /* 105: * Find out if the "current" line was blank. 106: */ 107: (void) ch_forw_get(); /* Skip the newline */ 108: c = ch_forw_get(); /* First char of "current" line */ 109: (void) ch_back_get(); /* Restore our position */ 110: (void) ch_back_get(); 111: 112: if (c == '\n') 113: { 114: /* 115: * The "current" line was blank. 116: * Skip over any preceeding blank lines, 117: * since we skipped them in forw_line(). 118: */ 119: while ((c = ch_back_get()) == '\n') 120: ; 121: if (c == EOF) 122: return (NULL_POSITION); 123: (void) ch_forw_get(); 124: } 125: } 126: 127: /* 128: * Scan backwards until we hit the beginning of the line. 129: */ 130: for (;;) 131: { 132: c = ch_back_get(); 133: if (c == '\n') 134: { 135: /* 136: * This is the newline ending the previous line. 137: * We have hit the beginning of the line. 138: */ 139: new_pos = ch_tell() + 1; 140: break; 141: } 142: if (c == EOF) 143: { 144: /* 145: * We have hit the beginning of the file. 146: * This must be the first line in the file. 147: * This must, of course, be the beginning of the line. 148: */ 149: new_pos = (POSITION)0; 150: break; 151: } 152: } 153: 154: /* 155: * Now scan forwards from the beginning of this line. 156: * We keep discarding "printable lines" (based on screen width) 157: * until we reach the curr_pos. 158: * 159: * {{ This algorithm is pretty inefficient if the lines 160: * are much longer than the screen width, 161: * but I don't know of any better way. }} 162: */ 163: if (ch_seek(new_pos)) 164: return (NULL_POSITION); 165: loop: 166: begin_new_pos = new_pos; 167: prewind(); 168: 169: do 170: { 171: c = ch_forw_get(); 172: new_pos++; 173: if (c == '\n') 174: break; 175: if (pappend(c)) 176: { 177: /* 178: * Got a full printable line, but we haven't 179: * reached our curr_pos yet. Discard the line 180: * and start a new one. 181: */ 182: (void) pappend('\0'); 183: (void) ch_back_get(); 184: new_pos--; 185: goto loop; 186: } 187: } while (new_pos < curr_pos); 188: 189: (void) pappend('\0'); 190: 191: return (begin_new_pos); 192: }