|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.