Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/woip/app
diff options
context:
space:
mode:
authorWade Brainerd <wadetb@gmail.com>2008-05-23 22:59:37 (GMT)
committer Wade Brainerd <wadetb@gmail.com>2008-05-23 22:59:37 (GMT)
commit9878512ab181ef56e82d91ed3e69ddbaa50520d0 (patch)
tree879e52bebdea44daa32afaaa8802c183fd9484ed /woip/app
parentdd58bf72d6799438d8033cf7de6bc26a711734c3 (diff)
Reorganization step 2.
Diffstat (limited to 'woip/app')
-rw-r--r--woip/app/ArticleView.h16
-rw-r--r--woip/app/ArticleView.m83
-rw-r--r--woip/app/Makefile23
-rw-r--r--woip/app/ReadStream.h16
-rw-r--r--woip/app/ReadStream.m71
-rw-r--r--woip/app/SearchBar.h11
-rw-r--r--woip/app/SearchBar.m69
-rw-r--r--woip/app/SearchResult.h9
-rw-r--r--woip/app/SearchResult.m13
-rw-r--r--woip/app/SearchView.h35
-rw-r--r--woip/app/SearchView.m179
-rw-r--r--woip/app/WPParser.h16
-rw-r--r--woip/app/WPParser.m113
-rw-r--r--woip/app/WebKitView.h15
-rw-r--r--woip/app/WebKitView.m77
-rw-r--r--woip/app/WikiApp.h24
-rw-r--r--woip/app/WikiApp.m139
-rw-r--r--woip/app/main.m9
18 files changed, 918 insertions, 0 deletions
diff --git a/woip/app/ArticleView.h b/woip/app/ArticleView.h
new file mode 100644
index 0000000..87347a0
--- /dev/null
+++ b/woip/app/ArticleView.h
@@ -0,0 +1,16 @@
+#import <UIKit/UIKit.h>
+#import "WebKitView.h"
+#import "WPParser.h"
+#import "../c/wp.h"
+
+@interface ArticleView : UIView {
+ WebKitView *wkv;
+
+ wp_dump *dump;
+ wp_article *article;
+}
+-(void) setPolicyDelegate: (id) obj;
+-(void) updateHTML: (NSString *) str;
+-(void) setDump: (wp_dump *) d;
+-(void) setWikiApp: (id) w;
+@end
diff --git a/woip/app/ArticleView.m b/woip/app/ArticleView.m
new file mode 100644
index 0000000..44718bc
--- /dev/null
+++ b/woip/app/ArticleView.m
@@ -0,0 +1,83 @@
+#import "ArticleView.h"
+
+@implementation ArticleView
+- (id) initWithFrame: (struct CGRect) frame
+{
+ self = [super initWithFrame:frame];
+
+ wkv = [[WebKitView alloc] initWithFrame: frame]; //CGRectMake(0, 0, frame.size.width, frame.size.height)];
+ [wkv setPolicyDelegate: self];
+
+ article = xalloc(sizeof(wp_article));
+ init_article(article);
+
+ [self addSubview: wkv];
+
+ return self;
+}
+
+- (BOOL)respondsToSelector:(SEL)aSelector
+{
+ NSLog(@"AV Request for selector: %@", NSStringFromSelector(aSelector));
+ return [super respondsToSelector:aSelector];
+}
+
+- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener
+{
+ NSLog(@"request: %@", request);
+ NSLog(@"url: %@", [actionInformation objectForKey: @"WebActionOriginalURLKey"]);
+
+ NSString *WebActionElementKey = @"WebActionElementKey";
+ id key;
+
+ for (key in actionInformation) {
+ NSLog(@"key: %@, value: %@", key, [actionInformation objectForKey:key]);
+ }
+
+ if([actionInformation objectForKey: WebActionElementKey] != nil) {
+ NSLog(@"loading article with url %@", [request URL]);
+ NSLog(@"url path: %@", [[actionInformation objectForKey: @"WebActionOriginalURLKey"] path]);
+ NSString *title = [[[[actionInformation objectForKey: @"WebActionOriginalURLKey"] path] substringFromIndex: 1]
+ stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
+ [self loadArticle: title];
+ [listener use];
+ } else
+ [listener use];
+
+ NSLog(@"webView:decidePolicyForNavigationAction: %@", [request URL]);
+ NSLog(@"listener: %@", listener);
+}
+
+- (void) updateHTML: (NSString *) str
+{
+ [wkv loadString: str];
+}
+
+-(void) setDump: (wp_dump *) d {
+ dump = d;
+}
+
+-(void) notFound: (NSString *) title {
+ [self loadArticle: title withContents: [NSString stringWithFormat: @"The article <strong>%@</strong> doesn't exist in this Wikipedia dump.", title]];
+}
+
+-(void) loadArticle: (NSString *) title {
+ NSString *cap = [NSString stringWithFormat: @"%c%@", toupper([title characterAtIndex: 0]), [title substringFromIndex: 1]];
+ NSLog(@"cap: %@", cap);
+ if(load_article(dump, [cap UTF8String], article) != -1)
+ [self loadArticle: cap withContents: [NSString stringWithUTF8String: article->text]];
+ else
+ [self notFound: title];
+}
+
+-(void) loadArticle: (NSString *) title fromBlock: (int) block {
+ block_load_article(dump, [title UTF8String], block, article);
+ [self loadArticle: title withContents: [NSString stringWithUTF8String: article->text]];
+}
+
+- (void) loadArticle: (NSString *) title withContents: (NSString *) contents {
+ WPParser *wp = [[WPParser alloc] initWithMarkup: contents];
+ NSString *css = @"body { font-family: Helvetica; width: 310px; padding: 5px; margin: 0; word-wrap: break-word }";
+ [self updateHTML: [NSString stringWithFormat: @"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><style>%@</style></head><body><h1>%@</h1>%@</body></html>", css, title, [wp parsed]]];
+}
+@end
diff --git a/woip/app/Makefile b/woip/app/Makefile
new file mode 100644
index 0000000..f27cf69
--- /dev/null
+++ b/woip/app/Makefile
@@ -0,0 +1,23 @@
+CC=arm-apple-darwin-gcc
+LD=$(CC)
+LDFLAGS=-lobjc -framework CoreFoundation -framework CoreGraphics -framework WebKit -framework Foundation -framework UIKit -framework LayerKit -lbz2
+CFLAGS=-I/usr/local/arm-apple-darwin/include -DWP_INCLUDE -DDEBUG -g
+SEARCHVIEW=SearchView.o
+
+all: WikiApp
+
+WikiApp: WikiApp.o $(SEARCHVIEW) WebKitView.o main.o ArticleView.o SearchResult.o SearchBar.o WPParser.o ReadStream.o ../c/wp.o ../c/bzipreader.o ../c/safe.o ../c/lsearcher.o ../c/blocks.o
+ $(LD) $(LDFLAGS) -o $@ $^
+
+%.o: %.m
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+
+%.do: %.m
+ cat $< | ../rb/objcproc.rb > _debug_$< && $(CC) -c $(CFLAGS) $(CPPFLAGS) _debug_$< -o $@
+
+clean:
+ rm -f *.o WikiApp
+
+install:
+ scp WikiApp root@192.168.1.105:
+ ssh root@192.168.1.105 ./WikiApp
diff --git a/woip/app/ReadStream.h b/woip/app/ReadStream.h
new file mode 100644
index 0000000..96f8fe2
--- /dev/null
+++ b/woip/app/ReadStream.h
@@ -0,0 +1,16 @@
+#import <Foundation/Foundation.h>
+
+@interface ReadStream : NSObject {
+ NSString *str;
+ int pos;
+}
+
+-(ReadStream *) initWithString: (NSString *) str;
+-(unichar) peek;
+-(unichar) peekTwo;
+-(unichar) read;
+-(unichar) expect: (unichar) c;
+-(BOOL) isAtEnd;
+-(NSString *) readUpto: (unichar) c;
+
+@end
diff --git a/woip/app/ReadStream.m b/woip/app/ReadStream.m
new file mode 100644
index 0000000..a02cfb2
--- /dev/null
+++ b/woip/app/ReadStream.m
@@ -0,0 +1,71 @@
+#import "ReadStream.h"
+
+@implementation ReadStream
+
+-(ReadStream *) initWithString: (NSString *) s {
+ [self init];
+ str = s;
+ pos = 0;
+ return self;
+}
+
+-(unichar) safeCharAtIndex: (int) i {
+ return [self isAtEnd] ? 0 : [str characterAtIndex: i];
+}
+
+-(unichar) peekBack {
+ return [self safeCharAtIndex: pos - 1];
+}
+
+-(unichar) peek {
+ return [self safeCharAtIndex: pos];
+}
+
+-(unichar) peekTwo {
+ return [self safeCharAtIndex: pos + 1];
+}
+
+-(unichar) read {
+ unichar c = [self safeCharAtIndex: pos];
+ pos++;
+ return c;
+}
+
+-(BOOL) isAtEnd {
+ return pos == [str length];
+}
+
+-(unichar) expect: (unichar) c {
+ unichar r;
+ if((r = [self read]) != c) NSLog(@"WARNING: expected %c at position %d, found %c", c, pos - 1, r);
+ return r;
+}
+
+-(NSString *) readUpto: (unichar) c {
+ int found = pos;
+
+ while(found != [str length] && [self safeCharAtIndex: found++] != c);
+ //if(found == [str length]) return NULL; // not found
+
+ found--;
+ NSString *s = [str substringWithRange: NSMakeRange(pos, found - pos)];
+ pos = found;
+
+ return s;
+}
+
+/*-(NSString *) readUptoString: (NSString *) s {
+ NSRange range = [str rangeOfString: s options: 0 range: NSMakeRange(pos, [str length] - pos)];
+ NSString *text;
+
+ if(range.location != NSNotFound) {
+ text = [str substringToIndex: range.location];
+ pos = range.location;
+ } else {
+ text = [str substringFromIndex: pos];
+ }
+
+ return text;
+}*/
+
+@end
diff --git a/woip/app/SearchBar.h b/woip/app/SearchBar.h
new file mode 100644
index 0000000..5baf2c2
--- /dev/null
+++ b/woip/app/SearchBar.h
@@ -0,0 +1,11 @@
+#import <UIKit/UIKit.h>
+#import <CoreGraphics/CGAffineTransform.h>
+
+@interface SearchBar : UISearchField {
+ struct CGRect bounds;
+}
+
+-(void) show;
+-(void) hide;
+
+@end
diff --git a/woip/app/SearchBar.m b/woip/app/SearchBar.m
new file mode 100644
index 0000000..667d765
--- /dev/null
+++ b/woip/app/SearchBar.m
@@ -0,0 +1,69 @@
+#import "SearchBar.h"
+
+@implementation SearchBar
+
+-(SearchBar *) initWithFrame: (struct CGRect) rect {
+ self = [super initWithFrame: rect];
+
+ bounds = rect;
+
+ [self setTextFont: @"font-family: Helvetica; font-size: 14px; padding-top: 5px; padding-left: 4px;"];
+ [self setAutoCapsType: 0];
+ [self setPreferredKeyboardType: 0];
+ [self setAutoCorrectionType: 1]; //disabled
+ [self setOpaque: 0];
+ [self setClearButtonStyle: 1];
+ //[self setPlaceholder: @"Search"];
+ [self setDelegate: self];
+ [self becomeFirstResponder];
+
+ return self;
+}
+
+- (void) show
+{
+ [self setTransform: CGAffineTransformMake(1,0,0,1,0,0)];
+ [self setFrame: CGRectMake(-bounds.size.width, bounds.origin.y, bounds.size.width, bounds.size.height)];
+
+ struct CGAffineTransform trans = CGAffineTransformMakeTranslation(bounds.size.width + 10, 0);
+ UITransformAnimation *translate = [[UITransformAnimation alloc] initWithTarget: self];
+ [translate setStartTransform: CGAffineTransformMake(1,0,0,1,0,0)];
+ [translate setEndTransform: trans];
+
+ UIAlphaAnimation *fade = [[UIAlphaAnimation alloc] initWithTarget: self];
+ [fade setEndAlpha: 1];
+ [fade setStartAlpha: 0];
+
+ UIAnimator *animator = [[UIAnimator alloc] init];
+ [animator addAnimation: translate withDuration: .3 start: YES];
+ [animator addAnimation: fade withDuration: .3 start: YES];
+
+}
+
+- (void) hide
+{
+ struct CGRect rect = [UIHardware fullScreenApplicationContentRect];
+ rect.origin.x = rect.origin.y = 0;
+
+ [self setTransform: CGAffineTransformMake(1,0,0,1,0,0)];
+ [self setFrame: CGRectMake(0, bounds.origin.y, bounds.size.width, bounds.size.height)];
+
+ struct CGAffineTransform trans = CGAffineTransformMakeTranslation(-(bounds.size.width + 10), 0);
+
+ UITransformAnimation *translate = [[UITransformAnimation alloc] initWithTarget: self];
+
+ [translate setStartTransform: CGAffineTransformMake(1,0,0,1,0,0)];
+ [translate setEndTransform: trans];
+
+ UIAlphaAnimation *fade = [[UIAlphaAnimation alloc] initWithTarget: self];
+ [fade setEndAlpha: 0];
+ [fade setStartAlpha: 1];
+
+ UIAnimator *animator = [[UIAnimator alloc] init];
+ [animator addAnimation: translate withDuration: .3 start: YES];
+ [animator addAnimation: fade withDuration: .3 start: YES];
+}
+
+
+@end
+
diff --git a/woip/app/SearchResult.h b/woip/app/SearchResult.h
new file mode 100644
index 0000000..2c8d53a
--- /dev/null
+++ b/woip/app/SearchResult.h
@@ -0,0 +1,9 @@
+#import <UIKit/UIKit.h>
+
+@interface SearchResult : UITableCell
+{
+ NSString *article;
+}
+-(void) setArticle: (NSString *) title;
+-(NSString *) article;
+@end
diff --git a/woip/app/SearchResult.m b/woip/app/SearchResult.m
new file mode 100644
index 0000000..848c365
--- /dev/null
+++ b/woip/app/SearchResult.m
@@ -0,0 +1,13 @@
+#import "SearchResult.h"
+
+@implementation SearchResult
+
+-(void) setArticle: (NSString *) title {
+ article = title;
+}
+
+-(NSString *) article {
+ return article;
+}
+
+@end
diff --git a/woip/app/SearchView.h b/woip/app/SearchView.h
new file mode 100644
index 0000000..1025f56
--- /dev/null
+++ b/woip/app/SearchView.h
@@ -0,0 +1,35 @@
+#import <UIKit/UIKit.h>
+#import <UIKit/UICompletionTable.h>
+#import <UIKit/UIProgressBar.h>
+#import "WebKitView.h"
+#import "SearchResult.h"
+#import "ArticleView.h"
+#import "../c/wp.h"
+
+@interface SearchView : UIView {
+ NSMutableArray *results;
+ ArticleView *aview;
+ UIKeyboard *kbrd;
+ UIProgressBar *prog;
+ id parent;
+ UICompletionTable *table;
+ NSString *needle;
+ NSThread *sthread;
+ NSTimer *updater;
+ NSLock *lock;
+ int curResults;
+ bool needRefresh;
+
+ int nsearch;
+ char *curNeedle;
+
+ wp_dump *dump;
+ wp_article *article;
+}
+
+-(void) setArticleView: (ArticleView *) aview;
+-(void) setParent: (id) parent;
+-(void) setNeedle: (NSString *) needle;
+-(void) runSearch: (char *) needle;
+-(void) refreshResults;
+@end
diff --git a/woip/app/SearchView.m b/woip/app/SearchView.m
new file mode 100644
index 0000000..9936136
--- /dev/null
+++ b/woip/app/SearchView.m
@@ -0,0 +1,179 @@
+#import "SearchView.h"
+#import "WikiApp.h"
+
+#define MAXRES 10
+
+int nresults = 0;
+uint32_t blocks[MAXRES];
+char *matches[MAXRES];
+char *buf;
+
+bool chandleResult(char *s) {
+ NSLog(@"chandleResult: %s", s);
+ buf = xalloc(MAXSTR * sizeof(char));
+ strcpy(buf, s);
+
+ NSLog(@"buf: 0x%x, %s", buf, buf);
+
+ char *blockpos = strrchr(buf, ' ');
+ int c;
+
+ if(nresults >= MAXRES) return false;
+
+ if(blockpos) {
+ *(blockpos - 1) = '\0';
+ blockpos++;
+
+ blocks[nresults] = atoi(blockpos);
+
+ matches[nresults] = buf;
+ } else
+ fatal("invalid: '%s'", buf);
+
+ NSLog(@"chandleResult returning...");
+ return ++nresults < MAXRES;
+}
+
+void zeroResults() {
+ int i;
+ for(i = 0; i < nresults; i++) free(matches[i]);
+ nresults = 0;
+}
+int numResults() { return nresults; }
+char *resultAt(int i) { return matches[i]; }
+uint32_t blockAt(int i) { return blocks[i]; }
+
+@implementation SearchView
+
+-(void) initMatches {
+ int i;
+ for(i = 0; i < MAXRES; i++)
+ matches[i] = xalloc(MAXSTR * sizeof(char));
+ buf = NULL;
+}
+
+-(id) initWithFrame: (struct CGRect) frame
+{
+ self = [super initWithFrame: frame];
+
+ curNeedle = xalloc(MAXSTR * sizeof(char));
+ [self initMatches];
+ sthread = nil;
+ lock = [[NSRecursiveLock alloc] init];
+
+ struct CGRect rect = [UIHardware fullScreenApplicationContentRect];
+ //TODO: re-enable me when I want progress bar
+ //table = [[UICompletionTable alloc] initWithFrame: CGRectMake(0, 0, frame.size.width, frame.size.height - 240)];
+ table = [[UICompletionTable alloc] initWithFrame: CGRectMake(0, 0, frame.size.width, frame.size.height - 215)];
+
+ [table setDelegate: self];
+
+ [self addSubview: table];
+
+ prog = [[UIProgressBar alloc] initWithFrame: CGRectMake(0, 180, 320, 20)];
+ [prog setStyle: 0];
+ [prog setProgress: 1.0];
+ //[self addSubview: prog];
+ //TODO: re-enable above to get progress bar
+
+ kbrd = [[UIKeyboard alloc] initWithFrame: CGRectMake(0, 200, 320, 480)];
+ [self addSubview: kbrd];
+
+ dump = xalloc(sizeof(wp_dump));
+
+ load_dump(dump,
+ "/var/root/wp/processed",
+ "/var/root/wp/locate.db",
+ "/var/root/wp/locate.prefixdb",
+ "/var/root/wp/blocks.db");
+
+ updater = [NSTimer scheduledTimerWithTimeInterval: 1
+ target: self
+ selector: @selector(refreshResults:)
+ userInfo: nil
+ repeats: YES];
+
+ return self;
+}
+
+-(void) stopSearch {
+ NSLog(@"stopSearch");
+ kill_search();
+ while(sthread && [sthread isExecuting]) {
+ //usleep(100000);
+ //NSLog(@"waiting for sthread");
+ }
+}
+
+
+-(void) runSearch {
+ NSLog(@"runSearch with needle: '%s'", curNeedle);
+ NSAutoreleasePool* pool = [NSAutoreleasePool new];
+ search(&dump->index, curNeedle, &chandleResult, NULL, true, true);
+ needRefresh = true;
+ NSLog(@"search done");
+ [pool release];
+}
+
+-(void) refreshResults: (NSTimer *) timer {
+ NSLog(@"refreshResults");
+ [lock lock];
+ if(needRefresh || (sthread && [sthread isExecuting])) {
+ [table reloadData];
+ if(needRefresh) needRefresh = false;
+ }
+ double d;
+ search_progress(&dump->index, &d);
+ [prog setProgress: d];
+ [prog updateIfNecessary];
+ [lock unlock];
+}
+
+-(void) updateResults {
+ NSLog(@"Updating results for '%@'", needle);
+ [self stopSearch];
+ zeroResults();
+ curResults = 0;
+ needRefresh = false;
+
+ /* TODO: keep the table results that match the new needle */
+ [table reloadData];
+ [prog setProgress: 0.0];
+
+ strncpy(curNeedle, [[needle capitalizedString] UTF8String], MAXSTR);
+
+ sthread = [[NSThread alloc] initWithTarget: self selector: @selector(runSearch) object: nil];
+ [sthread start];
+}
+
+-(int) numberOfCompletionsInTable:(UICompletionTable *) t {
+ return numResults();
+}
+
+-(UITableCell *) table:(UITable *)t completionAtIndex: (int) index {
+ return [NSString stringWithUTF8String: resultAt(index)];
+}
+
+-(void) table: (UICompletionTable *) t didSelectCompletionAtIndex: (int) i {
+ [aview loadArticle: [NSString stringWithUTF8String: resultAt(i)] fromBlock: blockAt(i)];
+ [parent switchToArticle];
+}
+
+- (void) setParent: (WikiApp *) w {
+ parent = w;
+}
+
+-(void) setNeedle: (NSString *) s {
+ [lock lock];
+ needle = s;
+
+ if([s length] > 0 && [s characterAtIndex: 0] != ' ')
+ [self updateResults];
+ [lock unlock];
+}
+
+- (void) setArticleView: (ArticleView *) a {
+ aview = a;
+ [aview setDump: dump];
+}
+@end
diff --git a/woip/app/WPParser.h b/woip/app/WPParser.h
new file mode 100644
index 0000000..5e659e2
--- /dev/null
+++ b/woip/app/WPParser.h
@@ -0,0 +1,16 @@
+#import <Foundation/Foundation.h>
+#import "ReadStream.h"
+
+@interface WPParser : NSObject {
+ ReadStream *raw;
+ NSMutableString *html;
+ BOOL italic;
+ BOOL bold;
+ int tmplLevel;
+}
+
+-(WPParser *) initWithMarkup: (NSString *) markup;
+-(void) parse;
+-(NSString *) parsed;
+
+@end
diff --git a/woip/app/WPParser.m b/woip/app/WPParser.m
new file mode 100644
index 0000000..848ac46
--- /dev/null
+++ b/woip/app/WPParser.m
@@ -0,0 +1,113 @@
+#import "WPParser.h"
+
+@implementation WPParser
+
+-(WPParser *) initWithMarkup: (NSString *) markup {
+ [self init];
+ raw = [[ReadStream alloc] initWithString: markup];
+ return self;
+}
+
+-(void) parseLink {
+ NSString *linkText, *linkHref, *text;
+
+ [raw expect: '['];
+ [raw expect: '['];
+ text = [raw readUpto: ']'];
+ [raw expect: ']'];
+ [raw expect: ']'];
+
+ NSRange range = [text rangeOfString: @"|"];
+ if(range.location != NSNotFound) {
+ linkText = [text substringFromIndex: range.location + 1];
+ linkHref = [text substringToIndex: range.location];
+ } else
+ linkText = linkHref = text;
+
+ [html appendFormat: @"<a href=\"wp://localhost/%@\">%@</a>", linkHref, linkText];
+}
+
+-(void) parseHeading {
+ NSString *text;
+
+ int level = 0;
+ while([raw peek] == '=') { [raw read]; level++; }
+ text = [raw readUpto: '='];
+ while([raw peek] == '=') [raw read];
+
+ [html appendFormat: @"<h%d>%@</h%d>", level, text, level];
+}
+
+-(void) parseItalic {
+ if(italic) {
+ italic = NO;
+ [html appendString: @"</i>"];
+ } else {
+ italic = YES;
+ [html appendString: @"<i>"];
+ }
+}
+
+-(void) parseBold {
+ [raw expect: '\''];
+
+ if(bold) {
+ bold = NO;
+ [html appendString: @"</b>"];
+ } else {
+ bold = YES;
+ [html appendString: @"<b>"];
+ }
+}
+
+-(void) parseBoldItalic {
+ [raw expect: '\''];
+ [raw expect: '\''];
+
+ if([raw peek] == '\'') [self parseBold];
+ else [self parseItalic];
+}
+
+-(void) parseTemplateStart {
+ [raw expect: '{'];
+ [raw expect: '{'];
+ tmplLevel++;
+}
+
+-(void) parseTemplateEnd {
+ [raw expect: '}'];
+ [raw expect: '}'];
+ tmplLevel--;
+}
+
+-(void) parse {
+ while(![raw isAtEnd]) {
+ unichar c = [raw peek];
+
+ if(c == '{' && [raw peekTwo] == '{')
+ [self parseTemplateStart];
+ else if(c == '}' && [raw peekTwo] == '}')
+ [self parseTemplateEnd];
+ else if(tmplLevel > 0)
+ [raw read];
+ else if(c == '[' && [raw peekTwo] == '[')
+ [self parseLink];
+ else if ([raw peekBack] == '\n' && [raw peek] == '=')
+ [self parseHeading];
+ else if(c == '\'' && [raw peekTwo] == '\'')
+ [self parseBoldItalic];
+ else
+ [html appendFormat: @"%c", [raw read]];
+ }
+}
+
+-(NSString *) parsed {
+ html = [[NSMutableString alloc] init];
+ bold = NO;
+ italic = NO;
+ tmplLevel = 0;
+ [self parse];
+ return html;
+}
+
+@end
diff --git a/woip/app/WebKitView.h b/woip/app/WebKitView.h
new file mode 100644
index 0000000..d038578
--- /dev/null
+++ b/woip/app/WebKitView.h
@@ -0,0 +1,15 @@
+#import <UIKit/UIKit.h>
+#import <UIKit/UIScroller.h>
+#import <UIKit/UIWebView.h>
+
+@interface WebKitView : UIScroller {
+ UIWebView *webView;
+ UIScroller *scroller;
+}
+
+-(id)initWithFrame: (CGRect)frame;
+-(void)loadURL: (NSURL *)url;
+-(void)dealloc;
+-(void)loadString: (NSString *)str;
+
+@end
diff --git a/woip/app/WebKitView.m b/woip/app/WebKitView.m
new file mode 100644
index 0000000..d9730e3
--- /dev/null
+++ b/woip/app/WebKitView.m
@@ -0,0 +1,77 @@
+#import "WebKitView.h"
+#import <UIKit/UIView-Geometry.h>
+
+@implementation WebKitView
+
+-(void)loadString: (NSString *)str
+{
+ [webView loadHTMLString: str baseURL: [NSURL URLWithString: @"http://foo.com"]];
+ [scroller setOffset: CGPointMake(0, 0)];
+}
+
+-(void)loadURL: (NSURL *)url
+{
+ NSURLRequest* urlRequest = [NSURLRequest requestWithURL: url];
+ [webView loadRequest: urlRequest];
+}
+
+-(void)dealloc
+{
+ [webView release];
+ [super dealloc];
+}
+
+-(void)setPolicyDelegate: (id) obj {
+ [[webView webView] setPolicyDelegate: obj];
+}
+
+- (BOOL)respondsToSelector:(SEL)aSelector
+{
+ NSLog(@"WKV Request for selector: %@", NSStringFromSelector(aSelector));
+ return [super respondsToSelector:aSelector];
+}
+
+/*-(void)view: (id)v didSetFrame:(CGRect)f
+{
+ if( v == webView )
+ [scroller setContentSize: CGSizeMake(f.size.width, f.size.height)];
+}*/
+
+-(void)view:(id)v didDrawInRect:(CGRect)f duration:(float)d
+{
+ if(v == webView)
+ [scroller setContentSize: CGSizeMake(320, [webView bounds].size.height)];
+}
+
+-(id)initWithFrame: (CGRect)frame
+{
+ [super initWithFrame: frame];
+
+ scroller = [[UIScroller alloc] initWithFrame: frame];
+ [scroller setScrollingEnabled: YES];
+ [scroller setAdjustForContentSizeChange: YES];
+ [scroller setClipsSubviews: YES];
+ [scroller setAllowsRubberBanding: YES];
+ [scroller setDelegate: self];
+
+
+ webView = [[UIWebView alloc] initWithFrame: frame]; //[scroller bounds]];
+ [webView setAutoresizes: YES];
+ [webView setDelegate: self];
+ //[webView setFrame: frame];
+ //[webView setAutoresizingMask: 2]; //don't reflow text... or something
+ //[webView setSmoothsFonts: true];
+ //[webView setClipsSubviews: YES];
+ //[webView setEnabledGestures: YES];
+ [webView setTilingEnabled: YES];
+ [webView setTileSize: CGSizeMake(320.0f,1000.0f)];
+ [scroller addSubview: webView];
+ [self addSubview: scroller];
+
+
+ return self;
+}
+
+@end
+
+
diff --git a/woip/app/WikiApp.h b/woip/app/WikiApp.h
new file mode 100644
index 0000000..b776849
--- /dev/null
+++ b/woip/app/WikiApp.h
@@ -0,0 +1,24 @@
+#import <UIKit/UIKit.h>
+#import "WebKitView.h"
+#import "ArticleView.h"
+#import "SearchView.h"
+#import "SearchResult.h"
+#import "SearchBar.h"
+
+#define SEARCH_VIEW 1
+#define ARTICLE_VIEW 2
+
+@interface WikiApp : UIApplication {
+ WebKitView *wkv;
+ UIWindow *window;
+ UINavigationBar *navBar;
+ SearchBar *tf;
+ UIView *mainView;
+ UITransitionView *contentView;
+ ArticleView *aview;
+ SearchView *sview;
+ struct CGRect rect;
+ int currentView;
+ NSString *currentTitle;
+}
+@end
diff --git a/woip/app/WikiApp.m b/woip/app/WikiApp.m
new file mode 100644
index 0000000..6509d26
--- /dev/null
+++ b/woip/app/WikiApp.m
@@ -0,0 +1,139 @@
+#import <CoreFoundation/CoreFoundation.h>
+#import <Foundation/Foundation.h>
+#import <UIKit/CDStructures.h>
+#import <UIKit/UIPushButton.h>
+#import <UIKit/UIThreePartButton.h>
+#import <UIKit/UINavigationBar.h>
+#import <UIKit/UIWindow.h>
+#import <UIKit/UIView-Hierarchy.h>
+#import <UIKit/UIHardware.h>
+
+#import "WebKitView.h"
+#import "WikiApp.h"
+
+@implementation WikiApp
+
+-(UINavigationBar *) createNavBar: (struct CGRect) rect {
+ struct CGSize s = [UINavigationBar defaultSize];
+ UINavigationBar *bar = [[UINavigationBar alloc]
+ initWithFrame: CGRectMake(0, 0, s.width, s.height)];
+ [bar setDelegate: self];
+ [bar enableAnimation];
+
+ return bar;
+}
+
+-(void) updateNavBar {
+ switch(currentView) {
+ case ARTICLE_VIEW:
+ [navBar showButtonsWithLeftTitle: @"Search" rightTitle: NULL leftBack: YES];
+ break;
+ case SEARCH_VIEW:
+ [navBar showButtonsWithLeftTitle: NULL rightTitle: @"Article"];
+ break;
+ }
+}
+
+-(void) switchToArticle {
+ currentView = ARTICLE_VIEW;
+ [self updateNavBar];
+ [tf hide];
+ [contentView transition: 1 toView: aview];
+}
+
+-(void) switchToSearch {
+ currentView = SEARCH_VIEW;
+ [self updateNavBar];
+ [contentView transition: 2 toView: sview];
+ [tf show];
+}
+
+-(void) navigationBar: (UINavigationBar *) bar buttonClicked: (int) button {
+ NSLog(@"Button clicked: %d", button);
+
+ switch(button) {
+ case 0:
+ [self switchToArticle];
+ break;
+ case 1:
+ [self switchToSearch];
+ break;
+ }
+}
+
+-(void) logText: (id) not {
+ NSString *str = [[not object] text];
+ NSLog(@"text changed: %@", not);
+ NSLog(@"text is now '%@'", str);
+
+ if(str != nil)
+ [sview setNeedle: str];
+}
+
+-(void) createSearchField {
+ tf = [[SearchBar alloc] initWithFrame: (CGRectMake(5, 6, 240, 30))];
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver: self
+ selector: @selector(logText:)
+ name: UITextFieldTextDidChangeNotification
+ object: tf];
+
+ [navBar addSubview: tf];
+}
+
+-(void) createArticleView: (struct CGRect) r {
+ aview = [[ArticleView alloc] initWithFrame: r];
+}
+
+-(void) createSearchView: (struct CGRect) r {
+ sview = [[SearchView alloc] initWithFrame: r];
+ [sview setParent: self];
+}
+
+-(void) setupUI {
+ currentView = SEARCH_VIEW;
+
+ rect = [UIHardware fullScreenApplicationContentRect];
+ rect.origin.x = rect.origin.y = 0.0f;
+
+ window = [[UIWindow alloc] initWithContentRect: [UIHardware fullScreenApplicationContentRect]];
+
+ mainView = [[UITransitionView alloc] initWithFrame: rect];
+
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ float bgColor[4] = {0.2, 0.2, 0.2, 1};
+ CGColorRef bgRef = CGColorCreate(colorSpace, bgColor);
+ [mainView setBackgroundColor: bgRef];
+
+ navBar = [self createNavBar: rect];
+ [mainView addSubview: navBar];
+
+ struct CGSize s = [UINavigationBar defaultSize];
+ struct CGRect r = CGRectMake(0, 0, rect.size.width, rect.size.height - s.height);
+ contentView = [[UITransitionView alloc]
+ initWithFrame: CGRectMake(0, s.height, rect.size.width, rect.size.height - s.height)];
+ [mainView addSubview: contentView];
+
+ [self createSearchField];
+
+ [self updateNavBar];
+ [window orderFront: self];
+ [window makeKey: self];
+ [window _setHidden: NO];
+ [window setContentView: mainView];
+
+ [self createSearchView: r];
+ [self createArticleView: r];
+ [sview setArticleView: aview];
+ [contentView addSubview: sview];
+}
+
+- (void) applicationDidFinishLaunching: (id) unused
+{
+ [self setupUI];
+
+ [aview updateHTML: @"<html><body></body></html>"];
+}
+
+@end
diff --git a/woip/app/main.m b/woip/app/main.m
new file mode 100644
index 0000000..6a0862f
--- /dev/null
+++ b/woip/app/main.m
@@ -0,0 +1,9 @@
+#import <UIKit/UIKit.h>
+
+#import "WikiApp.h"
+
+int main(int argc, char **argv)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ return UIApplicationMain(argc, argv, [WikiApp class]);
+}