Add support for tab-completion when selecting by rule
[alpine.git] / pith / icache.c
blob19f152140c9bf6c7300e8d187ec4af5c6462445c
1 /*
2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2006-2007 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include "../pith/headers.h"
16 #include "../pith/icache.h"
17 #include "../pith/mailindx.h"
18 #include "../pith/flag.h"
19 #include "../pith/msgno.h"
20 #include "../pith/status.h"
21 #include "../pith/pineelt.h"
24 * Internal prototypes
29 * * * * Index entry cache manager * * *
34 * Erase a particular entry in the cache.
36 void
37 clear_index_cache_ent(MAILSTREAM *stream, long int msgno, unsigned int flags)
39 long rawno = -1L;
40 PINELT_S **peltp;
41 MESSAGECACHE *mc;
43 if(stream){
44 if(flags & IC_USE_RAW_MSGNO)
45 rawno = msgno;
46 else
47 rawno = mn_m2raw(sp_msgmap(stream), msgno);
49 if(rawno > 0L && rawno <= stream->nmsgs){
50 mc = mail_elt(stream, rawno);
51 if(mc && mc->sparep){
52 peltp = (PINELT_S **) &mc->sparep;
53 if((*peltp)->ice){
55 * This is intended to be a lightweight reset of
56 * just the widths and print_format strings. For example,
57 * the width of the screen changed and nothing else.
58 * We simply unset the widths_done bit and it
59 * is up to the drawer to free and recalculate the
60 * print_format strings and to reset the widths.
62 * The else case is a clear of the entire cache entry
63 * leaving behind only the empty structure.
65 if(flags & IC_CLEAR_WIDTHS_DONE){
66 (*peltp)->ice->widths_done = 0;
68 /* also zero out hash value */
69 (*peltp)->ice->id = 0;
71 if((*peltp)->ice->tice){
72 (*peltp)->ice->tice->widths_done = 0;
74 /* also zero out hash value */
75 (*peltp)->ice->tice->id = 0;
78 else
79 clear_ice(&(*peltp)->ice);
87 void
88 clear_index_cache(MAILSTREAM *stream, unsigned int flags)
90 long rawno;
92 if(stream){
93 set_need_format_setup(stream);
94 for(rawno = 1L; rawno <= stream->nmsgs; rawno++)
95 clear_index_cache_ent(stream, rawno, flags | IC_USE_RAW_MSGNO);
100 void
101 clear_index_cache_for_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap)
103 unsigned long msgno;
105 if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
106 return;
108 msgno = mn_raw2m(msgmap, thrd->rawno);
110 clear_index_cache_ent(stream, msgno, 0);
112 if(thrd->next)
113 clear_index_cache_for_thread(stream, fetch_thread(stream, thrd->next),
114 msgmap);
116 if(thrd->branch)
117 clear_index_cache_for_thread(stream, fetch_thread(stream, thrd->branch),
118 msgmap);
122 void
123 clear_icache_flags(MAILSTREAM *stream)
125 sp_set_icache_flags(stream, 0);
129 void
130 set_need_format_setup(MAILSTREAM *stream)
132 sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_NEED_FORMAT_SETUP);
137 need_format_setup(MAILSTREAM *stream)
139 return(sp_icache_flags(stream) & SP_NEED_FORMAT_SETUP);
143 void
144 set_format_includes_msgno(MAILSTREAM *stream)
146 sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_FORMAT_INCLUDES_MSGNO);
151 format_includes_msgno(MAILSTREAM *stream)
153 return(sp_icache_flags(stream) & SP_FORMAT_INCLUDES_MSGNO);
157 void
158 set_format_includes_smartdate(MAILSTREAM *stream)
160 sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_FORMAT_INCLUDES_SMARTDATE);
165 format_includes_smartdate(MAILSTREAM *stream)
167 return(sp_icache_flags(stream) & SP_FORMAT_INCLUDES_SMARTDATE);
172 * Almost a free_ice, but we leave the memory there for the ICE_S.
174 void
175 clear_ice(ICE_S **ice)
177 if(ice && *ice){
178 free_ifield(&(*ice)->ifield);
180 if((*ice)->linecolor)
181 free_color_pair(&(*ice)->linecolor);
183 if((*ice)->tice)
184 clear_ice(&(*ice)->tice);
186 /* do these one at a time so we don't clear tice */
187 (*ice)->color_lookup_done = 0;
188 (*ice)->to_us = 0;
189 (*ice)->cc_us = 0;
190 (*ice)->plus = 0;
191 (*ice)->id = 0;
196 void
197 free_ice(ICE_S **ice)
199 if(ice && *ice){
201 if((*ice)->tice)
202 free_ice(&(*ice)->tice);
204 clear_ice(ice);
206 fs_give((void **) ice);
211 void
212 free_ifield(IFIELD_S **ifld)
214 if(ifld && *ifld){
215 free_ifield(&(*ifld)->next);
216 free_ielem(&(*ifld)->ielem);
217 fs_give((void **) ifld);
222 void
223 free_ielem(IELEM_S **il)
225 if(il && *il){
226 free_ielem(&(*il)->next);
227 if((*il)->freeprintf && (*il)->print_format)
228 fs_give((void **) &(*il)->print_format);
230 if((*il)->freecolor && (*il)->color)
231 free_color_pair(&(*il)->color);
233 if((*il)->freedata && (*il)->data)
234 fs_give((void **) &(*il)->data);
236 fs_give((void **) il);
242 * Returns the index cache entry associated with this message.
243 * If it doesn't already exist it is instantiated.
245 ICE_S *
246 fetch_ice(MAILSTREAM *stream, long unsigned int rawno)
248 PINELT_S **peltp;
249 MESSAGECACHE *mc;
251 if(!stream || rawno < 1L || rawno > stream->nmsgs)
252 return NULL;
254 if(!(mc = mail_elt(stream, rawno)))
255 return NULL;
258 * any private elt data yet?
260 if(*(peltp = (PINELT_S **) &mc->sparep) == NULL){
261 *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
262 memset(*peltp, 0, sizeof(PINELT_S));
265 if((*peltp)->ice == NULL)
266 (*peltp)->ice = new_ice();
268 if(need_format_setup(stream) && setup_header_widths)
269 (*setup_header_widths)(stream);
271 return((*peltp)->ice);
275 ICE_S **
276 fetch_ice_ptr(MAILSTREAM *stream, long unsigned int rawno)
278 PINELT_S **peltp;
279 MESSAGECACHE *mc;
281 if(!stream || rawno < 1L || rawno > stream->nmsgs)
282 return NULL;
284 if(!(mc = mail_elt(stream, rawno)))
285 return NULL;
288 * any private elt data yet?
290 if(*(peltp = (PINELT_S **) &mc->sparep) == NULL){
291 *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
292 memset(*peltp, 0, sizeof(PINELT_S));
295 return(&(*peltp)->ice);
299 ICE_S *
300 copy_ice(ICE_S *src)
302 ICE_S *head = NULL;
304 if(src){
305 head = new_ice();
307 head->color_lookup_done = src->color_lookup_done;
308 head->widths_done = src->widths_done;
309 head->to_us = src->to_us;
310 head->cc_us = src->cc_us;
311 head->plus = src->plus;
312 head->id = src->id;
314 if(src->linecolor)
315 head->linecolor = new_color_pair(src->linecolor->fg, src->linecolor->bg);
317 if(src->ifield)
318 head->ifield = copy_ifield(src->ifield);
320 if(src->tice)
321 head->tice = copy_ice(src->tice);
324 return(head);
328 IFIELD_S *
329 copy_ifield(IFIELD_S *src)
331 IFIELD_S *head = NULL;
333 if(src){
334 head = new_ifield(NULL);
336 if(src->next)
337 head->next = copy_ifield(src->next);
339 head->ctype = src->ctype;
340 head->width = src->width;
341 head->leftadj = src->leftadj;
343 if(src->ielem)
344 head->ielem = copy_ielem(src->ielem);
347 return(head);
351 IELEM_S *
352 copy_ielem(IELEM_S *src)
354 IELEM_S *head = NULL;
356 if(src){
357 head = new_ielem(NULL);
359 if(src->next)
360 head->next = copy_ielem(src->next);
362 head->type = src->type;
363 head->wid = src->wid;
365 if(src->color){
366 head->color = new_color_pair(src->color->fg, src->color->bg);
367 head->freecolor = 1;
370 if(src->data){
371 head->data = cpystr(src->data);
372 head->datalen = strlen(head->data);
373 head->freedata = 1;
376 if(src->print_format){
377 head->print_format = cpystr(src->print_format);
378 head->freeprintf = strlen(head->print_format) + 1;
382 return(head);
386 ICE_S *
387 new_ice(void)
389 ICE_S *ice;
391 ice = (ICE_S *) fs_get(sizeof(ICE_S));
392 memset(ice, 0, sizeof(ICE_S));
393 return(ice);
398 * Create new IFIELD_S, zero it out, and insert it at end.
400 IFIELD_S *
401 new_ifield(IFIELD_S **ifieldp)
403 IFIELD_S *ifield, *ip;
405 ifield = (IFIELD_S *) fs_get(sizeof(*ifield));
406 memset(ifield, 0, sizeof(*ifield));
408 if(ifieldp){
409 ip = *ifieldp;
410 if(ip){
411 for(ip = (*ifieldp); ip && ip->next; ip = ip->next)
414 ip->next = ifield;
416 else
417 *ifieldp = ifield;
420 return(ifield);
425 * Create new IELEM_S, zero it out, and insert it at end.
427 IELEM_S *
428 new_ielem(IELEM_S **ielemp)
430 IELEM_S *ielem, *ip;
432 ielem = (IELEM_S *) fs_get(sizeof(*ielem));
433 memset(ielem, 0, sizeof(*ielem));
435 if(ielemp){
436 ip = *ielemp;
437 if(ip){
438 for(ip = (*ielemp); ip && ip->next; ip = ip->next)
441 ip->next = ielem;
443 else
444 *ielemp = ielem;
447 return(ielem);