This is MailboxInspector.m in view mode; [Download] [Up]
/*+++* * title: MailboxInspector.m * abstract: NEXTSTEP Workspace Manager Inspector for Mail.app ".mbox" files. * author: T.R.Hageman, The Netherlands * created: May 1996 * modified: (see RCS Log at end) * copyleft: * * Copyright (C) 1996,1997 Tom R. Hageman. * * This 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 software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * description: * *---*/ static const char *const RCSid = ((void)&RCSid, /* to avoid `unused' warning. */ "@(#)MailboxInspector.m,v 1.5 1997/05/10 15:22:21 tom Exp"); #define VERSION "1.1" #ifndef DEBUG # define DEBUG 0 #endif #import "MailboxInspector.h" #include <string.h> #include <stdlib.h> #include <stdio.h> #include "mailtoc.h" // Localized strings #define OPENBUTTON NXLocalizedStringFromTableInBundle(NULL, bundle, "Open", NULL, okbutton label) #define NO_NEW_MESSAGES NXLocalizedStringFromTableInBundle(NULL, bundle, "", NULL, newMailTextField: No new messages) #define ONE_NEW_MESSAGE NXLocalizedStringFromTableInBundle(NULL, bundle, "1 new message", NULL, newMailTextField: 1 new message) #define N_NEW_MESSAGES NXLocalizedStringFromTableInBundle(NULL, bundle, "%lu new messages", NULL, newMailTextField: %lu new messages format string) #define CANNOT_READ_TOC NXLocalizedStringFromTableInBundle(NULL, bundle, "Unable to read Table of Contents", NULL, newMailTextField: Cannot read Table of Contents) #define INDEX_SIZE NXLocalizedStringFromTableInBundle(NULL, bundle, "(index: %s)", NULL, indexSizeField: (index: %s)) #define TOC_SIZE NXLocalizedStringFromTableInBundle(NULL, bundle, "(table of contents: %s)", NULL, tocSizeField: (table of contents: %s)) #define KBYTES NXLocalizedStringFromTableInBundle(NULL, bundle, "KB", NULL, KiloBytes) #define MBYTES NXLocalizedStringFromTableInBundle(NULL, bundle, "MB", NULL, MegaBytes) #define LOCALIZE(s) NXLoadLocalized\ StringFromTableInBundle(NULL, bundle, s, NULL) // (line continuation to keep "genstrings" from breaking.) @implementation MailboxInspector - initWithNibName:(const char *)nibname { char path[MAXPATHLEN+1]; bundle = [NXBundle bundleForClass:[self class]]; if ([bundle getPath:path forResource:nibname ofType:"nib"] && [NXApp loadNibFile:path owner:self]) { // Set version field. [inspectorVersionField setStringValue:VERSION]; } else { fprintf(stderr, "Couldn't load %s.nib\n", nibname); [self free]; self = nil; } return self; } + new { static MailboxInspector *instance; if (instance == nil) { instance = [[super new] initWithNibName:[self name]]; } return instance; } - showInfo:sender { if (infoPanel == nil) { char path[MAXPATHLEN+1]; if ([bundle getPath:path forResource:"Info" ofType:"nib"] && [NXApp loadNibFile:path owner:self]) { [infoVersionField setStringValue:[inspectorVersionField stringValue]]; } } [infoPanel makeKeyAndOrderFront:sender]; return self; } - revert:sender { [super revert:sender]; if ([self selectionCount] != 1) { return nil; } else { char path[MAXPATHLEN+1]; [mailbox free]; [self selectionPathsInto:path separator:'\0']; if (!(mailbox = [[NXBundle allocFromZone:[self zone]] initForDirectory:path])) { return nil; } if ([self shouldLoad]) { [self load]; } } [[[self okButton] setTitle:OPENBUTTON] setEnabled:YES]; return self; } - ok:sender { [self perform:@selector(open:) with:sender afterDelay:0 cancelPrevious:NO]; [super ok:sender]; return self; } - load { unsigned long counts[NUMTAGS] = {0}; unsigned long sizes[NUMTAGS] = {0}; unsigned long attachCounts[NUMTAGS] = {0}; unsigned long attachSizes[NUMTAGS] = {0}; BOOL indexed; unsigned long indexSize; unsigned long tocSize; BOOL valid = FALSE; char path[MAXPATHLEN+1]; char sizeBuf[20]; FILE *tocf; int tag; /* Quick hack; knows about *.mbox internals. A more OO solution would be to introduce a MailBoxSummary object that does the dirty work, and have us query it. */ if ((tocf = fopen([self getPath:path forFile:FILE_TOC], "rb")) != NULL) { struct table_of_contents_header *th; if ((th = get_table_of_contents_header(tocf, NO)) != NULL) { int msgCount = th->num_msgs; free(th); valid = TRUE; // Tally read, new and deleted messages. while (--msgCount >= 0) { struct message_index *mi; long size, attachSize; if ((mi = get_message_index(tocf)) == NULL) { valid = FALSE; break; } switch (mi->status) { case '*': tag = TAG_NEW; break; case 'd': case 'D': tag = TAG_DELETED; break; case 'u': case 'U': tag = TAG_UNREAD; break; case '+': tag = TAG_FLAGGED; break; default: tag = TAG_READ; break; } size = mi->mes_length; if ((attachSize = message_attachsize(mi)) > 0) { attachCounts[tag]++; attachSizes[tag] += attachSize; attachCounts[TAG_TOTAL]++; attachSizes[TAG_TOTAL] += attachSize; size += attachSize; } counts[tag]++; sizes[tag] += size; counts[TAG_TOTAL]++; sizes[TAG_TOTAL] += size; free(mi); } } fclose(tocf); } /* Quick&dirty hack to determine if index store file exists. */ indexed = (stats[STAT_INDEX].st_ino != 0); indexSize = stats[STAT_INDEX].st_size; #if DEBUG & 4 fprintf(stderr, "MailboxInspector: indexed = %d\n", indexed); #endif tocSize = stats[STAT_TOC].st_size; /* Fill in the inspector fields. */ [[self window] disableFlushWindow]; [indexTagButton setState:indexed]; [newMailIconButton setState:(valid && counts[TAG_NEW] > 0)]; [newMailTextField setStringValue: (valid ? (counts[TAG_NEW] == 0 ? NO_NEW_MESSAGES : counts[TAG_NEW] == 1 ? ONE_NEW_MESSAGE : (sprintf(path, N_NEW_MESSAGES, counts[TAG_NEW]), path)) : CANNOT_READ_TOC)]; for (tag = 0; tag < NUMTAGS; tag++) { #define FORMATCOUNT(count) \ (valid ? ((count) ? (sprintf(sizeBuf, "%lu", (count)), sizeBuf) : \ "Ð") : "?") #define FORMATSIZE(size) \ (valid ? [self formatSize:(size) inBuf:sizeBuf] : "") [[messageCountMatrix findCellWithTag:tag] setStringValue:FORMATCOUNT(counts[tag])]; [[messageSizeMatrix findCellWithTag:tag] setStringValue:FORMATSIZE(sizes[tag])]; [[attachmentCountMatrix findCellWithTag:tag] setStringValue:FORMATCOUNT(attachCounts[tag])]; [[attachmentSizeMatrix findCellWithTag:tag] setStringValue:FORMATSIZE(attachSizes[tag])]; #undef FORMATCOUNT #undef FORMATSIZE } [indexSizeField setStringValue: (indexed ? (sprintf(path, INDEX_SIZE, [self formatSize:indexSize inBuf:sizeBuf]), path) : "")]; [tocSizeField setStringValue: (sprintf(path, TOC_SIZE, [self formatSize:tocSize inBuf:sizeBuf]), path)]; [[self window] reenableFlushWindow]; [[self window] flushWindowIfNeeded]; return self; } #define STAT_EQ(s1, s2) ((s1)->st_ino == (s2)->st_ino && \ (s1)->st_dev == (s2)->st_dev && \ (s1)->st_mtime == (s2)->st_mtime && \ (s1)->st_size == (s2)->st_size) - (BOOL)shouldLoad { char path[MAXPATHLEN+1]; struct stat newstats[NUMSTATS]; static const char * const filesToStat[NUMSTATS] = { FILESTOSTAT }; BOOL result = NO; int i; for (i = 0; i < NUMSTATS; i++) { memset(&newstats[i], 0, sizeof(struct stat)); stat([self getPath:path forFile:filesToStat[i]], &newstats[i]); if (!STAT_EQ(&newstats[i], &stats[i])) { result = YES; ///break; // NOT!!! must stat all for accurate cache. } stats[i] = newstats[i]; } return result; } // Support methods - (const char *)getPath:(char *)buf forFile:(const char *)file { sprintf(buf, "%s/%s", [mailbox directory], file); #if DEBUG & 2 fprintf(stderr, "MailboxInspector: file=\"%s\" path=\"%s\"\n", file, buf); #endif return buf; } - (const char *)formatSize:(unsigned long)size inBuf:(char *)buf { #define KB 1024 #define MB (KB * 1024) if (size == 0) { strcpy(buf, ""); } else if (size < 1000*KB - KB/2) { sprintf(buf, "%.*f%s", //(size < 10*KB - KB/2 ? 2 : size < 100*KB - KB/2 ? 1 : 0), (size < 10*KB - KB/2 ? 1 : 0), (double) size / KB, KBYTES); } else { sprintf(buf, "%.*f%s", //(size < 10*MB - MB/2 ? 2 : size < 100*MB - MB/2 ? 1 : 0), (size < 10*MB - MB/2 ? 1 : 0), (double) size / MB, MBYTES); } return buf; #undef KB #undef MB } static void openInWorkspace(const char *filename) { // Indirect approach to circumvent Workspace deadlock/timeout. char command[14+3*MAXPATHLEN+1]; const char *s; char *d = command; for (s = "exec open '"; *s; ) *d++ = *s++; // Escape single quote characters. for (s = filename; *s; ) { if ((*d++ = *s++) == '\'') { *d++ = '\\', *d++ = '\'', *d++ = '\''; } } for (s = "'&"; *d++ = *s++; ) ; system(command); } - open:sender { openInWorkspace([mailbox directory]); return self; } @end // MailboxInspector //====================================================================== // MailboxInspector.m,v // Revision 1.5 1997/05/10 15:22:21 tom // MailboxInspector: // (tocSizeField): new outlet. // (VERSION): bumped to 1.1. // (TOC_SIZE): new localizable string. // (LOCALIZE): hack to keep "genstrings" from breaking. // (-load): show toc size. // // Makefile.preamble: // (GENSTRINGS,LANGUAGE_DIRECTORIES): new variables. // // Makefile.postamble: // (clean::,resources::,genstrings:): new targets. // // README.rtf: // - updated for 1.1. // // Revision 1.4 1997/04/19 18:14:56 tom // (VERSION): upped to 1.0. // (-load): adapt to mailtoc API changes. // // Revision 1.3 1996/06/27 22:55:52 tom // Add sccs `what' marker in ident. // // Revision 1.2 1996/06/27 20:04:40 tom // (VERSION): bumped to 0.9. // (INDEX_SIZE): new localizable. // (-load): show size of index store. // // Revision 1.1 1996/06/26 14:40:42 tom // Initial revision // //======================================================================
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.