BSD 4_3 development
[unix-history] / usr / contrib / jove / marks.c
CommitLineData
394a1d25
C
1/*************************************************************************
2 * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3 * provided to you without charge for use only on a licensed Unix *
4 * system. You may copy JOVE provided that this notice is included with *
5 * the copy. You may not sell copies of this program or versions *
6 * modified for use on microcomputer systems, unless the copies are *
7 * included with a Unix system distribution and the source is provided. *
8 *************************************************************************/
9
10int MarksShouldFloat = 1;
11
12#include "jove.h"
13
14Mark *
15MakeMark(line, column, type)
16register Line *line;
17{
18 register Mark *newmark = (Mark *) emalloc(sizeof *newmark);
19
20 MarkSet(newmark, line, column);
21 newmark->m_next = curbuf->b_marks;
22 newmark->m_floater = type;
23 curbuf->b_marks = newmark;
24 return newmark;
25}
26
27DelMark(m)
28register Mark *m;
29{
30 register Mark *mp = curbuf->b_marks;
31
32 if (m == mp)
33 curbuf->b_marks = m->m_next;
34 else {
35 while (mp != 0 && mp->m_next != m)
36 mp = mp->m_next;
37 if (mp == 0)
38 complain("Unknown mark!");
39 mp->m_next = m->m_next;
40 }
41 free((char *) m);
42}
43
44AllMarkSet(b, line, col)
45Buffer *b;
46register Line *line;
47{
48 register Mark *mp;
49
50 for (mp = b->b_marks; mp != 0; mp = mp->m_next)
51 MarkSet(mp, line, col);
52}
53
54MarkSet(m, line, column)
55Mark *m;
56Line *line;
57{
58 m->m_line = line;
59 m->m_char = column;
60}
61
62PopMark()
63{
64 int pmark;
65
66 if (curmark == 0)
67 return;
68 if (curbuf->b_markring[(curbuf->b_themark + 1) % NMARKS] == 0) {
69 pmark = curbuf->b_themark;
70 do {
71 if (--pmark < 0)
72 pmark = NMARKS - 1;
73 } while (curbuf->b_markring[pmark] != 0);
74
75 curbuf->b_markring[pmark] = MakeMark(curline, curchar, MarksShouldFloat);
76 ToMark(curmark);
77 DelMark(curmark);
78 curmark = 0;
79 } else
80 PtToMark();
81
82 pmark = curbuf->b_themark - 1;
83 if (pmark < 0)
84 pmark = NMARKS - 1;
85 curbuf->b_themark = pmark;
86}
87
88SetMark()
89{
90 if (exp_p)
91 PopMark();
92 else
93 DoSetMark(curline, curchar);
94}
95
96DoSetMark(l, c)
97Line *l;
98{
99 curbuf->b_themark = (curbuf->b_themark + 1) % NMARKS;
100 if (curmark == 0)
101 curmark = MakeMark(l, c, MarksShouldFloat);
102 else
103 MarkSet(curmark, l, c);
104 s_mess("[Point pushed]");
105}
106
107/* Move point to Mark */
108
109ToMark(m)
110Mark *m;
111{
112 int len;
113
114 if (m == 0)
115 return;
116 DotTo(m->m_line, m->m_char);
117 if (curchar > (len = length(curline)))
118 curchar = len;
119}
120
121Mark *
122CurMark()
123{
124 if (curmark == 0)
125 complain("No mark.");
126 return curmark;
127}
128
129PtToMark()
130{
131 Line *mline;
132 int mchar;
133 Mark *m = CurMark();
134
135 mline = curline;
136 mchar = curchar;
137
138 ToMark(m);
139 MarkSet(m, mline, mchar);
140}
141
142/* Fix marks for after a deletion. For now, even marks that don't
143 float will actually float, because we can't allow marks to point
144 to non-existant lines. */
145
146DFixMarks(line1, char1, line2, char2)
147register Line *line1,
148 *line2;
149{
150 register Mark *m;
151 Line *lp = line1;
152
153 if (curbuf->b_marks == 0)
154 return;
155 while (lp != line2->l_next) {
156 for (m = curbuf->b_marks; m != 0; m = m->m_next) {
157/* if (!m->m_floater)
158 continue; */
159 if (m->m_line == lp)
160 m->m_char |= (1 << 15);
161 }
162 lp = lp->l_next;
163 }
164 for (m = curbuf->b_marks; m; m = m->m_next) {
165/* if (!m->m_floater)
166 continue; */
167 if ((m->m_char & (1 << 15)) == 0)
168 continue; /* Not effected */
169 m->m_char &= ~(1 << 15);
170 if (m->m_line == line1 && m->m_char < char1)
171 continue; /* This mark is not affected */
172 if (line1 == line2) {
173 if (m->m_char >= char1 && m->m_char <= char2)
174 m->m_char = char1;
175 else if (m->m_char > char2)
176 m->m_char -= (char2 - char1);
177 /* Same line move the mark backward */
178 } else if (m->m_line == line2) {
179 if (m->m_char > char2)
180 m->m_char = char1 + (m->m_char - char2);
181 else
182 m->m_char = char1;
183 m->m_line = line1;
184 } else {
185 m->m_char = char1;
186 m->m_line = line1;
187 }
188 }
189}
190
191/* Fix marks after an insertion. Marks that don't float are ignored
192 on insertion, which means PtToMark has to be careful ... */
193
194IFixMarks(line1, char1, line2, char2)
195register Line *line1,
196 *line2;
197{
198 register Mark *m;
199
200 for (m = curbuf->b_marks; m != 0; m = m->m_next) {
201 if (!m->m_floater)
202 continue;
203 if (m->m_line == line1) {
204 if (m->m_char > char1) {
205 m->m_line = line2;
206 if (line1 == line2)
207 m->m_char += (char2 - char1);
208 else
209 m->m_char = char2 + (m->m_char - char1);
210 }
211 }
212 }
213}