// static pascal OSStatus IGraphicsCarbon::TextEntryHandler(EventHandlerCallRef pHandlerCall, EventRef pEvent, void* pGraphicsCarbon) { IGraphicsCarbon* _this = (IGraphicsCarbon*) pGraphicsCarbon; UInt32 eventClass = GetEventClass(pEvent); UInt32 eventKind = GetEventKind(pEvent); switch (eventClass) { case kEventClassKeyboard: switch (eventKind) { case kEventRawKeyDown: case kEventRawKeyRepeat: { // Get the keys and modifiers char c; UInt32 k; UInt32 modifiers; GetEventParameter(pEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &c); GetEventParameter(pEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &k); GetEventParameter(pEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); // paste if (c == 118 && modifiers == 256) { if (TXNIsScrapPastable()) { TXNPaste(_this->mTextEntryView); return eventNotHandledErr; } } // trap enter keys if (c == 3 || c == 13) { _this->EndUserInput(true); return noErr; } // trap escape key if (c == 27) { _this->EndUserInput(false); return noErr; } // pass arrow keys if (k == 125 || k == 126 || k == 123 || k == 124) return eventNotHandledErr; // pass delete keys if (c == 8 || c == 127) return eventNotHandledErr; if (_this->mEdParam) { switch ( _this->mEdParam->Type() ) { case IParam::kTypeEnum: case IParam::kTypeInt: case IParam::kTypeBool: if (c >= '0' && c <= '9') break; else if (c == '-') break; else if (c == '+') break; else return noErr; case IParam::kTypeDouble: if (c >= '0' && c <= '9') break; else if (c == '.') break; else if (c == '-') break; else if (c == '+') break; else return noErr; default: break; } } // Get the text CharsHandle textHandle; long textLength = 0; TXNGetDataEncoded(_this->mTextEntryView, kTXNStartOffset, kTXNEndOffset, &textHandle, kTXNTextData); // Check that we have some worthwhile data if (textHandle != NULL && GetHandleSize(textHandle) > 0) { textLength = GetHandleSize(textHandle); } if(textLength >= _this->mEdControl->GetTextEntryLength()) { return noErr; } else { EventRecord eventRecord; if (ConvertEventRefToEventRecord(pEvent, &eventRecord)) { TXNKeyDown(_this->mTextEntryView, &eventRecord); return noErr; } } } break; } break; case kEventClassMouse: { switch (eventKind) { case kEventMouseDown: case kEventMouseUp: { // Get the window handle WindowRef window; GetEventParameter(pEvent, kEventParamWindowRef, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window); // Determine the point HIPoint p; GetEventParameter(pEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &p); Point point = { (short)p.y, (short)p.x }; QDGlobalToLocalPoint(GetWindowPort (window), &point); // Get the viewable area Rect rect; TXNGetViewRect (_this->mTextEntryView, &rect); //swell collision #undef PtInRect #define MacPtInRect PtInRect // Handle the click as necessary if (PtInRect(point, &rect)) { #define PtInRect(r,p) SWELL_PtInRect(r,p) EventRecord eventRecord; if (eventKind == kEventMouseDown && ConvertEventRefToEventRecord(pEvent, &eventRecord)) { TXNClick(_this->mTextEntryView, &eventRecord); } return noErr; } else { CallNextEventHandler(pHandlerCall, pEvent); ClearKeyboardFocus(window); _this->EndUserInput(false); return noErr; } } break; case kEventMouseMoved: TXNAdjustCursor(_this->mTextEntryView, NULL); return noErr; case kEventMouseWheelMoved: return noErr; } break; } case kEventClassWindow: { WindowRef window; GetEventParameter (pEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window); switch (eventKind) { case kEventWindowFocusRelinquish: case kEventWindowClosed: case kEventWindowDeactivated: CallNextEventHandler(pHandlerCall, pEvent); ClearKeyboardFocus(window); _this->EndUserInput(false); return noErr; } break; } } return eventNotHandledErr; }
/* YASTControlCarbonEventHandler defines the main entry point for all of the carbon event handlers installed for the YASTControl. */ static pascal OSStatus YASTControlCarbonEventHandler( EventHandlerCallRef myHandler, EventRef event, void* userData) { #pragma unused ( myHandler ) OSStatus err, returnedResult; YASTControlVarsPtr varsp; UInt32 eclass, ekind; /* set up locals */ eclass = GetEventClass(event); ekind = GetEventKind(event); varsp = (YASTControlVarsPtr) userData; returnedResult = eventNotHandledErr; /* dispatch the event by class*/ switch (eclass) { case kEventClassWindow: if ( ekind == kEventWindowCursorChange ) { Point where; UInt32 modifiers; Boolean cursorWasSet; /* get the mouse position */ err = GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(where), NULL, &where); if (err == noErr) { err = GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); if (err == noErr) { SetPort(varsp->fGrafPtr); GlobalToLocal(&where); if (PtInRect(where, &varsp->fRBounds)) { err = HandleControlSetCursor( varsp->fControl, where, modifiers, &cursorWasSet); if (err != noErr) cursorWasSet = false; if ( ! cursorWasSet ) InitCursor(); returnedResult = noErr; } } } } break; case kEventClassMouse: /* handle mouse downs in the control, but only if the control is in focus. */ if ( ekind == kEventMouseDown ) { EventRecord outEvent; if ( varsp->fInFocus ) { if (ConvertEventRefToEventRecord( event, &outEvent)) { TXNClick( varsp->fTXNObject, &outEvent); } returnedResult = noErr; } } break; case kEventClassTextInput: if ( ekind == kEventUnicodeForKeyEvent && varsp->fTabMovesFocus) { UniChar mUnicodeText[8]; UInt32 bytecount, nchars; /* get the character */ err = GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, sizeof(mUnicodeText), &bytecount, (char*) mUnicodeText); if ((err == noErr) && (bytecount >= sizeof(UniChar))) { nchars = ( bytecount / sizeof(UniChar) ); /* if it's not the tab key, forget it... */ if ( mUnicodeText[0] == '\t' ) { EventRef rawKeyEvent; Boolean shiftDown; /* is the shift key held down? */ shiftDown = false; err = GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawKeyEvent), NULL, &rawKeyEvent); if (err == noErr) { UInt32 modifiers; err = GetEventParameter(rawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); if (err == noErr) { shiftDown = ( (modifiers & shiftKey) != 0 ); } } /* advance the keyboard focus, backwards if shift is down */ if (shiftDown) ReverseKeyboardFocus( varsp->fWindow ); else AdvanceKeyboardFocus( varsp->fWindow ); /* noErr lets the CEM know we handled the event */ returnedResult = noErr; } } } break; case kEventClassControl: switch (ekind) { case kEventControlSetFocusPart: { ControlPartCode thePart; err = GetEventParameter(event, kEventParamControlPart, typeControlPartCode, NULL, sizeof(thePart), NULL, &thePart); if (err == noErr) { switch (thePart) { default: case kControlFocusNoPart: /* turn off focus */ if ( varsp->fInFocus ) { TXNFocus( varsp->fTXNObject, false); varsp->fInFocus = false; } thePart = kControlFocusNoPart; break; case kYASTControlOnlyPart: /* turn on focus */ if ( ! varsp->fInFocus ) { TXNFocus( varsp->fTXNObject, true); varsp->fInFocus = true; } thePart = kYASTControlOnlyPart; break; case kControlFocusPrevPart: /* toggle focus on/off */ case kControlFocusNextPart: varsp->fInFocus = ! varsp->fInFocus; TXNFocus( varsp->fTXNObject, varsp->fInFocus); thePart = (varsp->fInFocus ? kYASTControlOnlyPart : kControlFocusNoPart); break; } SetPort(varsp->fGrafPtr); /* calculate the next highlight state */ SetTextActivation(varsp, varsp->fIsActive && varsp->fInFocus); /* redraw the text fram and focus rectangle to indicate the new focus state */ DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); RedrawFocusOutline(varsp); } /* pass back the foocus part code */ err = SetEventParameter( event, kEventParamControlPart, typeControlPartCode, sizeof(thePart), &thePart); returnedResult = err; } break; case kEventControlHitTest: /* this event does not necessairly mean that a mouse click has occured. Here we are simply testing to see if a particular point is located inside of the control. More complicated controls would return different part codes for different parts of themselves; but, since YASTControls only advertise one part, the hit test here is more or less a boolean test. */ { ControlPartCode thePart; Point where; err = GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(where), NULL, &where); if (err == noErr) { if (PtInRect(where, &varsp->fRTextArea)) { thePart = kYASTControlOnlyPart; } else thePart = 0; err = SetEventParameter( event, kEventParamControlPart, typeControlPartCode, sizeof(thePart), &thePart); } returnedResult = err; } break; case kEventControlClick: /* here we handle focus switching on the control. Actual tracking of mouse down events in the control is performed in the kEventClassMouse mouse down handler above. */ if ( ! varsp->fInFocus ) { SetKeyboardFocus(varsp->fWindow, varsp->fControl, kYASTControlOnlyPart); returnedResult = noErr; } break; case kEventControlBoundsChanged: /* we moved, or switched size - recalculate our rectangles */ { Rect bounds; err = GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(bounds), NULL, &bounds); if (err == noErr) { YASTControlCalculateBounds(varsp, &bounds); TXNSetFrameBounds( varsp->fTXNObject, varsp->fRTextArea.top, varsp->fRTextArea.left, varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrameID); } } break; case kEventControlActivate: case kEventControlDeactivate: { SetPort(varsp->fGrafPtr); varsp->fIsActive = (ekind == kEventControlActivate); SetTextActivation(varsp, varsp->fIsActive && varsp->fInFocus); /* redraw the frame */ DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); RedrawFocusOutline(varsp); returnedResult = noErr; } break; case kEventControlDraw: /* redraw the control */ SetPort(varsp->fGrafPtr); /* update the text region */ TXNDraw(varsp->fTXNObject, NULL); /* restore the drawing environment */ /* draw the text frame and focus frame (if necessary) */ DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); RedrawFocusOutline(varsp); returnedResult = noErr; break; case kEventControlSetCursor: /* cursor adjustment */ { SetPortWindowPort(varsp->fWindow); TXNAdjustCursor( varsp->fTXNObject, varsp->fRTextOutlineRegion); returnedResult = noErr; } break; case kEventControlDispose: /* RemoveEventHandler(varsp->fControlEvents); -- this call has been left out on purpose because it will be called automatically when the control is disposed. */ RemoveEventHandler(varsp->fWindowEvents); TXNDeleteObject(varsp->fTXNObject); DisposeRgn(varsp->fRTextOutlineRegion); free(varsp); /* returnedResult = noErr; -- this has been left out on purpose because we want the dispatching to continue and dispose of the control */ break; case kEventControlSetData: { ResType inTagName; Size inBufferSize; void * inBuffer; err = GetEventParameter( event, kEventParamControlDataTag, typeEnumeration, NULL, sizeof(inTagName), NULL, &inTagName); if (err == noErr) { err = GetEventParameter( event, kEventParamControlDataBuffer, typePtr, NULL, sizeof(inBuffer), NULL, &inBuffer); if (err == noErr) { err = GetEventParameter( event, kEventParamControlDataBufferSize, typeLongInteger, NULL, sizeof(inBufferSize), NULL, &inBufferSize); if (err == noErr) { err = YASTControlSetData(varsp, inTagName, inBuffer, inBufferSize); } } } returnedResult = err; } break; case kEventControlGetData: { ResType inTagName; Size inBufferSize, outBufferSize; void * inBuffer; err = GetEventParameter( event, kEventParamControlDataTag, typeEnumeration, NULL, sizeof(inTagName), NULL, &inTagName); if (err == noErr) { err = GetEventParameter( event, kEventParamControlDataBuffer, typePtr, NULL, sizeof(inBuffer), NULL, &inBuffer); if (err == noErr) { err = GetEventParameter( event, kEventParamControlDataBufferSize, typeLongInteger, NULL, sizeof(inBufferSize), NULL, &inBufferSize); if (err == noErr) { err = YASTControlGetData(varsp, inTagName, inBuffer, inBufferSize, &outBufferSize); if (err == noErr) { err = SetEventParameter( event, kEventParamControlDataBufferSize, typeLongInteger, sizeof(outBufferSize), &outBufferSize); } } } } returnedResult = err; } break; } break; case kEventClassCommand: if ( ekind == kEventProcessCommand ) { HICommand command; err = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command); if (err == noErr) { switch (command.commandID) { case kHICommandUndo: TXNUndo(varsp->fTXNObject); returnedResult = noErr; break; case kHICommandRedo: TXNRedo(varsp->fTXNObject); returnedResult = noErr; break; case kHICommandCut: ClearCurrentScrap(); err = TXNCut(varsp->fTXNObject); if (err == noErr) err = TXNConvertToPublicScrap(); returnedResult = err; break; case kHICommandCopy: ClearCurrentScrap(); err = TXNCopy(varsp->fTXNObject); if (err == noErr) err = TXNConvertToPublicScrap(); returnedResult = err; break; case kHICommandPaste: err = TXNConvertFromPublicScrap(); if (err == noErr) err = TXNPaste(varsp->fTXNObject); returnedResult = err; break; case kHICommandClear: err = TXNClear(varsp->fTXNObject); returnedResult = err; break; case kHICommandSelectAll: err = TXNSetSelection(varsp->fTXNObject, kTXNStartOffset, kTXNEndOffset); returnedResult = err; break; } } } else if ( ekind == kEventCommandUpdateStatus ) { HICommand command; TXNOffset oStartOffset, oEndOffset; TXNActionKey oActionKey; err = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command); if ((err == noErr) && ((command.attributes & kHICommandFromMenu) != 0)) { switch (command.commandID) { case kHICommandUndo: if (TXNCanUndo(varsp->fTXNObject, &oActionKey)) { EnableMenuItem(command.menu.menuRef, 0); /* required pre OS 10.2 */ EnableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); } else DisableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); returnedResult = noErr; break; case kHICommandRedo: if (TXNCanRedo(varsp->fTXNObject, &oActionKey)) { EnableMenuItem(command.menu.menuRef, 0); /* required pre OS 10.2 */ EnableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); } else DisableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); returnedResult = noErr; break; case kHICommandCut: case kHICommandCopy: case kHICommandClear: TXNGetSelection(varsp->fTXNObject, &oStartOffset, &oEndOffset); if (oStartOffset != oEndOffset) { EnableMenuItem(command.menu.menuRef, 0); /* required pre OS 10.2 */ EnableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); } else DisableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); returnedResult = noErr; break; case kHICommandPaste: if (TXNIsScrapPastable()) { EnableMenuItem(command.menu.menuRef, 0); /* required pre OS 10.2 */ EnableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); } else DisableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); returnedResult = noErr; break; case kHICommandSelectAll: if(TXNDataSize(varsp->fTXNObject) > 0) { EnableMenuItem(command.menu.menuRef, 0); /* required pre OS 10.2 */ EnableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); } else DisableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); returnedResult = noErr; break; } } } break; } return returnedResult; }