| 1 | /* |
| 2 | * Routines dealing with the "position" table. |
| 3 | * This is a table which tells the position (in the input file) of the |
| 4 | * first char on each currently displayed line. |
| 5 | * |
| 6 | * {{ The position table is scrolled by moving all the entries. |
| 7 | * Would be better to have a circular table |
| 8 | * and just change a couple of pointers. }} |
| 9 | */ |
| 10 | |
| 11 | #include "less.h" |
| 12 | #include "position.h" |
| 13 | |
| 14 | static POSITION *table = NULL; /* The position table */ |
| 15 | static int table_size; |
| 16 | |
| 17 | extern int sc_width, sc_height; |
| 18 | |
| 19 | /* |
| 20 | * Return the starting file position of a line displayed on the screen. |
| 21 | * The line may be specified as a line number relative to the top |
| 22 | * of the screen, but is usually one of these special cases: |
| 23 | * the top (first) line on the screen |
| 24 | * the second line on the screen |
| 25 | * the bottom line on the screen |
| 26 | * the line after the bottom line on the screen |
| 27 | */ |
| 28 | public POSITION |
| 29 | position(where) |
| 30 | int where; |
| 31 | { |
| 32 | switch (where) |
| 33 | { |
| 34 | case BOTTOM: |
| 35 | where = sc_height - 2; |
| 36 | break; |
| 37 | case BOTTOM_PLUS_ONE: |
| 38 | where = sc_height - 1; |
| 39 | break; |
| 40 | case MIDDLE: |
| 41 | where = sc_height / 2; |
| 42 | } |
| 43 | return (table[where]); |
| 44 | } |
| 45 | |
| 46 | /* |
| 47 | * Add a new file position to the bottom of the position table. |
| 48 | */ |
| 49 | public void |
| 50 | add_forw_pos(pos) |
| 51 | POSITION pos; |
| 52 | { |
| 53 | register int i; |
| 54 | |
| 55 | /* |
| 56 | * Scroll the position table up. |
| 57 | */ |
| 58 | for (i = 1; i < sc_height; i++) |
| 59 | table[i-1] = table[i]; |
| 60 | table[sc_height - 1] = pos; |
| 61 | } |
| 62 | |
| 63 | /* |
| 64 | * Add a new file position to the top of the position table. |
| 65 | */ |
| 66 | public void |
| 67 | add_back_pos(pos) |
| 68 | POSITION pos; |
| 69 | { |
| 70 | register int i; |
| 71 | |
| 72 | /* |
| 73 | * Scroll the position table down. |
| 74 | */ |
| 75 | for (i = sc_height - 1; i > 0; i--) |
| 76 | table[i] = table[i-1]; |
| 77 | table[0] = pos; |
| 78 | } |
| 79 | |
| 80 | /* |
| 81 | * Initialize the position table, done whenever we clear the screen. |
| 82 | */ |
| 83 | public void |
| 84 | pos_clear() |
| 85 | { |
| 86 | register int i; |
| 87 | |
| 88 | for (i = 0; i < sc_height; i++) |
| 89 | table[i] = NULL_POSITION; |
| 90 | } |
| 91 | |
| 92 | /* |
| 93 | * Allocate the position table. |
| 94 | */ |
| 95 | public void |
| 96 | pos_init() |
| 97 | { |
| 98 | if (sc_height <= table_size) |
| 99 | return; |
| 100 | if (table != NULL) |
| 101 | free((char*)table); |
| 102 | table = (POSITION *) ecalloc(sc_height, sizeof(POSITION)); |
| 103 | table_size = sc_height; |
| 104 | } |
| 105 | |
| 106 | /* |
| 107 | * See if the byte at a specified position is currently on the screen. |
| 108 | * Check the position table to see if the position falls within its range. |
| 109 | * Return the position table entry if found, -1 if not. |
| 110 | */ |
| 111 | public int |
| 112 | onscreen(pos) |
| 113 | POSITION pos; |
| 114 | { |
| 115 | register int i; |
| 116 | |
| 117 | if (pos < table[0]) |
| 118 | return (-1); |
| 119 | for (i = 1; i < sc_height; i++) |
| 120 | if (pos < table[i]) |
| 121 | return (i-1); |
| 122 | return (-1); |
| 123 | } |
| 124 | |
| 125 | /* |
| 126 | * See if the entire screen is empty. |
| 127 | */ |
| 128 | public int |
| 129 | empty_screen() |
| 130 | { |
| 131 | return (empty_lines(0, sc_height-1)); |
| 132 | } |
| 133 | |
| 134 | public int |
| 135 | empty_lines(s, e) |
| 136 | int s; |
| 137 | int e; |
| 138 | { |
| 139 | register int i; |
| 140 | |
| 141 | for (i = s; i <= e; i++) |
| 142 | if (table[i] != NULL_POSITION) |
| 143 | return (0); |
| 144 | return (1); |
| 145 | } |
| 146 | |
| 147 | /* |
| 148 | * Get the current screen position. |
| 149 | * The screen position consists of both a file position and |
| 150 | * a screen line number where the file position is placed on the screen. |
| 151 | * Normally the screen line number is 0, but if we are positioned |
| 152 | * such that the top few lines are empty, we may have to set |
| 153 | * the screen line to a number > 0. |
| 154 | */ |
| 155 | public void |
| 156 | get_scrpos(scrpos) |
| 157 | struct scrpos *scrpos; |
| 158 | { |
| 159 | register int i; |
| 160 | |
| 161 | /* |
| 162 | * Find the first line on the screen which has something on it, |
| 163 | * and return the screen line number and the file position. |
| 164 | */ |
| 165 | for (i = 0; i < sc_height; i++) |
| 166 | if (table[i] != NULL_POSITION) |
| 167 | { |
| 168 | scrpos->ln = i+1; |
| 169 | scrpos->pos = table[i]; |
| 170 | return; |
| 171 | } |
| 172 | /* |
| 173 | * The screen is empty. |
| 174 | */ |
| 175 | scrpos->pos = NULL_POSITION; |
| 176 | } |
| 177 | |
| 178 | /* |
| 179 | * Adjust a screen line number to be a simple positive integer |
| 180 | * in the range { 0 .. sc_height-2 }. |
| 181 | * (The bottom line, sc_height-1, is reserved for prompts, etc.) |
| 182 | * The given "sline" may be in the range { 1 .. sc_height-1 } |
| 183 | * to refer to lines relative to the top of the screen (starting from 1), |
| 184 | * or it may be in { -1 .. -(sc_height-1) } to refer to lines |
| 185 | * relative to the bottom of the screen. |
| 186 | */ |
| 187 | public int |
| 188 | adjsline(sline) |
| 189 | int sline; |
| 190 | { |
| 191 | /* |
| 192 | * Negative screen line number means |
| 193 | * relative to the bottom of the screen. |
| 194 | */ |
| 195 | if (sline < 0) |
| 196 | sline += sc_height; |
| 197 | /* |
| 198 | * Can't be less than 1 or greater than sc_height-1. |
| 199 | */ |
| 200 | if (sline <= 0) |
| 201 | sline = 1; |
| 202 | if (sline >= sc_height) |
| 203 | sline = sc_height - 1; |
| 204 | /* |
| 205 | * Return zero-based line number, not one-based. |
| 206 | */ |
| 207 | return (sline-1); |
| 208 | } |