Commit 168bf470 authored by sullivan's avatar sullivan

Finished first cut at IFWebHistory implementation. All methods are implemented

	except the string-matching ones.

	* History.subproj/IFURIEntry.h:
	* History.subproj/IFURIEntry.m: (-[IFURIEntry initWithURL:title:image:comment:]),
	(-[IFURIEntry lastVisitedDate]), (-[IFURIEntry setModificationDate:]),
	(-[IFURIEntry setLastVisitedDate:]):
	Changed all NSDates to be NSCalendarDates.

	* History.subproj/IFWebHistory.h:
	* History.subproj/IFWebHistory.m: (-[IFWebHistory init]), (-[IFWebHistory
	dealloc]), (-[IFWebHistory sendEntriesChangedNotification]), (-[IFWebHistory
	addEntry:]), (-[IFWebHistory removeEntry:]), (-[IFWebHistory
	removeEntriesForDay:]), (-[IFWebHistory removeAllEntries]), (-[IFWebHistory
	orderedLastVisitedDays]), (-[IFWebHistory orderedEntriesLastVisitedOnDay:]),
	(-[IFWebHistory entriesWithAddressContainingString:]), (-[IFWebHistory
	entriesWithTitleOrAddressContainingString:]), (-[IFWebHistory containsURL:]):
	Implemented all IFWebHistory methods by calling through to IFWebHistoryPrivate object.
	Send a change notification each time the actual data changes. Removed all
	canned-data mechanisms.

	* History.subproj/IFWebHistoryPrivate.h:
	* History.subproj/IFWebHistoryPrivate.m: (-[IFWebHistoryPrivate init]),
	(-[IFWebHistoryPrivate dealloc]), (-[IFWebHistoryPrivate findIndex:forDay:]),
	(-[IFWebHistoryPrivate insertEntry:atDateIndex:]), (-[IFWebHistoryPrivate
	removeEntryForURLString:]), (-[IFWebHistoryPrivate addEntry:]),
	(-[IFWebHistoryPrivate removeEntry:]), (-[IFWebHistoryPrivate
	removeEntriesForDay:]), (-[IFWebHistoryPrivate removeAllEntries]),
	(-[IFWebHistoryPrivate orderedLastVisitedDays]), (-[IFWebHistoryPrivate
	orderedEntriesLastVisitedOnDay:]), (-[IFWebHistoryPrivate
	entriesWithAddressContainingString:]), (-[IFWebHistoryPrivate
	entriesWithTitleOrAddressContainingString:]), (-[IFWebHistoryPrivate
	containsURL:]):
	Implemented guts of history mechanism using a dictionary for URL lookup and
	a sorted array of dates with entries and a sorted array of sorted arrays of
	entries per date.

	* WebKit.pbproj/project.pbxproj: Updated for new files


    Made History window work.

	* BrowserDocument.h: whitespace changes only

	* BrowserDocument.m:
	(-[BrowserDocument addHistoryEntryForCurrentPage]): New method.
	(-[BrowserDocument locationChangeDone:forFrame:]): Call new method.
	(-[BrowserDocument locationChangeStartedForFrame:initiatedByUserEvent:]):
	Changed postNotification to use simpler userinfo-free version.

	* GlobalHistory.m:
	(+[GlobalHistory sharedGlobalHistory]): Register for changed notifications
	from IFWebHistory

	(-[GlobalHistory outlineView:objectValueForTableColumn:byItem:]): Use "today"
	for current date; "unknown title" for nil titles.
	(-[GlobalHistory historyIsEmpty]): New private convenience method.
	(-[GlobalHistory expandToday]): New method, expands the triangle for today's
	history entries if the first triangle is for today.
	(-[GlobalHistory updateButtons]),
	(-[GlobalHistory validateUserInterfaceItem:]): Use historyIsEmpty
	(-[GlobalHistory receivedEntriesChangedNotification:]): New method, react to
	change notification by reloading data and updating buttons.
	(-[GlobalHistory removeSelectedItems:]),
	(-[GlobalHistory removeAll:]):
	Implemented by calling IFWebHistory methods.
	(-[GlobalHistory showWindow:]): expand today's triangle

    * English.lproj/History.nib: Removed "completely fake" from History window title.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@645 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4e73a46d
2002-02-19 John Sullivan <sullivan@apple.com>
Finished first cut at IFWebHistory implementation. All methods are implemented
except the string-matching ones.
* History.subproj/IFURIEntry.h:
* History.subproj/IFURIEntry.m: (-[IFURIEntry initWithURL:title:image:comment:]),
(-[IFURIEntry lastVisitedDate]), (-[IFURIEntry setModificationDate:]),
(-[IFURIEntry setLastVisitedDate:]):
Changed all NSDates to be NSCalendarDates.
* History.subproj/IFWebHistory.h:
* History.subproj/IFWebHistory.m: (-[IFWebHistory init]), (-[IFWebHistory
dealloc]), (-[IFWebHistory sendEntriesChangedNotification]), (-[IFWebHistory
addEntry:]), (-[IFWebHistory removeEntry:]), (-[IFWebHistory
removeEntriesForDay:]), (-[IFWebHistory removeAllEntries]), (-[IFWebHistory
orderedLastVisitedDays]), (-[IFWebHistory orderedEntriesLastVisitedOnDay:]),
(-[IFWebHistory entriesWithAddressContainingString:]), (-[IFWebHistory
entriesWithTitleOrAddressContainingString:]), (-[IFWebHistory containsURL:]):
Implemented all IFWebHistory methods by calling through to IFWebHistoryPrivate object.
Send a change notification each time the actual data changes. Removed all
canned-data mechanisms.
* History.subproj/IFWebHistoryPrivate.h:
* History.subproj/IFWebHistoryPrivate.m: (-[IFWebHistoryPrivate init]),
(-[IFWebHistoryPrivate dealloc]), (-[IFWebHistoryPrivate findIndex:forDay:]),
(-[IFWebHistoryPrivate insertEntry:atDateIndex:]), (-[IFWebHistoryPrivate
removeEntryForURLString:]), (-[IFWebHistoryPrivate addEntry:]),
(-[IFWebHistoryPrivate removeEntry:]), (-[IFWebHistoryPrivate
removeEntriesForDay:]), (-[IFWebHistoryPrivate removeAllEntries]),
(-[IFWebHistoryPrivate orderedLastVisitedDays]), (-[IFWebHistoryPrivate
orderedEntriesLastVisitedOnDay:]), (-[IFWebHistoryPrivate
entriesWithAddressContainingString:]), (-[IFWebHistoryPrivate
entriesWithTitleOrAddressContainingString:]), (-[IFWebHistoryPrivate
containsURL:]):
Implemented guts of history mechanism using a dictionary for URL lookup and
a sorted array of dates with entries and a sorted array of sorted arrays of
entries per date.
* WebKit.pbproj/project.pbxproj: Updated for new files
2002-02-18 John Sullivan <sullivan@apple.com>
First piece of implementing IFWebHistory. None of the mutators do anything,
......
2002-02-19 John Sullivan <sullivan@apple.com>
Finished first cut at IFWebHistory implementation. All methods are implemented
except the string-matching ones.
* History.subproj/IFURIEntry.h:
* History.subproj/IFURIEntry.m: (-[IFURIEntry initWithURL:title:image:comment:]),
(-[IFURIEntry lastVisitedDate]), (-[IFURIEntry setModificationDate:]),
(-[IFURIEntry setLastVisitedDate:]):
Changed all NSDates to be NSCalendarDates.
* History.subproj/IFWebHistory.h:
* History.subproj/IFWebHistory.m: (-[IFWebHistory init]), (-[IFWebHistory
dealloc]), (-[IFWebHistory sendEntriesChangedNotification]), (-[IFWebHistory
addEntry:]), (-[IFWebHistory removeEntry:]), (-[IFWebHistory
removeEntriesForDay:]), (-[IFWebHistory removeAllEntries]), (-[IFWebHistory
orderedLastVisitedDays]), (-[IFWebHistory orderedEntriesLastVisitedOnDay:]),
(-[IFWebHistory entriesWithAddressContainingString:]), (-[IFWebHistory
entriesWithTitleOrAddressContainingString:]), (-[IFWebHistory containsURL:]):
Implemented all IFWebHistory methods by calling through to IFWebHistoryPrivate object.
Send a change notification each time the actual data changes. Removed all
canned-data mechanisms.
* History.subproj/IFWebHistoryPrivate.h:
* History.subproj/IFWebHistoryPrivate.m: (-[IFWebHistoryPrivate init]),
(-[IFWebHistoryPrivate dealloc]), (-[IFWebHistoryPrivate findIndex:forDay:]),
(-[IFWebHistoryPrivate insertEntry:atDateIndex:]), (-[IFWebHistoryPrivate
removeEntryForURLString:]), (-[IFWebHistoryPrivate addEntry:]),
(-[IFWebHistoryPrivate removeEntry:]), (-[IFWebHistoryPrivate
removeEntriesForDay:]), (-[IFWebHistoryPrivate removeAllEntries]),
(-[IFWebHistoryPrivate orderedLastVisitedDays]), (-[IFWebHistoryPrivate
orderedEntriesLastVisitedOnDay:]), (-[IFWebHistoryPrivate
entriesWithAddressContainingString:]), (-[IFWebHistoryPrivate
entriesWithTitleOrAddressContainingString:]), (-[IFWebHistoryPrivate
containsURL:]):
Implemented guts of history mechanism using a dictionary for URL lookup and
a sorted array of dates with entries and a sorted array of sorted arrays of
entries per date.
* WebKit.pbproj/project.pbxproj: Updated for new files
2002-02-18 John Sullivan <sullivan@apple.com>
First piece of implementing IFWebHistory. None of the mutators do anything,
......
......@@ -17,9 +17,9 @@
NSString *_title;
NSImage *_image;
NSString *_comment;
NSDate *_creationDate;
NSDate *_modificationDate;
NSDate *_lastVisitedDate;
NSCalendarDate *_creationDate;
NSCalendarDate *_modificationDate;
NSCalendarDate *_lastVisitedDate;
}
-(id)init;
......@@ -31,16 +31,16 @@
-(NSString *)title;
-(NSImage *)image;
-(NSString *)comment;
-(NSDate *)creationDate;
-(NSDate *)modificationDate;
-(NSDate *)lastVisitedDate;
-(NSCalendarDate *)creationDate;
-(NSCalendarDate *)modificationDate;
-(NSCalendarDate *)lastVisitedDate;
-(void)setURL:(NSURL *)url;
-(void)setTitle:(NSString *)title;
-(void)setImage:(NSImage *)image;
-(void)setComment:(NSString *)comment;
-(void)setModificationDate:(NSDate *)date;
-(void)setLastVisitedDate:(NSDate *)date;
-(void)setModificationDate:(NSCalendarDate *)date;
-(void)setLastVisitedDate:(NSCalendarDate *)date;
-(unsigned)hash;
-(BOOL)isEqual:(id)anObject;
......
......@@ -48,9 +48,9 @@ -(id)initWithURL:(NSURL *)url title:(NSString *)title image:(NSImage *)image com
_title = [title retain];
_image = [image retain];
_comment = [comment retain];
_creationDate = [[NSDate alloc] init];
_modificationDate = [[NSDate alloc] init];
_lastVisitedDate = [[NSDate alloc] init];
_creationDate = [[NSCalendarDate alloc] init];
_modificationDate = [[NSCalendarDate alloc] init];
_lastVisitedDate = [[NSCalendarDate alloc] init];
return self;
}
......@@ -75,17 +75,17 @@ -(NSString *)comment
return _comment;
}
-(NSDate *)creationDate;
-(NSCalendarDate *)creationDate;
{
return _creationDate;
}
-(NSDate *)modificationDate;
-(NSCalendarDate *)modificationDate;
{
return _modificationDate;
}
-(NSDate *)lastVisitedDate
-(NSCalendarDate *)lastVisitedDate
{
return _lastVisitedDate;
}
......@@ -122,7 +122,7 @@ -(void)setComment:(NSString *)comment
}
}
-(void)setModificationDate:(NSDate *)date
-(void)setModificationDate:(NSCalendarDate *)date
{
if (date != _modificationDate) {
[_modificationDate release];
......@@ -130,7 +130,7 @@ -(void)setModificationDate:(NSDate *)date
}
}
-(void)setLastVisitedDate:(NSDate *)date
-(void)setLastVisitedDate:(NSCalendarDate *)date
{
if (date != _lastVisitedDate) {
[_lastVisitedDate release];
......
......@@ -9,9 +9,14 @@
#import <Foundation/Foundation.h>
#import <WebKit/IFURIEntry.h>
@class IFWebHistoryPrivate;
// notification sent when history is modified
#define IFWebHistoryEntriesChangedNotification @"IFWebHistoryEntriesChangedNotification"
@interface IFWebHistory : NSObject {
@private
id _historyPrivate;
IFWebHistoryPrivate *_historyPrivate;
}
+ (IFWebHistory *)sharedWebHistory;
......@@ -19,6 +24,7 @@
// modifying contents
- (void)addEntry: (IFURIEntry *)entry;
- (void)removeEntry: (IFURIEntry *)entry;
- (void)removeEntriesForDay: (NSCalendarDate *)calendarDate;
- (void)removeAllEntries;
// retrieving contents for date-based presentation
......
......@@ -7,13 +7,10 @@
//
#import "IFWebHistory.h"
#import "IFWebHistoryPrivate.h"
static IFWebHistory *sharedWebHistory = nil;
@interface NSCalendarDate (IFExtensions)
- (int)daysSinceDate: (NSCalendarDate *)date;
@end
@implementation IFWebHistory
+ (IFWebHistory *)sharedWebHistory
......@@ -25,73 +22,55 @@ + (IFWebHistory *)sharedWebHistory
return sharedWebHistory;
}
- (IFURIEntry *)createTestEntryWithURLString: (NSString *)urlString
title: (NSString *)title
date: (NSDate *)date
- (id)init
{
IFURIEntry *entry = [[[IFURIEntry alloc] initWithURL: [NSURL URLWithString: urlString]
title: title] autorelease];
[entry setLastVisitedDate: date];
return entry;
}
- (NSArray *)testDataDates
{
static NSArray *testDataDates;
if (testDataDates == nil) {
NSCalendarDate *today, *yesterday;
today = [NSCalendarDate calendarDate];
yesterday = [today dateByAddingYears:0 months:0 days:-1 hours:0 minutes:0 seconds:0];
testDataDates = [NSArray arrayWithObjects: today, yesterday, nil];
[testDataDates retain];
if ((self = [super init]) != nil) {
_historyPrivate = [[IFWebHistoryPrivate alloc] init];
}
return testDataDates;
return self;
}
- (NSArray *)testData
- (void)dealloc
{
static NSArray *testData = nil;
if (testData == nil) {
NSCalendarDate *date1 = [[self testDataDates] objectAtIndex: 0];
NSCalendarDate *date2 = [[self testDataDates] objectAtIndex: 1];
testData = [NSArray arrayWithObjects:
[NSArray arrayWithObjects:
[self createTestEntryWithURLString: @"http://www.apple.com" title: @"Apple" date: date1],
[self createTestEntryWithURLString: @"http://www.google.com" title: @"Google" date: date1],
nil],
[NSArray arrayWithObjects:
[self createTestEntryWithURLString: @"http://www.amazon.com" title: @"Amazon" date: date2],
[self createTestEntryWithURLString: @"http://www.salon.com" title: @"Salon" date: date2],
nil],
nil];
[testData retain];
}
return testData;
[_historyPrivate release];
[super dealloc];
}
#pragma mark MODIFYING CONTENTS
- (void)sendEntriesChangedNotification
{
[[NSNotificationCenter defaultCenter]
postNotificationName: IFWebHistoryEntriesChangedNotification
object: self];
}
- (void)addEntry: (IFURIEntry *)entry
{
//FIXME: not yet implemented
[_historyPrivate addEntry: entry];
[self sendEntriesChangedNotification];
}
- (void)removeEntry: (IFURIEntry *)entry
{
//FIXME: not yet implemented
if ([_historyPrivate removeEntry: entry]) {
[self sendEntriesChangedNotification];
}
}
- (void)removeEntriesForDay: (NSCalendarDate *)calendarDate
{
if ([_historyPrivate removeEntriesForDay: calendarDate]) {
[self sendEntriesChangedNotification];
}
}
- (void)removeAllEntries
{
//FIXME: not yet implemented
if ([_historyPrivate removeAllEntries]) {
[self sendEntriesChangedNotification];
}
}
......@@ -99,65 +78,31 @@ - (void)removeAllEntries
- (NSArray *)orderedLastVisitedDays
{
//FIXME: not yet implemented
return [self testDataDates];
return [_historyPrivate orderedLastVisitedDays];
}
- (NSArray *)orderedEntriesLastVisitedOnDay: (NSCalendarDate *)date
{
//FIXME: not yet implemented
int index, count;
NSArray *dataDates;
dataDates = [self testDataDates];
count = [dataDates count];
for (index = 0; index < count; ++index) {
if ([date daysSinceDate: [dataDates objectAtIndex: index]] == 0) {
return [[self testData] objectAtIndex: index];
}
}
return nil;
return [_historyPrivate orderedEntriesLastVisitedOnDay: date];
}
#pragma mark STRING-BASED RETRIEVAL
- (NSArray *)entriesWithAddressContainingString: (NSString *)string
{
// FIXME: not yet implemented
return nil;
return [_historyPrivate entriesWithAddressContainingString: string];
}
- (NSArray *)entriesWithTitleOrAddressContainingString: (NSString *)string
{
// FIXME: not yet implemented
return nil;
return [_historyPrivate entriesWithTitleOrAddressContainingString: string];
}
#pragma mark URL MATCHING
- (BOOL)containsURL: (NSURL *)url
{
// FIXME: not yet implemented
return NO;
}
@end
@implementation NSCalendarDate (IFExtensions)
- (int)daysSinceDate: (NSCalendarDate *)date
{
int deltaDays;
if (self == date) {
deltaDays = 0;
} else {
[self years:NULL months:NULL days:&deltaDays
hours:NULL minutes:NULL seconds:NULL sinceDate: date];
}
return deltaDays;
return [_historyPrivate containsURL: url];
}
@end
//
// IFWebHistoryPrivate.h
// WebKit
//
// Created by John Sullivan on Tue Feb 19 2002.
// Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <WebKit/IFURIEntry.h>
@interface IFWebHistoryPrivate : NSObject {
@private
NSMutableDictionary *_urlDictionary;
NSMutableArray *_datesWithEntries;
NSMutableArray *_entriesByDate;
}
- (void)addEntry: (IFURIEntry *)entry;
- (BOOL)removeEntry: (IFURIEntry *)entry;
- (BOOL)removeEntriesForDay: (NSCalendarDate *)calendarDate;
- (BOOL)removeAllEntries;
- (NSArray *)orderedLastVisitedDays;
- (NSArray *)orderedEntriesLastVisitedOnDay: (NSCalendarDate *)calendarDate;
- (NSArray *)entriesWithAddressContainingString: (NSString *)string;
- (NSArray *)entriesWithTitleOrAddressContainingString: (NSString *)string;
- (BOOL)containsURL: (NSURL *)url;
@end
//
// IFWebHistoryPrivate.m
// WebKit
//
// Created by John Sullivan on Tue Feb 19 2002.
// Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
//
#import "IFWebHistoryPrivate.h"
#import <WebFoundation/IFNSCalendarDateExtensions.h>
#import <WebKit/WebKitDebug.h>
@implementation IFWebHistoryPrivate
#pragma mark OBJECT FRAMEWORK
- (id)init
{
if ((self = [super init]) != nil) {
_urlDictionary = [[NSMutableDictionary alloc] init];
_datesWithEntries = [[NSMutableArray alloc] init];
_entriesByDate = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc
{
[_urlDictionary release];
[_datesWithEntries release];
[_entriesByDate release];
[super dealloc];
}
#pragma mark MODIFYING CONTENTS
// Returns whether the day is already in the list of days,
// and fills in *index with the found or proposed index.
- (BOOL)findIndex: (int *)index forDay: (NSCalendarDate *)date
{
int count;
WEBKIT_ASSERT_VALID_ARG (index, index != nil);
//FIXME: just does linear search through days; inefficient if many days
count = [_datesWithEntries count];
for (*index = 0; *index < count; ++*index) {
int deltaDays = [date daysSinceDate: [_datesWithEntries objectAtIndex: *index]];
if (deltaDays == 0) {
return YES;
}
if (deltaDays > 0) {
return NO;
}
}
return NO;
}
- (void)insertEntry: (IFURIEntry *)entry atDateIndex: (int)dateIndex
{
int index, count;
NSMutableArray *entriesForDate;
NSCalendarDate *entryDate;
WEBKIT_ASSERT_VALID_ARG (entry, entry != nil);
WEBKIT_ASSERT_VALID_ARG (dateIndex, dateIndex >= 0 && (uint)dateIndex < [_entriesByDate count]);
//FIXME: just does linear search through entries; inefficient if many entries for this date
entryDate = [entry lastVisitedDate];
entriesForDate = [_entriesByDate objectAtIndex: dateIndex];
count = [entriesForDate count];
for (index = 0; index < count; ++index) {
if ([entryDate compare: [[entriesForDate objectAtIndex: index] lastVisitedDate]] != NSOrderedAscending) {
break;
}
}
[entriesForDate insertObject: entry atIndex: index];
}
- (BOOL)removeEntryForURLString: (NSString *)urlString
{
IFURIEntry *entry;
int dateIndex;
entry = [_urlDictionary objectForKey: urlString];
if (entry == nil) {
return NO;
}
[_urlDictionary removeObjectForKey: urlString];
if ([self findIndex: &dateIndex forDay: [entry lastVisitedDate]]) {
NSMutableArray *entriesForDate = [_entriesByDate objectAtIndex: dateIndex];
[entriesForDate removeObject: entry];
// remove this date entirely if there are no other entries on it
if ([entriesForDate count] == 0) {
[_entriesByDate removeObjectAtIndex: dateIndex];
[_datesWithEntries removeObjectAtIndex: dateIndex];
}
} else {
NSLog(@"'%@' was in url dictionary but its date %@ was not in date index",
[entry url], [entry lastVisitedDate]);
}
return YES;
}
- (void)addEntry: (IFURIEntry *)entry
{
int dateIndex;
NSString *urlString;
WEBKIT_ASSERT_VALID_ARG (entry, [entry lastVisitedDate] != nil);
urlString = [[entry url] absoluteString];
[self removeEntryForURLString: urlString];
if ([self findIndex: &dateIndex forDay: [entry lastVisitedDate]]) {
// other entries already exist for this date
[self insertEntry: entry atDateIndex: dateIndex];
} else {
// no other entries exist for this date
[_datesWithEntries insertObject: [entry lastVisitedDate] atIndex: dateIndex];
[_entriesByDate insertObject: [[NSMutableArray alloc] initWithObjects: entry, nil] atIndex: dateIndex];
}
[_urlDictionary setObject: entry forKey: urlString];
}
- (BOOL)removeEntry: (IFURIEntry *)entry
{
IFURIEntry *matchingEntry;
NSString *urlString;
urlString = [[entry url] absoluteString];
// If this exact object isn't stored, then make no change.
// FIXME: Is this the right behavior if this entry isn't present, but another entry for the same URL is?
// Maybe need to change the API to make something like removeEntryForURLString public instead.
matchingEntry = [_urlDictionary objectForKey: urlString];
if (matchingEntry != entry) {
return NO;
}
[self removeEntryForURLString: urlString];
return YES;
}
- (BOOL)removeEntriesForDay: (NSCalendarDate *)calendarDate
{
int index;
NSEnumerator *entriesForDay;
IFURIEntry *entry;
if (![self findIndex: &index forDay: calendarDate]) {
return NO;
}
entriesForDay = [[_entriesByDate objectAtIndex: index] objectEnumerator];
while ((entry = [entriesForDay nextObject]) != nil) {
[_urlDictionary removeObjectForKey: [[entry url] absoluteString]];
}
[_datesWithEntries removeObjectAtIndex: index];
[_entriesByDate removeObjectAtIndex: index];
return YES;
}
- (BOOL)removeAllEntries
{
if ([_urlDictionary count] == 0) {
return NO;
}
[_entriesByDate removeAllObjects];
[_datesWithEntries removeAllObjects];
[_urlDictionary removeAllObjects];
return YES;
}
#pragma mark DATE-BASED RETRIEVAL
- (NSArray *)orderedLastVisitedDays
{
return _datesWithEntries;
}
- (NSArray *)orderedEntriesLastVisitedOnDay: (NSCalendarDate *)date
{
int index;
if ([self findIndex: &index forDay: date]) {
return [_entriesByDate objectAtIndex: index];
}
return nil;
}
#pragma mark STRING-BASED RETRIEVAL