* Improvements to the pico manual as well as on the code that displays
[alpine.git] / pith / icache.c
blob1b27d39b0dae147cb04e47d59390dc6ebdafac1a
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: icache.c 874 2007-12-15 02:51:06Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2013-2019 Eduardo Chappa
8 * Copyright 2006-2007 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 #include "../pith/headers.h"
20 #include "../pith/icache.h"
21 #include "../pith/mailindx.h"
22 #include "../pith/flag.h"
23 #include "../pith/msgno.h"
24 #include "../pith/status.h"
25 #include "../pith/pineelt.h"
28 * Internal prototypes
33 * * * * Index entry cache manager * * *
38 * Erase a particular entry in the cache.
40 void
41 clear_index_cache_ent(MAILSTREAM *stream, long int msgno, unsigned int flags)
43 long rawno = -1L;
44 PINELT_S **peltp;
45 MESSAGECACHE *mc;
47 if(stream){
48 if(flags & IC_USE_RAW_MSGNO)
49 rawno = msgno;
50 else
51 rawno = mn_m2raw(sp_msgmap(stream), msgno);
53 if(rawno > 0L && rawno <= stream->nmsgs){
54 mc = mail_elt(stream, rawno);
55 if(mc && mc->sparep){
56 peltp = (PINELT_S **) &mc->sparep;
57 if((*peltp)->ice){
59 * This is intended to be a lightweight reset of
60 * just the widths and print_format strings. For example,
61 * the width of the screen changed and nothing else.
62 * We simply unset the widths_done bit and it
63 * is up to the drawer to free and recalculate the
64 * print_format strings and to reset the widths.
66 * The else case is a clear of the entire cache entry
67 * leaving behind only the empty structure.
69 if(flags & IC_CLEAR_WIDTHS_DONE){
70 (*peltp)->ice->widths_done = 0;
72 /* also zero out hash value */
73 (*peltp)->ice->id = 0;
75 if((*peltp)->ice->tice){
76 (*peltp)->ice->tice->widths_done = 0;
78 /* also zero out hash value */
79 (*peltp)->ice->tice->id = 0;
82 else
83 clear_ice(&(*peltp)->ice);
91 void
92 clear_index_cache(MAILSTREAM *stream, unsigned int flags)
94 long rawno;
96 if(stream){
97 set_need_format_setup(stream);
98 for(rawno = 1L; rawno <= stream->nmsgs; rawno++)
99 clear_index_cache_ent(stream, rawno, flags | IC_USE_RAW_MSGNO);
104 void
105 clear_index_cache_for_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap)
107 unsigned long msgno;
109 if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
110 return;
112 msgno = mn_raw2m(msgmap, thrd->rawno);
114 clear_index_cache_ent(stream, msgno, 0);
116 if(thrd->next)
117 clear_index_cache_for_thread(stream, fetch_thread(stream, thrd->next),
118 msgmap);
120 if(thrd->branch)
121 clear_index_cache_for_thread(stream, fetch_thread(stream, thrd->branch),
122 msgmap);
126 void
127 clear_icache_flags(MAILSTREAM *stream)
129 sp_set_icache_flags(stream, 0);
133 void
134 set_need_format_setup(MAILSTREAM *stream)
136 sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_NEED_FORMAT_SETUP);
141 need_format_setup(MAILSTREAM *stream)
143 return(sp_icache_flags(stream) & SP_NEED_FORMAT_SETUP);
147 void
148 set_format_includes_msgno(MAILSTREAM *stream)
150 sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_FORMAT_INCLUDES_MSGNO);
155 format_includes_msgno(MAILSTREAM *stream)
157 return(sp_icache_flags(stream) & SP_FORMAT_INCLUDES_MSGNO);
161 void
162 set_format_includes_smartdate(MAILSTREAM *stream)
164 sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_FORMAT_INCLUDES_SMARTDATE);
169 format_includes_smartdate(MAILSTREAM *stream)
171 return(sp_icache_flags(stream) & SP_FORMAT_INCLUDES_SMARTDATE);
176 * Almost a free_ice, but we leave the memory there for the ICE_S.
178 void
179 clear_ice(ICE_S **ice)
181 if(ice && *ice){
182 free_ifield(&(*ice)->ifield);
184 if((*ice)->linecolor)
185 free_color_pair(&(*ice)->linecolor);
187 if((*ice)->tice)
188 clear_ice(&(*ice)->tice);
190 /* do these one at a time so we don't clear tice */
191 (*ice)->color_lookup_done = 0;
192 (*ice)->to_us = 0;
193 (*ice)->cc_us = 0;
194 (*ice)->plus = 0;
195 (*ice)->id = 0;
200 void
201 free_ice(ICE_S **ice)
203 if(ice && *ice){
205 if((*ice)->tice)
206 free_ice(&(*ice)->tice);
208 clear_ice(ice);
210 fs_give((void **) ice);
215 void
216 free_ifield(IFIELD_S **ifld)
218 if(ifld && *ifld){
219 free_ifield(&(*ifld)->next);
220 free_ielem(&(*ifld)->ielem);
221 fs_give((void **) ifld);
226 void
227 free_ielem(IELEM_S **il)
229 if(il && *il){
230 free_ielem(&(*il)->next);
231 if((*il)->freeprintf && (*il)->print_format)
232 fs_give((void **) &(*il)->print_format);
234 if((*il)->freecolor && (*il)->color)
235 free_color_pair(&(*il)->color);
237 if((*il)->freedata && (*il)->data)
238 fs_give((void **) &(*il)->data);
240 fs_give((void **) il);
246 * Returns the index cache entry associated with this message.
247 * If it doesn't already exist it is instantiated.
249 ICE_S *
250 fetch_ice(MAILSTREAM *stream, long unsigned int rawno)
252 PINELT_S **peltp;
253 MESSAGECACHE *mc;
255 if(!stream || rawno < 1L || rawno > stream->nmsgs)
256 return NULL;
258 if(!(mc = mail_elt(stream, rawno)))
259 return NULL;
262 * any private elt data yet?
264 if(*(peltp = (PINELT_S **) &mc->sparep) == NULL){
265 *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
266 memset(*peltp, 0, sizeof(PINELT_S));
269 if((*peltp)->ice == NULL)
270 (*peltp)->ice = new_ice();
272 if(need_format_setup(stream) && setup_header_widths)
273 (*setup_header_widths)(stream);
275 return((*peltp)->ice);
279 ICE_S **
280 fetch_ice_ptr(MAILSTREAM *stream, long unsigned int rawno)
282 PINELT_S **peltp;
283 MESSAGECACHE *mc;
285 if(!stream || rawno < 1L || rawno > stream->nmsgs)
286 return NULL;
288 if(!(mc = mail_elt(stream, rawno)))
289 return NULL;
292 * any private elt data yet?
294 if(*(peltp = (PINELT_S **) &mc->sparep) == NULL){
295 *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
296 memset(*peltp, 0, sizeof(PINELT_S));
299 return(&(*peltp)->ice);
303 ICE_S *
304 copy_ice(ICE_S *src)
306 ICE_S *head = NULL;
308 if(src){
309 head = new_ice();
311 head->color_lookup_done = src->color_lookup_done;
312 head->widths_done = src->widths_done;
313 head->to_us = src->to_us;
314 head->cc_us = src->cc_us;
315 head->plus = src->plus;
316 head->id = src->id;
318 if(src->linecolor)
319 head->linecolor = new_color_pair(src->linecolor->fg, src->linecolor->bg);
321 if(src->ifield)
322 head->ifield = copy_ifield(src->ifield);
324 if(src->tice)
325 head->tice = copy_ice(src->tice);
328 return(head);
332 IFIELD_S *
333 copy_ifield(IFIELD_S *src)
335 IFIELD_S *head = NULL;
337 if(src){
338 head = new_ifield(NULL);
340 if(src->next)
341 head->next = copy_ifield(src->next);
343 head->ctype = src->ctype;
344 head->width = src->width;
345 head->leftadj = src->leftadj;
347 if(src->ielem)
348 head->ielem = copy_ielem(src->ielem);
351 return(head);
355 IELEM_S *
356 copy_ielem(IELEM_S *src)
358 IELEM_S *head = NULL;
360 if(src){
361 head = new_ielem(NULL);
363 if(src->next)
364 head->next = copy_ielem(src->next);
366 head->type = src->type;
367 head->wid = src->wid;
369 if(src->color){
370 head->color = new_color_pair(src->color->fg, src->color->bg);
371 head->freecolor = 1;
374 if(src->data){
375 head->data = cpystr(src->data);
376 head->datalen = strlen(head->data);
377 head->freedata = 1;
380 if(src->print_format){
381 head->print_format = cpystr(src->print_format);
382 head->freeprintf = strlen(head->print_format) + 1;
386 return(head);
390 ICE_S *
391 new_ice(void)
393 ICE_S *ice;
395 ice = (ICE_S *) fs_get(sizeof(ICE_S));
396 memset(ice, 0, sizeof(ICE_S));
397 return(ice);
402 * Create new IFIELD_S, zero it out, and insert it at end.
404 IFIELD_S *
405 new_ifield(IFIELD_S **ifieldp)
407 IFIELD_S *ifield, *ip;
409 ifield = (IFIELD_S *) fs_get(sizeof(*ifield));
410 memset(ifield, 0, sizeof(*ifield));
412 if(ifieldp){
413 ip = *ifieldp;
414 if(ip){
415 for(ip = (*ifieldp); ip && ip->next; ip = ip->next)
418 ip->next = ifield;
420 else
421 *ifieldp = ifield;
424 return(ifield);
429 * Create new IELEM_S, zero it out, and insert it at end.
431 IELEM_S *
432 new_ielem(IELEM_S **ielemp)
434 IELEM_S *ielem, *ip;
436 ielem = (IELEM_S *) fs_get(sizeof(*ielem));
437 memset(ielem, 0, sizeof(*ielem));
439 if(ielemp){
440 ip = *ielemp;
441 if(ip){
442 for(ip = (*ielemp); ip && ip->next; ip = ip->next)
445 ip->next = ielem;
447 else
448 *ielemp = ielem;
451 return(ielem);