home *** CD-ROM | disk | FTP | other *** search
- /* thread.c -- Threads messages for easier perusal
- This file is part of Paperboy, an offline mail/newsreader for Windows
- Copyright (C) 1994 Michael H. Vartanian
- vart@clark.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "error.h"
- #include "soup.h"
- #include "structs.h"
- #include "msgs.h"
- #include "areas.h"
- #include "thread.h"
-
- struct llmsg ** hold;
-
- char * stripsubject (char * subject)
- {
- /* Remove leading RE: to get down to a basic subject */
- char * stripped;
- int replen; /* Cache length for performance (loop invariant)*/
-
- assert(subject!=NULL);
- stripped=subject;
-
- replen=strlen(REPLYSTR);
-
- while (_fstrnicmp(stripped,REPLYSTR,replen)==0)
- {
- stripped+=replen;
- }
-
- return stripped;
- }
-
-
-
- static int comparemsg (const void * m1, const void * m2)
- {
- struct llmsg * msg1, * msg2;
- struct llmsg ** p;
- time_t comp;
-
- p=NULL;
- msg1=NULL;
- msg2=NULL;
-
- assert(m1!=NULL);
- assert(m2!=NULL);
- if (m1==m2) return 0;
- p=(struct llmsg **)m1;
- msg1=(struct llmsg *)*p;
- p=(struct llmsg **)m2;
- msg2=(struct llmsg *)*p;
-
- /* I've had loads of trouble debugging this routine, can't you tell ? */
- assert(msg1!=NULL);
- assert(msg2!=NULL);
- if (msg1==msg2) return 0;
- assert(msg1->magic==MSGMAGIC);
- assert(msg2->magic==MSGMAGIC);
-
- comp=msg1->thread_idate - msg2->thread_idate;
-
- if (comp==0) /* Same thread, sort by date */
- {
- /* Always put base of thread first, regardless of date
- (our date routine farkles timezones) */
- assert(msg1->subject!=NULL);
- assert(msg2->subject!=NULL);
- if (stripsubject(msg1->subject)==msg1->subject) return -1;
- if (stripsubject(msg2->subject)==msg2->subject) return 1;
- comp=msg1->idate - msg2->idate;
- }
-
- if (comp>0) return 1;
- if (comp<0) return -1;
- return 0;
- }
-
- void ComputeBaseThreadDate(struct llareas * area)
- {
- /* For every message in this group, find the date of it's earliest
- thread.
- We're not terribly efficient in this routine O(n^2), but it works.
- */
- struct llmsg * cur, * inner;
- char * subj1, * subj2;
-
- assert(area!=NULL);
-
- cur=area->head;
-
- while (cur)
- {
- subj1=stripsubject(cur->subject);
- inner=area->head;
- while (inner)
- {
- subj2=stripsubject(inner->subject);
- if (!strcmp(subj1,subj2)) /* Base subjects are the same */
- {
- if (inner->idate < cur->thread_idate)
- cur->thread_idate=inner->idate;
- }
- inner=inner->next;
- }
- cur=cur->next;
- }
- }
-
-
-
- int DLLFUNC ThreadMsgs (int index)
- {
- struct llareas * area;
- struct llmsg * msghead;
- int nummsg;
- int pt;
-
- assert(index>0);
- assert(index<=GetNumAreas());
- area=findarea(index);
-
- assert(area!=NULL);
-
- ComputeBaseThreadDate(area);
-
- nummsg=GetNumMsgs(index);
-
- assert(nummsg!=0);
-
- /* We create an array large enough to hold pointers to all messages */
- hold=(struct llmsg **)malloc(sizeof(struct llmsg *) * nummsg);
- if (hold==NULL) return ERRMEM;
- memset(hold, 0, sizeof(struct llmsg *) * nummsg );
-
- /* Now stuff pointers to each element into the array */
- msghead=area->head;
- assert(msghead!=NULL);
-
- for (pt=0; pt<nummsg; pt++)
- {
- assert(msghead!=NULL);
- assert(msghead->magic==MSGMAGIC);
- hold[pt]=msghead;
- msghead=msghead->next;
- }
-
- assert(pt==nummsg);
-
- /* Sort the array */
- qsort(hold, nummsg, sizeof(struct llmsg *), comparemsg);
-
- /* Reassemble the linked list */
- area->head=hold[0];
-
- for (pt=0; pt<nummsg-1; pt++)
- hold[pt]->next=hold[pt+1];
-
- hold[pt]->next=NULL; /* End of list */
-
- free(hold);
- return 0;
- }
-