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