Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 0c56df3e8d
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 135 lines (109 sloc) 4.134 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
// Copyright 2009 Max Howell
#import "ComicController.h"
#import "NSString+mxcl.h"
#import <stdio.h>


static NSString* fgetns(FILE* f)
{
    // http://support.microsoft.com/kb/q208427/
    // http://www.boutell.com/newfaq/misc/urllength.html
    char buf[2084];
    if(!fgets(buf, 2084, f))return nil;
    return [[NSString stringWithUTF8String:buf] strip];
}

static NSString* command(NSString* rb)
{
    NSString* resources = [[NSBundle mainBundle] resourcePath];
    return [NSString stringWithFormat:@"ruby -I'%@' '%@/%@'", resources, resources, rb];
}


NSMutableArray* comicsFromScript(NSString* rb)
{
    // 10 is typical, so lets be conservative
    NSMutableArray* comics = [[NSMutableArray alloc] initWithCapacity:10];
    
    FILE* pipe = popen([command(rb) UTF8String], "r+");
    if(!pipe)
        return comics;

    NSString* s;
    while(s = fgetns(pipe))
    {
        NSURL* url = [NSURL URLWithString:s];
        NSString* ext = [[s pathExtension] lowercaseString];
#define _(x) [ext isEqualToString:x]
        if(_(@"png") || _(@"jpg") || _(@"jpeg") || _(@"gif")){
            NSNumber* time = [NSNumber numberWithUnsignedInt:[fgetns(pipe) intValue]];
            NSString* title = fgetns(pipe);
            
            [comics addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                               url, @"URL",
                               time, @"UTC",
                               title, @"Title",
                               rb, @"Comic",
                               nil]];
        }else{
            NSString* s = [NSString stringWithContentsOfURL:url];
            uint32_t const n = [s lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
            const char* data = [s UTF8String];
            
            // first write the size of the data in network-byte-order
            uint32_t size_of_index = htonl(n);
            fwrite(&size_of_index, sizeof(size_of_index), 1, pipe);
            // now write the data itself
            fwrite(data, sizeof(char), n, pipe);
            fflush(pipe);
        }
#undef _
    }
    pclose(pipe);

    return comics;
}


@implementation ComicController

NSInteger sort(id a, id b, void* v)
{
    return [[a objectForKey:@"UTC"] compare:[b objectForKey:@"UTC"]];
}

void prune(NSMutableArray* comics, time_t before)
{
    NSMutableArray* toremove = [NSMutableArray array];
    NSDictionary* comic;
    for(comic in comics){
        time_t t = [[comic objectForKey:@"UTC"] unsignedIntValue];
        if(t <= before)
            [toremove addObject:comic];
    }
    [comics removeObjectsInArray:toremove];
}

NSArray* comix(NSString* rb)
{
    NSMutableArray* xkcd = comicsFromScript(rb);
    time_t before = [[[NSUserDefaults standardUserDefaults] objectForKey:rb] unsignedIntValue];
    prune(xkcd, before);
    return xkcd;
}

-(void)awakeFromNib
{
    comics = [[NSMutableArray arrayWithCapacity:20] retain];
   [comics addObjectsFromArray:comix(@"xkcd.com.rb")];
   [comics addObjectsFromArray:comix(@"explosm.net.rb")];
    comics = [[comics sortedArrayUsingFunction:sort context:nil] mutableCopy];
}

float titleBarHeight()
{
    NSRect outside = NSMakeRect(0, 0, 100, 100);
    NSRect inside = [NSWindow contentRectForFrameRect:outside
                                            styleMask:NSTitledWindowMask];
    return outside.size.height - inside.size.height;
}

-(IBAction)next:(id)sender
{
    NSDictionary* comic = [comics lastObject];
    [comics removeLastObject];
    
    NSURL* url = [comic objectForKey:@"URL"];
    NSImage* image = [[NSImage alloc] initWithContentsOfURL:url];

    if(!image)return; //TODO more
    
    [view setImage:image];

    NSRect frame = [[view window] frame];
    frame.size = [[view image] size];
    frame.size.height += titleBarHeight();
    [[view window] setFrame:frame display:true animate:true];
    
    [[view window] setTitle:[comic objectForKey:@"Title"]];
    
    [[NSUserDefaults standardUserDefaults] setObject:[comic objectForKey:@"UTC"]
                                              forKey:[comic objectForKey:@"Comic"]];
}

@end
Something went wrong with that request. Please try again.