• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

BathyScapheの中身をぐちゃぐちゃに


Commit MetaInfo

Révision33df2e0703924a88d4877d209f52b7ab68e1a220 (tree)
l'heure2012-07-02 23:03:32
Auteurmasakih <masakih@user...>
Commitermasakih

Message de Log

[New] KMLinkHanlderを新設。リンクの処理クラス。

Change Summary

Modification

--- a/application/BathyScaphe.xcodeproj/project.pbxproj
+++ b/application/BathyScaphe.xcodeproj/project.pbxproj
@@ -399,6 +399,8 @@
399399 F410E7A2153BDAAE00E3C31E /* KMLogViewRangeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F410E7A0153BDAAE00E3C31E /* KMLogViewRangeTest.m */; };
400400 F410E7A6153EE3CF00E3C31E /* CMRFavoritesManager+KMAddition.h in Headers */ = {isa = PBXBuildFile; fileRef = F410E7A4153EE3CD00E3C31E /* CMRFavoritesManager+KMAddition.h */; };
401401 F410E7A7153EE3CF00E3C31E /* CMRFavoritesManager+KMAddition.m in Sources */ = {isa = PBXBuildFile; fileRef = F410E7A5153EE3CE00E3C31E /* CMRFavoritesManager+KMAddition.m */; };
402+ F41FF6F515A1D01800B599D2 /* KMLinkHanlder.h in Headers */ = {isa = PBXBuildFile; fileRef = F41FF6F315A1D01700B599D2 /* KMLinkHanlder.h */; };
403+ F41FF6F615A1D01800B599D2 /* KMLinkHanlder.m in Sources */ = {isa = PBXBuildFile; fileRef = F41FF6F415A1D01800B599D2 /* KMLinkHanlder.m */; };
402404 F426B07F119831AA00E169D4 /* BSWhereClauseCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = F426B07D119831AA00E169D4 /* BSWhereClauseCreator.m */; };
403405 F426B080119831AA00E169D4 /* BSWhereClauseCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = F426B07E119831AA00E169D4 /* BSWhereClauseCreator.h */; };
404406 F437FD671199AF3B00D078FB /* SmartBoardItemEditor.xib in Resources */ = {isa = PBXBuildFile; fileRef = F437FD651199AF3B00D078FB /* SmartBoardItemEditor.xib */; };
@@ -1556,6 +1558,8 @@
15561558 F41308B10A8E279300740620 /* BSDownloadTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSDownloadTask.m; sourceTree = "<group>"; };
15571559 F41308B80A8E27A400740620 /* BSThreadsListOPTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSThreadsListOPTask.h; sourceTree = "<group>"; };
15581560 F41308B90A8E27A400740620 /* BSThreadsListOPTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSThreadsListOPTask.m; sourceTree = "<group>"; };
1561+ F41FF6F315A1D01700B599D2 /* KMLinkHanlder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KMLinkHanlder.h; sourceTree = "<group>"; };
1562+ F41FF6F415A1D01800B599D2 /* KMLinkHanlder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KMLinkHanlder.m; sourceTree = "<group>"; };
15591563 F426AB4B1196904900E169D4 /* Japanese */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Japanese; path = Japanese.lproj/LibraryRowTemplate.plist; sourceTree = "<group>"; };
15601564 F426B07D119831AA00E169D4 /* BSWhereClauseCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSWhereClauseCreator.m; sourceTree = "<group>"; };
15611565 F426B07E119831AA00E169D4 /* BSWhereClauseCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSWhereClauseCreator.h; sourceTree = "<group>"; };
@@ -3314,6 +3318,8 @@
33143318 F49CC8BB1546F02000341F99 /* KMBSLogPopUp.m */,
33153319 F49CC8A915438C3100341F99 /* KMReplyMessenger.h */,
33163320 F49CC8AA15438C3100341F99 /* KMReplyMessenger.m */,
3321+ F41FF6F315A1D01700B599D2 /* KMLinkHanlder.h */,
3322+ F41FF6F415A1D01800B599D2 /* KMLinkHanlder.m */,
33173323 );
33183324 name = LogViewSupport;
33193325 sourceTree = "<group>";
@@ -3668,6 +3674,7 @@
36683674 F49CC8BC1546F02000341F99 /* KMBSLogPopUp.h in Headers */,
36693675 F4C45F59154CDB9900D00D27 /* BSThreadListTask.h in Headers */,
36703676 F451BEB915555D3000CCE5C6 /* KMAppDelegate.h in Headers */,
3677+ F41FF6F515A1D01800B599D2 /* KMLinkHanlder.h in Headers */,
36713678 );
36723679 runOnlyForDeploymentPostprocessing = 0;
36733680 };
@@ -4370,6 +4377,7 @@
43704377 F49CC8BD1546F02000341F99 /* KMBSLogPopUp.m in Sources */,
43714378 F4C45F5A154CDB9900D00D27 /* BSThreadListTask.m in Sources */,
43724379 F451BEBA15555D3000CCE5C6 /* KMAppDelegate.m in Sources */,
4380+ F41FF6F615A1D01800B599D2 /* KMLinkHanlder.m in Sources */,
43734381 );
43744382 runOnlyForDeploymentPostprocessing = 0;
43754383 };
@@ -5553,8 +5561,8 @@
55535561 "-DPATCH=1",
55545562 );
55555563 PRODUCT_NAME = KakuriNoMiya;
5556- USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/source\"/**";
55575564 SKIP_INSTALL = NO;
5565+ USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/source\"/**";
55585566 WARNING_CFLAGS = "-Wmost";
55595567 WRAPPER_EXTENSION = app;
55605568 };
@@ -5581,8 +5589,8 @@
55815589 INSTALL_PATH = "$(HOME)/Applications";
55825590 LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/source\"";
55835591 PRODUCT_NAME = KakuriNoMiya;
5584- USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/source\"/**";
55855592 SKIP_INSTALL = NO;
5593+ USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/source\"/**";
55865594 WARNING_CFLAGS = "-Wmost";
55875595 WRAPPER_EXTENSION = app;
55885596 };
--- /dev/null
+++ b/application/source/KakuriNoMiya/KMLinkHanlder.h
@@ -0,0 +1,21 @@
1+//
2+// KMLinkHanlder.h
3+// BathyScaphe
4+//
5+// Created by 堀 昌樹 on 12/07/02.
6+// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7+//
8+
9+#import <Foundation/Foundation.h>
10+
11+@class KMBSLogViewController;
12+@interface KMLinkHanlder : NSObject
13+{
14+ KMBSLogViewController *_logViewController;
15+}
16+@property (assign) KMBSLogViewController *logViewController;
17+
18+- (BOOL)clickedOnLink:(id)aLink;
19+- (BOOL)isMessageLink:(id)aLink messageIndexes:(NSIndexSet **)indexesPtr;
20+
21+@end
--- /dev/null
+++ b/application/source/KakuriNoMiya/KMLinkHanlder.m
@@ -0,0 +1,320 @@
1+//
2+// KMLinkHanlder.m
3+// BathyScaphe
4+//
5+// Created by 堀 昌樹 on 12/07/02.
6+// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7+//
8+
9+#import "KMLinkHanlder.h"
10+
11+
12+#import "KMBSLogViewController.h"
13+#import <SGAppKit/NSWorkspace-SGExtensions.h>
14+
15+
16+#import "AppDefaults.h"
17+#import "SGDownloadLinkCommand.h"
18+#import "CMRHostHandler.h"
19+#import "CMRThreadLinkProcessor.h"
20+#import "CMRDocumentFileManager.h"
21+
22+
23+#define kBeProfileLinkTemplateKey @"System - be2ch Profile URL"
24+
25+
26+@implementation KMLinkHanlder
27+@synthesize logViewController = _logViewController;
28+
29+
30+- (void)openMessagesWithIndexes:(NSIndexSet *)indexes
31+{
32+ if (!indexes || [indexes count] == 0) {
33+ return;
34+ }
35+
36+ NSURL *boardURL = self.logViewController.doc.boardURL;
37+ CMRHostHandler *handler = [CMRHostHandler hostHandlerForURL:self.logViewController.doc.boardURL];
38+ NSURL *url = [handler readURLWithBoard:boardURL
39+ datName:self.logViewController.doc.datIdentifier
40+ start:[indexes firstIndex]+1
41+ end:[indexes lastIndex]+1
42+ nofirst:YES];
43+
44+ if (url) {
45+ [[NSWorkspace sharedWorkspace] openURL:url inBackground:[CMRPref openInBg]];
46+ }
47+}
48+
49+#pragma mark Previewing (or Downloading) Link
50+static inline NSString *urlPathExtension(NSURL *url)
51+{
52+ CFStringRef extensionRef = CFURLCopyPathExtension((CFURLRef)url);
53+ if (!extensionRef) {
54+ return nil;
55+ }
56+ NSString *extension = [(NSString *)extensionRef lowercaseString];
57+ CFRelease(extensionRef);
58+ return extension;
59+}
60+
61+- (NSDictionary *)refererThreadInfoForLinkDownloader
62+{
63+ return [NSDictionary dictionaryWithObjectsAndKeys:self.logViewController.doc.threadTitle, kRefererTitleKey, [self.logViewController.doc.threadURL absoluteString], kRefererURLKey, NULL];
64+}
65+
66+- (BOOL)previewOrDownloadURL:(NSURL *)url
67+{
68+ if (!url || [[url scheme] isEqualToString:@"mailto"]) {
69+ return NO;
70+ }
71+
72+ NSArray *extensions = [CMRPref linkDownloaderExtensionTypes];
73+ NSString *linkExtension = urlPathExtension(url);
74+
75+ if (linkExtension && [extensions containsObject:linkExtension]) {
76+ SGDownloadLinkCommand *dlCmd = [SGDownloadLinkCommand functorWithObject:[url absoluteString]];
77+ [dlCmd setRefererThreadInfo:[self refererThreadInfoForLinkDownloader]];
78+ [dlCmd execute:self];
79+ return YES;
80+ }
81+
82+
83+ id<BSLinkPreviewing> previewer = [CMRPref sharedLinkPreviewer];
84+ if (previewer) {
85+ return [previewer validateLink:url] ? [previewer previewLink:url] : NO;
86+ } else {
87+ id<BSImagePreviewerProtocol> oldPreviewer = [CMRPref sharedImagePreviewer];
88+ if (oldPreviewer) {
89+ return [oldPreviewer validateLink:url] ? [oldPreviewer showImageWithURL:url] : NO;
90+ }
91+ }
92+ return NO;
93+}
94+
95+- (void)openURLsWithAppStore:(NSArray *)array
96+{
97+ [[NSWorkspace sharedWorkspace] openURLs:array
98+ withAppBundleIdentifier:@"com.apple.appstore"
99+ options:NSWorkspaceLaunchDefault
100+ additionalEventParamDescriptor:nil
101+ launchIdentifiers:NULL];
102+}
103+
104+- (BOOL)handleExternalLink:(id)aLink forView:(NSView *)aView
105+{
106+ BOOL shouldPreviewWithNoModifierKey = [CMRPref previewLinkWithNoModifierKey];
107+ BOOL isOptionKeyPressed;
108+ BOOL isFileURL;
109+ NSURL *url = [NSURL URLWithLink:aLink];
110+ NSEvent *theEvent;
111+
112+ if(!url) return NO;
113+
114+ theEvent = [[aView window] currentEvent];
115+ UTILAssertNotNil(theEvent);
116+
117+ isOptionKeyPressed = (([theEvent modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask);
118+ isFileURL = [url isFileURL];
119+
120+ if ([CMRPref convertsHttpToItmsIfNeeded] && [[url host] isEqualToString:@"itunes.apple.com"]) {
121+ NSMutableString *tmp = [[url absoluteString] mutableCopy];
122+ if ([tmp hasSuffix:@"?mt=12"]) { // Mac App Store URL ?
123+ [tmp replaceCharactersInRange:NSMakeRange(0,4) withString:@"macappstore"];
124+ NSURL *newURL2 = [NSURL URLWithString:tmp];
125+ [tmp release];
126+
127+ // App Store.app が既に起動しているかどうか?
128+ NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
129+ id hoge = [apps valueForKey:@"NSApplicationBundleIdentifier"];
130+ if ([hoge containsObject:@"com.apple.appstore"]) {
131+ // 既に起動しているなら直ちに開かせる
132+ [self openURLsWithAppStore:[NSArray arrayWithObject:newURL2]];
133+ return YES;
134+ } else {
135+ // App Store.app の起動を試みる
136+ BOOL launched = [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:@"com.apple.appstore"
137+ options:NSWorkspaceLaunchWithoutActivation
138+ additionalEventParamDescriptor:nil
139+ launchIdentifier:NULL];
140+ if (launched) {
141+ // 起動できたら、遅延実行で当該アプリのページを開かせる(遅延させないとうまくいかない)
142+ NSAlert *alert = [[[NSAlert alloc] init] autorelease];
143+ [alert setAlertStyle:NSInformationalAlertStyle];
144+ [alert setMessageText:[self localizedString:@"App Store Waiting Msg"]];
145+ [alert setInformativeText:[self localizedString:@"App Store Waiting Info"]];
146+ [alert addButtonWithTitle:[self localizedString:@"App Store Continue"]];
147+ [alert addButtonWithTitle:[self localizedString:@"App Store Cancel"]];
148+ if ([alert runModal] == NSAlertFirstButtonReturn) {
149+ [self openURLsWithAppStore:[NSArray arrayWithObject:newURL2]];
150+ }
151+ return YES;
152+ } else {
153+ // App Store.app が存在しない環境か、他の何らかの理由で起動に失敗。URL を通常通り Web ブラウザで開かせる。
154+ return [[NSWorkspace sharedWorkspace] openURL:url inBackground:[CMRPref openInBg]];
155+ }
156+ }
157+ } else {
158+ [tmp replaceCharactersInRange:NSMakeRange(0,4) withString:@"itms"];
159+ NSURL *newURL = [NSURL URLWithString:tmp];
160+ [tmp release];
161+ [[NSWorkspace sharedWorkspace] openURLs:[NSArray arrayWithObject:newURL]
162+ withAppBundleIdentifier:@"com.apple.iTunes"
163+ options:NSWorkspaceLaunchDefault
164+ additionalEventParamDescriptor:nil launchIdentifiers:NULL];
165+ return YES;
166+ }
167+ }
168+
169+ if (shouldPreviewWithNoModifierKey) {
170+ if (!isOptionKeyPressed && !isFileURL) {
171+ if ([self previewOrDownloadURL:url]) return YES;
172+ }
173+ } else {
174+ if (isOptionKeyPressed && !isFileURL) {
175+ if ([self previewOrDownloadURL:url]) return YES;
176+ }
177+ }
178+ return [[NSWorkspace sharedWorkspace] openURL:url inBackground:[CMRPref openInBg]];
179+}
180+
181+- (NSIndexSet *)isStandardMessageLink:(id)aLink
182+{
183+ NSURL *link_;
184+ CMRHostHandler *handler_;
185+ NSString *bbs_;
186+ NSString *key_;
187+
188+ NSUInteger stIndex_;
189+ NSUInteger endIndex_;
190+ NSRange moveRange_;
191+
192+ link_ = [NSURL URLWithLink:aLink];
193+ handler_ = [CMRHostHandler hostHandlerForURL:link_];
194+ if (!handler_) return nil;
195+
196+ if (![handler_ parseParametersWithReadURL:link_
197+ bbs:&bbs_
198+ key:&key_
199+ start:&stIndex_
200+ to:&endIndex_
201+ showFirst:NULL]) {
202+ return nil;
203+ }
204+
205+ if (NSNotFound != stIndex_) {
206+ moveRange_.location = stIndex_ -1;
207+ moveRange_.length = (endIndex_ - stIndex_) +1;
208+ } else {
209+ return nil;
210+ }
211+
212+ // 同じ掲示板の同じスレッドならメッセージ移動処理
213+ if ([self.logViewController.doc.bbsIdentifier isEqualToString:bbs_] && [self.logViewController.doc.datIdentifier isEqualToString:key_]) {
214+ return [NSIndexSet indexSetWithIndexesInRange:moveRange_];
215+ }
216+
217+ return nil;
218+}
219+
220+- (BOOL)isMessageLink:(id)aLink messageIndexes:(NSIndexSet **)indexesPtr
221+{
222+ NSIndexSet *indexes;
223+ if (!aLink) return NO;
224+
225+ if ([CMRThreadLinkProcessor isMessageLinkUsingLocalScheme:aLink messageIndexes:indexesPtr]) {
226+ return YES;
227+ } else if ((indexes = [self isStandardMessageLink:aLink])) {
228+ if (indexesPtr != NULL) *indexesPtr = indexes;
229+ return YES;
230+ }
231+
232+ return NO;
233+}
234+
235+- (BOOL)clickedOnLink:(id)aLink
236+{
237+ NSString *boardName_;
238+ NSURL *boardURL_;
239+ NSString *filepath_;
240+ NSString *host_;
241+ NSString *beParam_;
242+ NSIndexSet *indexes;
243+
244+ // 同じスレッドのレスへのアンカー
245+ if ([self isMessageLink:aLink messageIndexes:&indexes]) {
246+ NSInteger action = [CMRPref threadViewerLinkType];
247+ if ([indexes firstIndex] != NSNotFound) {
248+ switch (action) {
249+ case ThreadViewerMoveToIndexLinkType:
250+ [self.logViewController scrollMessageAtIndex:[indexes firstIndex]];
251+ break;
252+ case ThreadViewerOpenBrowserLinkType:
253+ [self openMessagesWithIndexes:indexes];
254+ break;
255+ case ThreadViewerResPopUpLinkType:
256+ break;
257+ default:
258+ break;
259+ }
260+ }
261+
262+ return YES;
263+ }
264+
265+ // be Profile
266+ if ([CMRThreadLinkProcessor isBeProfileLinkUsingLocalScheme:aLink linkParam:&beParam_]) {
267+ NSString *template_ = SGTemplateResource(kBeProfileLinkTemplateKey);
268+ NSString *thURL_ = [self.logViewController.doc.threadURL absoluteString];
269+ // #warning 64BIT: Check formatting arguments
270+ // 2010-03-28 tsawada2 検証済
271+ NSString *tmpURL_ = [NSString stringWithFormat:template_, beParam_, thURL_];
272+
273+ NSURL *accessURL_ = [NSURL URLWithString:tmpURL_];
274+
275+ return [[NSWorkspace sharedWorkspace] openURL:accessURL_ inBackground:[CMRPref openInBg]];
276+ }
277+
278+ // 2ch thread
279+ if ([CMRThreadLinkProcessor parseThreadLink:aLink boardName:&boardName_ boardURL:&boardURL_ filepath:&filepath_ parsedHost:&host_]) {
280+ CMRDocumentFileManager *dm;
281+ NSDictionary *contentInfo_;
282+ NSString *datIdentifier_;
283+
284+ dm = [CMRDocumentFileManager defaultManager];
285+ datIdentifier_ = [dm datIdentifierWithLogPath:filepath_];
286+ contentInfo_ = [NSDictionary dictionaryWithObjectsAndKeys:
287+ [boardURL_ absoluteString], BoardPlistURLKey,
288+ boardName_, ThreadPlistBoardNameKey,
289+ datIdentifier_, ThreadPlistIdentifierKey,
290+ host_, @"candidateHost",
291+ nil];
292+
293+ [dm ensureDirectoryExistsWithBoardName:boardName_];
294+ // return [[CMRDocumentController sharedDocumentController] showDocumentWithContentOfFile:[NSURL fileURLWithPath:filepath_] boardInfo:contentInfo_];
295+ NSError *error = nil;
296+ KMDocument *document = [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:[NSURL fileURLWithPath:filepath_]
297+ display:NO
298+ error:&error];
299+ if(!document) {
300+ NSLog(@"2ch Link open Error.\n%@", error);
301+ return NO;
302+ }
303+#warning THIS IS TEST IMPLEMENTATION
304+ NSLog(@"######## THIS IS TEST IMPLEMENTATION. #######");
305+ [document addWindowController:self.logViewController.view.window.windowController];
306+ [document showWindows];
307+
308+ return YES;
309+ }
310+
311+ // 2ch (or other) BBS
312+ if ([CMRThreadLinkProcessor parseBoardLink:aLink boardName:&boardName_ boardURL:&boardURL_]) {
313+ [[NSApp delegate] showThreadsListForBoard:boardName_ selectThread:nil addToListIfNeeded:YES];
314+ return YES;
315+ }
316+
317+ // 外部リンクと判断
318+ return [self handleExternalLink:aLink forView:self.logViewController.documentView];
319+}
320+@end