// // ICeCoffEEWebKit.m // ICeCoffEE APE // // Created by Nicholas Riley on Sun Jan 19 2003. // Copyright (c) 2003 Nicholas Riley. All rights reserved. // #import "ICeCoffEEWebKit.h" #import // WebCoreBridge, from WebCoreBridge.h (Safari 2) // Web(Core)FrameBridge, from WebCoreFrameBridge.h (Safari 3) @interface WebCoreBridge : NSObject // can only use setMarkedText:selectedRange: if WebHTMLView is editable // or, should we move to DOM-based accessors, i.e. "setMarkDOMRange"? - (void)selectNSRange:(NSRange)range; @end // from WebKit, private -- XXX maybe I'm better off going back the other way, relying on public methods in the bridge? @interface WebHTMLView : NSObject - (NSString *)selectedString; - (NSRect)selectionRect; - (NSRect)_selectionRect; // Safari 2, supported in Safari 3 only for use with Mail - (NSRange)selectedRange; // XXX same as selectedNSRange in WebCoreFrameBridge.h? - (void)deselectAll; - (WebCoreBridge *)_bridge; /* WebFrameBridge in Safari 3 (see above) */ - (NSDictionary *)elementAtPoint:(NSPoint)point; @end @implementation ICeCoffEEWebKit - (NSMenu *)menuForEvent:(NSEvent *)e; { NSMenu *myMenu = [super menuForEvent: e]; return ICCF_MenuForEvent(self, myMenu, e); } static NSEvent *downEvent = nil; static NSString *selectedString = nil; static NSRange selectedRange; - (void)mouseDown:(NSEvent *)e; { [downEvent release]; downEvent = nil; if (ICCF_enabled && ICCF_prefs.commandClickEnabled && ICCF_EventIsCommandMouseDown(e)) { if ([self respondsToSelector: @selector(selectedRange)]) { // save selection: it may be deselected on super mouseDown selectedRange = [(WebHTMLView *)self selectedRange]; } [selectedString release]; selectedString = nil; selectedString = [[(WebHTMLView *)self selectedString] retain]; downEvent = [e retain]; } [super mouseDown: e]; } - (void)mouseUp:(NSEvent *)e; { [super mouseUp: e]; if (downEvent != nil) { NSPoint downPt = [downEvent locationInWindow]; NSPoint upPt = [e locationInWindow]; if (abs(downPt.x - upPt.x) > kICHysteresisPixels && abs(downPt.y - upPt.y) > kICHysteresisPixels) return; NS_DURING NSPoint viewClickPt = [self convertPoint: downPt fromView: nil]; NSDictionary *elementDict = [(WebHTMLView *)self elementAtPoint: viewClickPt]; WebCoreBridge *bridge = [(WebHTMLView *)self _bridge]; ICLog(@"elementDict: %@", elementDict); NSAssert([elementDict count] != 0, @"Internal error: Got empty element dictionary from WebHTMLView"); if ([elementDict objectForKey: @"WebElementLinkURL"] != nil) { ICLog(@"got a link"); NS_VOIDRETURN; // don't activate on links } if (selectedString == nil || [selectedString length] == 0) { ICLog(@"no selected string"); NS_VOIDRETURN; } ICCF_StartIC(); BOOL canSetSelection = [bridge respondsToSelector: @selector(selectNSRange:)]; if (canSetSelection) { // may have become deselected in mouseDown [bridge selectNSRange: selectedRange]; } if (ICCF_LaunchURL(selectedString, ICCF_KeyboardAction(downEvent)) && ICCF_prefs.textBlinkEnabled && canSetSelection) { int i; NSRect selectionRect; if ([self respondsToSelector: @selector(selectionRect)]) selectionRect = [(WebHTMLView *)self selectionRect]; else selectionRect = [(WebHTMLView *)self _selectionRect]; ICLog(@"selectedRange %@ selectionRect %@ textBlinkCount %d", NSStringFromRange(selectedRange), NSStringFromRect(selectionRect), ICCF_prefs.textBlinkCount); for (i = 0 ; i < ICCF_prefs.textBlinkCount ; i++) { [(WebHTMLView *)self deselectAll]; [self setNeedsDisplayInRect: selectionRect]; [self display]; usleep(kICBlinkDelayUsecs); [bridge selectNSRange: selectedRange]; [self setNeedsDisplayInRect: selectionRect]; [self display]; usleep(kICBlinkDelayUsecs); } } NS_HANDLER ICCF_HandleException(localException, downEvent); NS_ENDHANDLER [downEvent release]; downEvent = nil; ICCF_StopIC(); } } @end