// // 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 // from WebCoreBridge.h @interface WebCoreBridge : NSObject - (NSDictionary *)elementAtPoint:(NSPoint)point; - (NSString *)selectedString; - (void)deselectAll; // only in Safari 1.0-1.2 - (void)setSelectionFrom:(id /* WebDOMNode */)start startOffset:(int)startOffset to:(id /* WebDOMNode */)end endOffset:(int) endOffset; - (id /* WebDOMNode */)selectionStart; - (int)selectionStartOffset; - (id /* WebDOMNode */)selectionEnd; - (int)selectionEndOffset; // only in Safari 1.1-1.2 - (NSRect)selectionRect; // only in Safari 1.3 - (void)selectNSRange:(NSRange)range; @end // from WebKit, private @interface WebHTMLView : NSObject - (WebCoreBridge *)_bridge; // only in Safari 1.3 - (NSRange)selectedRange; @end @implementation ICeCoffEEWebKit - (NSMenu *)menuForEvent:(NSEvent *)e; { NSMenu *myMenu = [super menuForEvent: e]; return ICCF_MenuForEvent(self, myMenu, e); } static NSEvent *downEvent = nil; // used in Safari < 1.3 because there's no sane way to set the selection typedef struct { int startOffset; int endOffset; id fromNode; id toNode; } ICCF_WebCoreSelection; static ICCF_WebCoreSelection selection = {nil, nil, 0, 0}; void ICCF_GetWebCoreBridgeSelection(WebCoreBridge *bridge, ICCF_WebCoreSelection *ioSel) { [ioSel->fromNode release]; ioSel->fromNode = nil; [ioSel->toNode release]; ioSel->toNode = nil; ioSel->startOffset = [bridge selectionStartOffset]; ioSel->endOffset = [bridge selectionEndOffset]; ioSel->fromNode = [[bridge selectionStart] retain]; ioSel->toNode = [[bridge selectionEnd] retain]; } void ICCF_SetWebCoreBridgeSelection(WebCoreBridge *bridge, ICCF_WebCoreSelection *inSel) { if (inSel->fromNode == nil || inSel->toNode == nil) [bridge deselectAll]; [bridge setSelectionFrom: inSel->fromNode startOffset: inSel->startOffset to: inSel->toNode endOffset: inSel->endOffset]; } // end Safari < 1.3 section static NSString *selectedString = nil; static NSRange selectedRange; - (void)mouseDown:(NSEvent *)e; { [downEvent release]; downEvent = nil; // don't want command-option-click, command-shift-click, etc. to trigger if (ICCF_enabled && ICCF_prefs.commandClickEnabled && ICCF_EventIsCommandMouseDown(e)) { WebCoreBridge *bridge = [(WebHTMLView *)self _bridge]; if ([self respondsToSelector: @selector(selectedRange)]) { // Safari 1.3 save selection: it may be deselected on super mouseDown selectedRange = [(WebHTMLView *)self selectedRange]; } else if ([bridge respondsToSelector: @selector(selectionStartOffset)]) { // Safari < 1.3 save selection: it will be deselected on super mouseDown ICCF_GetWebCoreBridgeSelection(bridge, &selection); ICLog(@"selection start %d@%@ end %d@%@ string %@", [bridge selectionStartOffset], [bridge selectionStart], [bridge selectionEndOffset], [bridge selectionEnd], [bridge selectedString]); } [selectedString release]; selectedString = nil; selectedString = [[bridge 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]; [downEvent release]; downEvent = nil; if (abs(downPt.x - upPt.x) > kICHysteresisPixels && abs(downPt.y - upPt.y) > kICHysteresisPixels) return; NS_DURING WebCoreBridge *bridge = [(WebHTMLView *)self _bridge]; NSPoint viewClickPt = [self convertPoint: downPt fromView: nil]; NSDictionary *elementDict = [bridge elementAtPoint: viewClickPt]; 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(); // ICCF_LaunchURL(selectedString, ICCF_KeyboardAction()); if (ICCF_prefs.textBlinkEnabled && [bridge respondsToSelector: @selector(selectNSRange:)]) { // blink text in Safari 1.3 [bridge selectNSRange: selectedRange]; int i; NSRect selectionRect = [bridge selectionRect]; ICLog(@"selectedRange %@ selectionRect %@ textBlinkCount %d", NSStringFromRange(selectedRange), NSStringFromRect(selectionRect), ICCF_prefs.textBlinkCount); for (i = 0 ; i < ICCF_prefs.textBlinkCount ; i++) { [bridge deselectAll]; [self setNeedsDisplayInRect: selectionRect]; [self display]; usleep(kICBlinkDelayUsecs); [bridge selectNSRange: selectedRange]; [self setNeedsDisplayInRect: selectionRect]; [self display]; usleep(kICBlinkDelayUsecs); } } else { // select text in Safari 1.0-1.2 ICCF_SetWebCoreBridgeSelection(bridge, &selection); if (ICCF_prefs.textBlinkEnabled && [bridge respondsToSelector: @selector(selectionRect)]) { // blink text in Safari 1.1/1.2 int i; NSRect selectionRect = [bridge selectionRect]; for (i = 0 ; i < ICCF_prefs.textBlinkCount ; i++) { [bridge deselectAll]; [self setNeedsDisplayInRect: selectionRect]; [self display]; usleep(kICBlinkDelayUsecs); ICCF_SetWebCoreBridgeSelection(bridge, &selection); [self setNeedsDisplayInRect: selectionRect]; [self display]; usleep(kICBlinkDelayUsecs); } } } NS_HANDLER ICCF_HandleException(localException); NS_ENDHANDLER ICCF_StopIC(); } } @end