#include "less.h"
extern IFILE curr_ifile;
extern int sc_height;
extern int jump_sline;
struct mark {
IFILE m_ifile;
struct scrpos m_scrpos;
};
#define NMARKS ((2*26)+1)
#define LASTMARK (NMARKS-1)
static struct mark marks[NMARKS];
void
init_mark(void)
{
int i;
for (i = 0; i < NMARKS; i++)
marks[i].m_scrpos.pos = -1;
}
static struct mark *
getumark(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);
return (NULL);
}
static struct mark *
getmark(int c)
{
struct mark *m;
static struct mark sm;
switch (c) {
case '^':
m = &sm;
m->m_scrpos.pos = ch_zero();
m->m_scrpos.ln = 0;
m->m_ifile = curr_ifile;
break;
case '$':
if (ch_end_seek()) {
error("Cannot seek to end of file", NULL);
return (NULL);
}
m = &sm;
m->m_scrpos.pos = ch_tell();
m->m_scrpos.ln = sc_height-1;
m->m_ifile = curr_ifile;
break;
case '.':
m = &sm;
get_scrpos(&m->m_scrpos);
m->m_ifile = curr_ifile;
break;
case '\'':
m = &marks[LASTMARK];
break;
default:
m = getumark(c);
if (m == NULL)
break;
if (m->m_scrpos.pos == -1) {
error("Mark not set", NULL);
return (NULL);
}
break;
}
return (m);
}
int
badmark(int c)
{
return (getmark(c) == NULL);
}
void
setmark(int c)
{
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;
}
void
lastmark(void)
{
struct scrpos scrpos;
if (ch_getflags() & CH_HELPFILE)
return;
get_scrpos(&scrpos);
if (scrpos.pos == -1)
return;
marks[LASTMARK].m_scrpos = scrpos;
marks[LASTMARK].m_ifile = curr_ifile;
}
void
gomark(int c)
{
struct mark *m;
struct scrpos scrpos;
m = getmark(c);
if (m == NULL)
return;
if (m == &marks[LASTMARK] && m->m_scrpos.pos == -1) {
m->m_ifile = curr_ifile;
m->m_scrpos.pos = ch_zero();
m->m_scrpos.ln = jump_sline;
}
scrpos = m->m_scrpos;
if (m->m_ifile != curr_ifile) {
if (edit_ifile(m->m_ifile))
return;
}
jump_loc(scrpos.pos, scrpos.ln);
}
off_t
markpos(int c)
{
struct mark *m;
m = getmark(c);
if (m == NULL)
return (-1);
if (m->m_ifile != curr_ifile) {
error("Mark not in current file", NULL);
return (-1);
}
return (m->m_scrpos.pos);
}
void
unmark(IFILE ifile)
{
int i;
for (i = 0; i < NMARKS; i++)
if (marks[i].m_ifile == ifile)
marks[i].m_scrpos.pos = -1;
}