/************************************************************************ * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * * provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ************************************************************************/ #include "jove.h" RCS("$Id: marks.c,v 14.31 1993/02/18 10:07:33 tom Exp tom $") DEF_INT( "marks-should-float", MarksShouldFloat, V_BOOL ) = YES; Mark * MakeMark(line, column, type) Line *line; { register Buffer *cb = curbuf; register Mark *newmark = (Mark *) emalloc(sizeof *newmark); init_mark(newmark, cb, line, column, type); newmark->m_alloced++; /* say that it can be free()ed */ return newmark; } int del_mark(m, b) register Mark *m; Buffer *b; { register Mark **hp; for (hp = &b->b_marks; (*hp) != m; hp = &(*hp)->m_next) if ((*hp) == NULL) return NO; (*hp) = m->m_next; /* only release it if it was created by MakeMark. */ if (m->m_alloced) free((void_*) m); return YES; } void DelMark(m) Mark *m; { if (!del_mark(m, curbuf)) complain("?mark?"); } DEF_CMD( "pop-mark", PopMark, NO ) { register Buffer *cb = curbuf; register unsigned pmark = cb->b_themark; /* unsigned for % */ register Mark *cm; if ((cm = cb->b_markring[pmark]) == NULL) /* curmark */ return; PtToMark(); cb->b_themark = (pmark - 1) % NMARKS; if (cb->b_markring[(pmark + 1) % NMARKS] == NULL) { /* move the mark just popped to the end of the list, and clear the slot, so that next DoSetMark creates a new mark. */ cb->b_markring[pmark] = NULL; do { pmark = (pmark - 1) % NMARKS; } while (cb->b_markring[pmark] != NULL); cb->b_markring[pmark] = cm; } } void set_mark() { register Buffer *cb = curbuf; DoSetMark(cb->b_dot, cb->b_char); } DEF_CMD( "set-mark", SetMark, NO ) { if (exp_p) PopMark(); else set_mark(); } void DoSetMark(l, c) Line *l; { register Buffer *cb = curbuf; register int pmark = (unsigned)(cb->b_themark + 1) % NMARKS; register Mark **mp; cb->b_themark = pmark; if (*(mp = &cb->b_markring[pmark])) DelMark(*mp); (*mp) = MakeMark(l, c, MarksShouldFloat); s_mess("[Point pushed]"); } /* Move point to Mark */ void ToMark(mark) Mark *mark; { register Mark *m; if ((m = mark) == NULL) return; DotTo(m->m_line, m->m_char); #if NO /* [TRH] this is now assured by DotTo */ { register Buffer *cb = curbuf; register int len; if (cb->b_char > (len = length(cb->b_dot))) cb->b_char = len; } #endif } Mark * CurMark() { register Buffer *cb = curbuf; register Mark *m; if ((m = cb->b_markring[cb->b_themark]) == NULL) complain("No mark."); #if 0 /* NO! breaks too many things! */ if (m->m_line == cb->b_dot && m->m_char == cb->b_char) complain("Empty region."); #endif return m; } void to_mark() { ToMark(CurMark()); } DEF_CMD( "exchange-point-and-mark", PtToMark, NO ) { register Line *mline; register int mchar; { register Buffer *cb = curbuf; mline = cb->b_dot; mchar = cb->b_char; } { register Mark *m = CurMark(); ToMark(m); MarkSet(m, mline, mchar); } } /* show mark */ DEF_CMD( "mark-flash", ShowMark, NO ) { register Mark *m = CurMark(); Blink(m->m_line, m->m_char); } /* Fix marks for after a deletion. For now, even marks that don't float will actually float, because we can't allow marks to point to non-existant lines. [TRH] It is a lot simpler than you thought... no need for two passes since marks are moved backward while we move forward over the lines so we can never encounter the same mark twice */ void DFixMarks(line1, char1, line2, char2) Line *line1; register int char1; Line *line2; { register Mark *m; register Line *lp = line1; do { if ((m = curbuf->b_marks) == NULL) return; do { #if NO if (!m->m_floater) continue; #endif if (m->m_line != lp) continue; if (/*m->m_line*/ lp == line1 && m->m_char <= char1) continue; /* set mark to start of region. (we know it's inside since lp is) Be careful about marks just outside on last line. */ if (/*m->m_line*/ lp == line2 && m->m_char > char2) m->m_char -= (char2 - char1); else m->m_char = char1; m->m_line = line1; } while (m = m->m_next); } while (lp != line2 && (lp = lp->l_next, TRUE)); } /* Fix marks after an insertion. Marks that don't float are ignored on insertion, which means PtToMark has to be careful. Note that programmed FLOATERing marks that equal DOT move along with it, whereas user-defined marks stay put ... */ void IFixMarks(line1, char1, line2, char2) register Line *line1; register int char1; Line *line2; { register Mark *m; if (m = curbuf->b_marks) do { if (!m->m_floater) continue; if (m->m_line != line1) continue; if (m->m_char < char1) continue; if (m->m_char == char1 && !(m->m_floater & FLOATER)) continue; m->m_char += (char2 - char1); m->m_line = line2; } while (m = m->m_next); } /*====================================================================== * $Log: marks.c,v $ * Revision 14.31 1993/02/18 10:07:33 tom * remove (void) casts; lotsa random optimizations. * * Revision 14.30 1993/02/05 00:07:30 tom * cleanup whitespace; some random optimizations. * * Revision 14.28 1992/10/24 01:24:21 tom * convert to "port{ansi,defs}.h" conventions. * * Revision 14.26 1992/08/26 23:56:56 tom * remove AllMarkSet(); add RCS directives. * */