Fix out-of-bounds error when incorporating email from stdin
[mmh] / sbr / seq_msgstats.c
1 /*
2 ** seq_msgstats -- message and sequence manipulation and folder attributes
3 **
4 ** (These functions had once been macros in h/mh.h)
5 */
6
7 #include <sysexits.h>
8 #include <h/mh.h>
9
10 static void
11 assert_msg_range(struct msgs *mp, int msgnum)
12 {
13         if (msgnum < mp->lowoff || msgnum > mp->hghoff) {
14                 adios(EX_SOFTWARE, NULL, "Bug: message out of bounds");
15         }
16 }
17
18
19 void
20 add_sequence(struct msgs *mp, int seqnum, int msgnum)
21 {
22         assert_msg_range(mp, msgnum);
23         mp->msgstats[msgnum - mp->lowoff] |= (1 << (FFATTRSLOT + seqnum));
24 }
25
26 void
27 clear_msg_flags(struct msgs *mp, int msgnum)
28 {
29         assert_msg_range(mp, msgnum);
30         mp->msgstats[msgnum - mp->lowoff] = 0;
31 }
32
33 void
34 clear_sequence(struct msgs *mp, int seqnum, int msgnum)
35 {
36         assert_msg_range(mp, msgnum);
37         mp->msgstats[msgnum - mp->lowoff] &= ~(1 << (FFATTRSLOT + seqnum));
38 }
39
40 void
41 copy_msg_flags(struct msgs *mp, int dstmsg, int srcmsg)
42 {
43         assert_msg_range(mp, srcmsg);
44         assert_msg_range(mp, dstmsg);
45         mp->msgstats[dstmsg - mp->lowoff] = mp->msgstats[srcmsg - mp->lowoff];
46 }
47
48 seqset_t
49 does_exist(struct msgs *mp, int msgnum)
50 {
51         assert_msg_range(mp, msgnum);
52         return mp->msgstats[msgnum - mp->lowoff] & EXISTS;
53 }
54
55 void
56 get_msg_flags(struct msgs *mp, seqset_t *dst, int msgnum)
57 {
58         assert_msg_range(mp, msgnum);
59         *dst = mp->msgstats[msgnum - mp->lowoff];
60 }
61
62 seqset_t
63 in_sequence(struct msgs *mp, int seqnum, int msgnum)
64 {
65         assert_msg_range(mp, msgnum);
66         return mp->msgstats[msgnum - mp->lowoff] & (1 << (FFATTRSLOT + seqnum));
67 }
68
69 seqset_t
70 is_selected(struct msgs *mp, int msgnum)
71 {
72         assert_msg_range(mp, msgnum);
73         return mp->msgstats[msgnum - mp->lowoff] & SELECTED;
74 }
75
76 seqset_t
77 is_unseen(struct msgs *mp, int msgnum)
78 {
79         assert_msg_range(mp, msgnum);
80         return mp->msgstats[msgnum - mp->lowoff] & SELECT_UNSEEN;
81 }
82
83 void
84 set_exists(struct msgs *mp, int msgnum)
85 {
86         assert_msg_range(mp, msgnum);
87         mp->msgstats[msgnum - mp->lowoff] |= EXISTS;
88 }
89
90 void
91 set_msg_flags(struct msgs *mp, seqset_t *src, int msgnum)
92 {
93         assert_msg_range(mp, msgnum);
94         mp->msgstats[msgnum - mp->lowoff] = *src;
95 }
96
97 void
98 set_selected(struct msgs *mp, int msgnum)
99 {
100         assert_msg_range(mp, msgnum);
101
102         if (is_selected(mp, msgnum)) {
103                 return;
104         }
105
106         mp->msgstats[msgnum - mp->lowoff] |= SELECTED;
107         if (mp->lowsel == 0 || msgnum < mp->lowsel) {
108                 mp->lowsel = msgnum;
109         }
110         if (msgnum > mp->hghsel) {
111                 mp->hghsel = msgnum;
112         }
113         mp->numsel++;
114 }
115
116 void
117 set_unseen(struct msgs *mp, int msgnum)
118 {
119         assert_msg_range(mp, msgnum);
120         mp->msgstats[msgnum - mp->lowoff] |= SELECT_UNSEEN;
121 }
122
123 void
124 unset_exists(struct msgs *mp, int msgnum)
125 {
126         assert_msg_range(mp, msgnum);
127         mp->msgstats[msgnum - mp->lowoff] &= ~EXISTS;
128 }
129
130 void
131 unset_selected(struct msgs *mp, int msgnum)
132 {
133         assert_msg_range(mp, msgnum);
134
135         if (!is_selected(mp, msgnum)) {
136                 return;
137         }
138
139         mp->msgstats[msgnum - mp->lowoff] &= ~SELECTED;
140         if (mp->numsel > 0) {
141                 mp->numsel--;
142         }
143 }
144
145 void
146 unset_unseen(struct msgs *mp, int msgnum)
147 {
148         assert_msg_range(mp, msgnum);
149         mp->msgstats[msgnum - mp->lowoff] &= ~SELECT_UNSEEN;
150 }
151
152
153 /*
154 **  private/public sequences
155 */
156
157 int
158 is_seq_private(struct msgs *mp, int seqnum)
159 {
160         return mp->attrstats & (1 << (FFATTRSLOT + seqnum));
161 }
162
163 void
164 make_seq_public(struct msgs *mp, int seqnum)
165 {
166         mp->attrstats &= ~(1 << (FFATTRSLOT + seqnum));
167 }
168 void
169 make_seq_private(struct msgs *mp, int seqnum)
170 {
171         mp->attrstats |= (1 << (FFATTRSLOT + seqnum));
172 }
173 void
174 make_all_public(struct msgs *mp)
175 {
176         mp->attrstats = 0;
177 }
178
179
180 /*
181 ** folder attributes
182 */
183
184 void
185 clear_folder_flags(struct msgs *mp)
186 {
187         mp->msgflags = 0;
188 }
189
190 int
191 is_readonly(struct msgs *mp)
192 {
193         return mp->msgflags & READONLY;
194 }
195 void
196 set_readonly(struct msgs *mp)
197 {
198         mp->msgflags |= READONLY;
199 }
200
201 int
202 other_files(struct msgs *mp)
203 {
204         return mp->msgflags & OTHERS;
205 }
206 void
207 set_other_files(struct msgs *mp)
208 {
209         mp->msgflags |= OTHERS;
210 }