1/*
|
2 * Copyright (C) 1984-2002 Mark Nudelman
|
2 * Copyright (C) 1984-2011 Mark Nudelman |
3 * 4 * You may distribute under the terms of either the GNU General Public 5 * License or the Less License, as specified in the README file. 6 * 7 * For more information about less, or for information on how to 8 * contact the author, see the README file. 9 */ 10 11 12#include "less.h" 13 14extern IFILE curr_ifile; 15extern int sc_height; 16extern int jump_sline; 17 18/* 19 * A mark is an ifile (input file) plus a position within the file. 20 */ 21struct mark { 22 IFILE m_ifile; 23 struct scrpos m_scrpos; 24}; 25 26/* 27 * The table of marks. 28 * Each mark is identified by a lowercase or uppercase letter. 29 * The final one is lmark, for the "last mark"; addressed by the apostrophe. 30 */ 31#define NMARKS ((2*26)+1) /* a-z, A-Z, lastmark */ 32#define LASTMARK (NMARKS-1) 33static struct mark marks[NMARKS]; 34 35/* 36 * Initialize the mark table to show no marks are set. 37 */ 38 public void 39init_mark() 40{ 41 int i; 42 43 for (i = 0; i < NMARKS; i++) 44 marks[i].m_scrpos.pos = NULL_POSITION; 45} 46 47/* 48 * See if a mark letter is valid (between a and z). 49 */ 50 static struct mark * 51getumark(c) 52 int c; 53{ 54 if (c >= 'a' && c <= 'z') 55 return (&marks[c-'a']); 56 57 if (c >= 'A' && c <= 'Z') 58 return (&marks[c-'A'+26]); 59 60 error("Invalid mark letter", NULL_PARG); 61 return (NULL); 62} 63 64/* 65 * Get the mark structure identified by a character. 66 * The mark struct may come either from the mark table 67 * or may be constructed on the fly for certain characters like ^, $. 68 */ 69 static struct mark * 70getmark(c) 71 int c; 72{ 73 register struct mark *m; 74 static struct mark sm; 75 76 switch (c) 77 { 78 case '^': 79 /* 80 * Beginning of the current file. 81 */ 82 m = &sm; 83 m->m_scrpos.pos = ch_zero(); 84 m->m_scrpos.ln = 0; 85 m->m_ifile = curr_ifile; 86 break; 87 case '$': 88 /* 89 * End of the current file. 90 */ 91 if (ch_end_seek()) 92 { 93 error("Cannot seek to end of file", NULL_PARG); 94 return (NULL); 95 } 96 m = &sm; 97 m->m_scrpos.pos = ch_tell(); 98 m->m_scrpos.ln = sc_height-1; 99 m->m_ifile = curr_ifile; 100 break; 101 case '.': 102 /* 103 * Current position in the current file. 104 */ 105 m = &sm; 106 get_scrpos(&m->m_scrpos); 107 m->m_ifile = curr_ifile; 108 break; 109 case '\'': 110 /* 111 * The "last mark". 112 */ 113 m = &marks[LASTMARK]; 114 break; 115 default: 116 /* 117 * Must be a user-defined mark. 118 */ 119 m = getumark(c); 120 if (m == NULL) 121 break; 122 if (m->m_scrpos.pos == NULL_POSITION) 123 { 124 error("Mark not set", NULL_PARG); 125 return (NULL); 126 } 127 break; 128 } 129 return (m); 130} 131
|
132#ifndef SMALL_PROGRAM
|
132#if PIPEC |
133/* 134 * Is a mark letter is invalid? 135 */ 136 public int 137badmark(c) 138 int c; 139{ 140 return (getmark(c) == NULL); 141}
|
142#endif /* SMALL_PROGRAM */
|
142#endif |
143 144/* 145 * Set a user-defined mark. 146 */ 147 public void 148setmark(c) 149 int c; 150{ 151 register struct mark *m; 152 struct scrpos scrpos; 153 154 m = getumark(c); 155 if (m == NULL) 156 return; 157 get_scrpos(&scrpos); 158 m->m_scrpos = scrpos; 159 m->m_ifile = curr_ifile; 160} 161 162/* 163 * Set lmark (the mark named by the apostrophe). 164 */ 165 public void 166lastmark() 167{ 168 struct scrpos scrpos; 169
|
170 if (ch_getflags() & CH_HELPFILE) 171 return; |
172 get_scrpos(&scrpos); 173 if (scrpos.pos == NULL_POSITION) 174 return; 175 marks[LASTMARK].m_scrpos = scrpos; 176 marks[LASTMARK].m_ifile = curr_ifile; 177} 178 179/* 180 * Go to a mark. 181 */ 182 public void 183gomark(c) 184 int c; 185{ 186 register struct mark *m; 187 struct scrpos scrpos; 188 189 m = getmark(c); 190 if (m == NULL) 191 return; 192 193 /* 194 * If we're trying to go to the lastmark and 195 * it has not been set to anything yet, 196 * set it to the beginning of the current file. 197 */ 198 if (m == &marks[LASTMARK] && m->m_scrpos.pos == NULL_POSITION) 199 { 200 m->m_ifile = curr_ifile; 201 m->m_scrpos.pos = ch_zero(); 202 m->m_scrpos.ln = jump_sline; 203 } 204 205 /* 206 * If we're using lmark, we must save the screen position now, 207 * because if we call edit_ifile() below, lmark will change. 208 * (We save the screen position even if we're not using lmark.) 209 */ 210 scrpos = m->m_scrpos; 211 if (m->m_ifile != curr_ifile) 212 { 213 /* 214 * Not in the current file; edit the correct file. 215 */ 216 if (edit_ifile(m->m_ifile)) 217 return; 218 } 219 220 jump_loc(scrpos.pos, scrpos.ln); 221} 222
|
221#ifndef SMALL_PROGRAM
|
223#if PIPEC |
224/* 225 * Return the position associated with a given mark letter. 226 * 227 * We don't return which screen line the position 228 * is associated with, but this doesn't matter much, 229 * because it's always the first non-blank line on the screen. 230 */ 231 public POSITION 232markpos(c) 233 int c; 234{ 235 register struct mark *m; 236 237 m = getmark(c); 238 if (m == NULL) 239 return (NULL_POSITION); 240 241 if (m->m_ifile != curr_ifile) 242 { 243 error("Mark not in current file", NULL_PARG); 244 return (NULL_POSITION); 245 } 246 return (m->m_scrpos.pos); 247}
|
246#endif /* SMALL_PROGRAM */
|
248#endif /* PIPEC */ |
249 250/* 251 * Clear the marks associated with a specified ifile. 252 */ 253 public void 254unmark(ifile) 255 IFILE ifile; 256{ 257 int i; 258 259 for (i = 0; i < NMARKS; i++) 260 if (marks[i].m_ifile == ifile) 261 marks[i].m_scrpos.pos = NULL_POSITION; 262}
|