summaryrefslogtreecommitdiff
path: root/pith/icache.c
diff options
context:
space:
mode:
Diffstat (limited to 'pith/icache.c')
-rw-r--r--pith/icache.c452
1 files changed, 452 insertions, 0 deletions
diff --git a/pith/icache.c b/pith/icache.c
new file mode 100644
index 00000000..fc2a1eb8
--- /dev/null
+++ b/pith/icache.c
@@ -0,0 +1,452 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: icache.c 874 2007-12-15 02:51:06Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include "../pith/headers.h"
+#include "../pith/icache.h"
+#include "../pith/mailindx.h"
+#include "../pith/flag.h"
+#include "../pith/msgno.h"
+#include "../pith/status.h"
+#include "../pith/pineelt.h"
+
+/*
+ * Internal prototypes
+ */
+
+
+/*
+ * * * * Index entry cache manager * * *
+ */
+
+
+/*
+ * Erase a particular entry in the cache.
+ */
+void
+clear_index_cache_ent(MAILSTREAM *stream, long int msgno, unsigned int flags)
+{
+ long rawno = -1L;
+ PINELT_S **peltp;
+ MESSAGECACHE *mc;
+
+ if(stream){
+ if(flags && IC_USE_RAW_MSGNO)
+ rawno = msgno;
+ else
+ rawno = mn_m2raw(sp_msgmap(stream), msgno);
+
+ if(rawno > 0L && rawno <= stream->nmsgs){
+ mc = mail_elt(stream, rawno);
+ if(mc && mc->sparep){
+ peltp = (PINELT_S **) &mc->sparep;
+ if((*peltp)->ice){
+ /*
+ * This is intended to be a lightweight reset of
+ * just the widths and print_format strings. For example,
+ * the width of the screen changed and nothing else.
+ * We simply unset the widths_done bit and it
+ * is up to the drawer to free and recalculate the
+ * print_format strings and to reset the widths.
+ *
+ * The else case is a clear of the entire cache entry
+ * leaving behind only the empty structure.
+ */
+ if(flags & IC_CLEAR_WIDTHS_DONE){
+ (*peltp)->ice->widths_done = 0;
+
+ /* also zero out hash value */
+ (*peltp)->ice->id = 0;
+
+ if((*peltp)->ice->tice){
+ (*peltp)->ice->tice->widths_done = 0;
+
+ /* also zero out hash value */
+ (*peltp)->ice->tice->id = 0;
+ }
+ }
+ else
+ clear_ice(&(*peltp)->ice);
+ }
+ }
+ }
+ }
+}
+
+
+void
+clear_index_cache(MAILSTREAM *stream, unsigned int flags)
+{
+ long rawno;
+
+ if(stream){
+ set_need_format_setup(stream);
+ for(rawno = 1L; rawno <= stream->nmsgs; rawno++)
+ clear_index_cache_ent(stream, rawno, flags | IC_USE_RAW_MSGNO);
+ }
+}
+
+
+void
+clear_index_cache_for_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap)
+{
+ unsigned long msgno;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return;
+
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+
+ clear_index_cache_ent(stream, msgno, 0);
+
+ if(thrd->next)
+ clear_index_cache_for_thread(stream, fetch_thread(stream, thrd->next),
+ msgmap);
+
+ if(thrd->branch)
+ clear_index_cache_for_thread(stream, fetch_thread(stream, thrd->branch),
+ msgmap);
+}
+
+
+void
+clear_icache_flags(MAILSTREAM *stream)
+{
+ sp_set_icache_flags(stream, 0);
+}
+
+
+void
+set_need_format_setup(MAILSTREAM *stream)
+{
+ sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_NEED_FORMAT_SETUP);
+}
+
+
+int
+need_format_setup(MAILSTREAM *stream)
+{
+ return(sp_icache_flags(stream) & SP_NEED_FORMAT_SETUP);
+}
+
+
+void
+set_format_includes_msgno(MAILSTREAM *stream)
+{
+ sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_FORMAT_INCLUDES_MSGNO);
+}
+
+
+int
+format_includes_msgno(MAILSTREAM *stream)
+{
+ return(sp_icache_flags(stream) & SP_FORMAT_INCLUDES_MSGNO);
+}
+
+
+void
+set_format_includes_smartdate(MAILSTREAM *stream)
+{
+ sp_set_icache_flags(stream, sp_icache_flags(stream) | SP_FORMAT_INCLUDES_SMARTDATE);
+}
+
+
+int
+format_includes_smartdate(MAILSTREAM *stream)
+{
+ return(sp_icache_flags(stream) & SP_FORMAT_INCLUDES_SMARTDATE);
+}
+
+
+/*
+ * Almost a free_ice, but we leave the memory there for the ICE_S.
+ */
+void
+clear_ice(ICE_S **ice)
+{
+ if(ice && *ice){
+ free_ifield(&(*ice)->ifield);
+
+ if((*ice)->linecolor)
+ free_color_pair(&(*ice)->linecolor);
+
+ if((*ice)->tice)
+ clear_ice(&(*ice)->tice);
+
+ /* do these one at a time so we don't clear tice */
+ (*ice)->color_lookup_done = 0;
+ (*ice)->to_us = 0;
+ (*ice)->cc_us = 0;
+ (*ice)->plus = 0;
+ (*ice)->id = 0;
+ }
+}
+
+
+void
+free_ice(ICE_S **ice)
+{
+ if(ice && *ice){
+
+ if((*ice)->tice)
+ free_ice(&(*ice)->tice);
+
+ clear_ice(ice);
+
+ fs_give((void **) ice);
+ }
+}
+
+
+void
+free_ifield(IFIELD_S **ifld)
+{
+ if(ifld && *ifld){
+ free_ifield(&(*ifld)->next);
+ free_ielem(&(*ifld)->ielem);
+ fs_give((void **) ifld);
+ }
+}
+
+
+void
+free_ielem(IELEM_S **il)
+{
+ if(il && *il){
+ free_ielem(&(*il)->next);
+ if((*il)->freeprintf && (*il)->print_format)
+ fs_give((void **) &(*il)->print_format);
+
+ if((*il)->freecolor && (*il)->color)
+ free_color_pair(&(*il)->color);
+
+ if((*il)->freedata && (*il)->data)
+ fs_give((void **) &(*il)->data);
+
+ fs_give((void **) il);
+ }
+}
+
+
+/*
+ * Returns the index cache entry associated with this message.
+ * If it doesn't already exist it is instantiated.
+ */
+ICE_S *
+fetch_ice(MAILSTREAM *stream, long unsigned int rawno)
+{
+ PINELT_S **peltp;
+ MESSAGECACHE *mc;
+
+ if(!stream || rawno < 1L || rawno > stream->nmsgs)
+ return NULL;
+
+ if(!(mc = mail_elt(stream, rawno)))
+ return NULL;
+
+ /*
+ * any private elt data yet?
+ */
+ if((*(peltp = (PINELT_S **) &mc->sparep) == NULL)){
+ *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
+ memset(*peltp, 0, sizeof(PINELT_S));
+ }
+
+ if((*peltp)->ice == NULL)
+ (*peltp)->ice = new_ice();
+
+ if(need_format_setup(stream) && setup_header_widths)
+ (*setup_header_widths)(stream);
+
+ return((*peltp)->ice);
+}
+
+
+ICE_S **
+fetch_ice_ptr(MAILSTREAM *stream, long unsigned int rawno)
+{
+ PINELT_S **peltp;
+ MESSAGECACHE *mc;
+
+ if(!stream || rawno < 1L || rawno > stream->nmsgs)
+ return NULL;
+
+ if(!(mc = mail_elt(stream, rawno)))
+ return NULL;
+
+ /*
+ * any private elt data yet?
+ */
+ if((*(peltp = (PINELT_S **) &mc->sparep) == NULL)){
+ *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
+ memset(*peltp, 0, sizeof(PINELT_S));
+ }
+
+ return(&(*peltp)->ice);
+}
+
+
+ICE_S *
+copy_ice(ICE_S *src)
+{
+ ICE_S *head = NULL;
+
+ if(src){
+ head = new_ice();
+
+ head->color_lookup_done = src->color_lookup_done;
+ head->widths_done = src->widths_done;
+ head->to_us = src->to_us;
+ head->cc_us = src->cc_us;
+ head->plus = src->plus;
+ head->id = src->id;
+
+ if(src->linecolor)
+ head->linecolor = new_color_pair(src->linecolor->fg, src->linecolor->bg);
+
+ if(src->ifield)
+ head->ifield = copy_ifield(src->ifield);
+
+ if(src->tice)
+ head->tice = copy_ice(src->tice);
+ }
+
+ return(head);
+}
+
+
+IFIELD_S *
+copy_ifield(IFIELD_S *src)
+{
+ IFIELD_S *head = NULL;
+
+ if(src){
+ head = new_ifield(NULL);
+
+ if(src->next)
+ head->next = copy_ifield(src->next);
+
+ head->ctype = src->ctype;
+ head->width = src->width;
+ head->leftadj = src->leftadj;
+
+ if(src->ielem)
+ head->ielem = copy_ielem(src->ielem);
+ }
+
+ return(head);
+}
+
+
+IELEM_S *
+copy_ielem(IELEM_S *src)
+{
+ IELEM_S *head = NULL;
+
+ if(src){
+ head = new_ielem(NULL);
+
+ if(src->next)
+ head->next = copy_ielem(src->next);
+
+ head->type = src->type;
+ head->wid = src->wid;
+
+ if(src->color){
+ head->color = new_color_pair(src->color->fg, src->color->bg);
+ head->freecolor = 1;
+ }
+
+ if(src->data){
+ head->data = cpystr(src->data);
+ head->datalen = strlen(head->data);
+ head->freedata = 1;
+ }
+
+ if(src->print_format){
+ head->print_format = cpystr(src->print_format);
+ head->freeprintf = strlen(head->print_format) + 1;
+ }
+ }
+
+ return(head);
+}
+
+
+ICE_S *
+new_ice(void)
+{
+ ICE_S *ice;
+
+ ice = (ICE_S *) fs_get(sizeof(ICE_S));
+ memset(ice, 0, sizeof(ICE_S));
+ return(ice);
+}
+
+
+/*
+ * Create new IFIELD_S, zero it out, and insert it at end.
+ */
+IFIELD_S *
+new_ifield(IFIELD_S **ifieldp)
+{
+ IFIELD_S *ifield, *ip;
+
+ ifield = (IFIELD_S *) fs_get(sizeof(*ifield));
+ memset(ifield, 0, sizeof(*ifield));
+
+ if(ifieldp){
+ ip = *ifieldp;
+ if(ip){
+ for(ip = (*ifieldp); ip && ip->next; ip = ip->next)
+ ;
+
+ ip->next = ifield;
+ }
+ else
+ *ifieldp = ifield;
+ }
+
+ return(ifield);
+}
+
+
+/*
+ * Create new IELEM_S, zero it out, and insert it at end.
+ */
+IELEM_S *
+new_ielem(IELEM_S **ielemp)
+{
+ IELEM_S *ielem, *ip;
+
+ ielem = (IELEM_S *) fs_get(sizeof(*ielem));
+ memset(ielem, 0, sizeof(*ielem));
+
+ if(ielemp){
+ ip = *ielemp;
+ if(ip){
+ for(ip = (*ielemp); ip && ip->next; ip = ip->next)
+ ;
+
+ ip->next = ielem;
+ }
+ else
+ *ielemp = ielem;
+ }
+
+ return(ielem);
+}