X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=thirdparty%2Fless%2Fmark.c;fp=thirdparty%2Fless%2Fmark.c;h=585b412b49d20434bb4c6815ccd07dde1fc645fd;hb=70c3470408854526136adcf3705d1dc7e7189c0a;hp=0000000000000000000000000000000000000000;hpb=d3846c6fda2eb17ccd0402551be8b569ab2dbc5a;p=apitrace diff --git a/thirdparty/less/mark.c b/thirdparty/less/mark.c new file mode 100644 index 0000000..585b412 --- /dev/null +++ b/thirdparty/less/mark.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 1984-2011 Mark Nudelman + * + * You may distribute under the terms of either the GNU General Public + * License or the Less License, as specified in the README file. + * + * For more information about less, or for information on how to + * contact the author, see the README file. + */ + + +#include "less.h" + +extern IFILE curr_ifile; +extern int sc_height; +extern int jump_sline; + +/* + * A mark is an ifile (input file) plus a position within the file. + */ +struct mark { + IFILE m_ifile; + struct scrpos m_scrpos; +}; + +/* + * The table of marks. + * Each mark is identified by a lowercase or uppercase letter. + * The final one is lmark, for the "last mark"; addressed by the apostrophe. + */ +#define NMARKS ((2*26)+1) /* a-z, A-Z, lastmark */ +#define LASTMARK (NMARKS-1) +static struct mark marks[NMARKS]; + +/* + * Initialize the mark table to show no marks are set. + */ + public void +init_mark() +{ + int i; + + for (i = 0; i < NMARKS; i++) + marks[i].m_scrpos.pos = NULL_POSITION; +} + +/* + * See if a mark letter is valid (between a and z). + */ + static struct mark * +getumark(c) + int c; +{ + if (c >= 'a' && c <= 'z') + return (&marks[c-'a']); + + if (c >= 'A' && c <= 'Z') + return (&marks[c-'A'+26]); + + error("Invalid mark letter", NULL_PARG); + return (NULL); +} + +/* + * Get the mark structure identified by a character. + * The mark struct may come either from the mark table + * or may be constructed on the fly for certain characters like ^, $. + */ + static struct mark * +getmark(c) + int c; +{ + register struct mark *m; + static struct mark sm; + + switch (c) + { + case '^': + /* + * Beginning of the current file. + */ + m = &sm; + m->m_scrpos.pos = ch_zero(); + m->m_scrpos.ln = 0; + m->m_ifile = curr_ifile; + break; + case '$': + /* + * End of the current file. + */ + if (ch_end_seek()) + { + error("Cannot seek to end of file", NULL_PARG); + return (NULL); + } + m = &sm; + m->m_scrpos.pos = ch_tell(); + m->m_scrpos.ln = sc_height-1; + m->m_ifile = curr_ifile; + break; + case '.': + /* + * Current position in the current file. + */ + m = &sm; + get_scrpos(&m->m_scrpos); + m->m_ifile = curr_ifile; + break; + case '\'': + /* + * The "last mark". + */ + m = &marks[LASTMARK]; + break; + default: + /* + * Must be a user-defined mark. + */ + m = getumark(c); + if (m == NULL) + break; + if (m->m_scrpos.pos == NULL_POSITION) + { + error("Mark not set", NULL_PARG); + return (NULL); + } + break; + } + return (m); +} + +/* + * Is a mark letter is invalid? + */ + public int +badmark(c) + int c; +{ + return (getmark(c) == NULL); +} + +/* + * Set a user-defined mark. + */ + public void +setmark(c) + int c; +{ + register struct mark *m; + struct scrpos scrpos; + + m = getumark(c); + if (m == NULL) + return; + get_scrpos(&scrpos); + m->m_scrpos = scrpos; + m->m_ifile = curr_ifile; +} + +/* + * Set lmark (the mark named by the apostrophe). + */ + public void +lastmark() +{ + struct scrpos scrpos; + + if (ch_getflags() & CH_HELPFILE) + return; + get_scrpos(&scrpos); + if (scrpos.pos == NULL_POSITION) + return; + marks[LASTMARK].m_scrpos = scrpos; + marks[LASTMARK].m_ifile = curr_ifile; +} + +/* + * Go to a mark. + */ + public void +gomark(c) + int c; +{ + register struct mark *m; + struct scrpos scrpos; + + m = getmark(c); + if (m == NULL) + return; + + /* + * If we're trying to go to the lastmark and + * it has not been set to anything yet, + * set it to the beginning of the current file. + */ + if (m == &marks[LASTMARK] && m->m_scrpos.pos == NULL_POSITION) + { + m->m_ifile = curr_ifile; + m->m_scrpos.pos = ch_zero(); + m->m_scrpos.ln = jump_sline; + } + + /* + * If we're using lmark, we must save the screen position now, + * because if we call edit_ifile() below, lmark will change. + * (We save the screen position even if we're not using lmark.) + */ + scrpos = m->m_scrpos; + if (m->m_ifile != curr_ifile) + { + /* + * Not in the current file; edit the correct file. + */ + if (edit_ifile(m->m_ifile)) + return; + } + + jump_loc(scrpos.pos, scrpos.ln); +} + +/* + * Return the position associated with a given mark letter. + * + * We don't return which screen line the position + * is associated with, but this doesn't matter much, + * because it's always the first non-blank line on the screen. + */ + public POSITION +markpos(c) + int c; +{ + register struct mark *m; + + m = getmark(c); + if (m == NULL) + return (NULL_POSITION); + + if (m->m_ifile != curr_ifile) + { + error("Mark not in current file", NULL_PARG); + return (NULL_POSITION); + } + return (m->m_scrpos.pos); +} + +/* + * Clear the marks associated with a specified ifile. + */ + public void +unmark(ifile) + IFILE ifile; +{ + int i; + + for (i = 0; i < NMARKS; i++) + if (marks[i].m_ifile == ifile) + marks[i].m_scrpos.pos = NULL_POSITION; +}