diff --git a/ChangeLog b/ChangeLog index 343fd0b62..37c251b41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2000-03-19 Richard Frith-Macdonald + + Fixes fromFred Kiefer - + * Headers/gnustep/gui/NSResponder.h: prefix ivars with underscore + and add new _menu ivar. + * Source/NSResponder.m: Change ivars and add support for Apples menu + methods. + * Source/NSWindow.m: update for change to responder ivar names. + * Source/NSInterfaceStyle.m: ditto + * Source/NSText.m: Establish cursor on starting edit. + 2000-03-18 Richard Frith-Macdonald * Source/NSSplitView.m: ([-mouseDown:]) only highlight/unhighlight diff --git a/Headers/gnustep/gui/NSResponder.h b/Headers/gnustep/gui/NSResponder.h index 9d3806490..190b5f64b 100644 --- a/Headers/gnustep/gui/NSResponder.h +++ b/Headers/gnustep/gui/NSResponder.h @@ -39,8 +39,9 @@ @interface NSResponder : NSObject { - NSInterfaceStyle interface_style; - NSResponder *next_responder; + NSInterfaceStyle _interface_style; + NSResponder *_next_responder; + NSMenu *_menu; /* * Flags for internal use by NSResponder and it's subclasses. */ diff --git a/Source/NSInterfaceStyle.m b/Source/NSInterfaceStyle.m index e24405eaf..0626a6e2d 100644 --- a/Source/NSInterfaceStyle.m +++ b/Source/NSInterfaceStyle.m @@ -74,7 +74,7 @@ NSInterfaceStyleForKey(NSString *key, NSResponder *responder) */ if (responder) { - style = (NSInterfaceStyle)((accessToResponder)responder)->interface_style; + style = (NSInterfaceStyle)((accessToResponder)responder)->_interface_style; if (style != NSNoInterfaceStyle) { return style; diff --git a/Source/NSResponder.m b/Source/NSResponder.m index e0ec4e10d..029086e45 100644 --- a/Source/NSResponder.m +++ b/Source/NSResponder.m @@ -58,12 +58,12 @@ */ - (id) nextResponder { - return next_responder; + return _next_responder; } - (void) setNextResponder: (NSResponder*)aResponder { - next_responder = aResponder; + _next_responder = aResponder; } /* @@ -103,10 +103,10 @@ else { /* If we cannot perform then try the next responder */ - if (!next_responder) + if (!_next_responder) return NO; else - return [next_responder tryToPerform: anAction with: anObject]; + return [_next_responder tryToPerform: anAction with: anObject]; } } @@ -117,7 +117,68 @@ - (void) interpretKeyEvents:(NSArray*)eventArray { - // FIXME: As NSInputManger is still missing this method does nothing + // FIXME: As NSInputManger is still missing this method is hard coded + unsigned short keyCode; + NSEvent *theEvent; + NSEnumerator *eventEnum = [eventArray objectEnumerator]; + + while((theEvent = [eventEnum nextObject]) != nil) + { + keyCode = [theEvent keyCode]; + + switch (keyCode) + { + case NSUpArrowFunctionKey: + [self doCommandBySelector: @selector(moveUp:)]; + break; + case NSDownArrowFunctionKey: + [self doCommandBySelector: @selector(moveDown:)]; + break; + case NSLeftArrowFunctionKey: + [self doCommandBySelector: @selector(moveLeft:)]; + break; + case NSRightArrowFunctionKey: + [self doCommandBySelector: @selector(moveRight:)]; + break; + case NSDeleteFunctionKey: + [self doCommandBySelector: @selector(deleteForward:)]; + break; + case NSHomeFunctionKey: + [self doCommandBySelector: @selector(moveToBeginningOfDocument:)]; + break; + case NSBeginFunctionKey: + [self doCommandBySelector: @selector(moveToBeginningOfLine:)]; + break; + case NSEndFunctionKey: + [self doCommandBySelector: @selector(moveToEndOfLine:)]; + break; + case NSPageUpFunctionKey: + [self doCommandBySelector: @selector(pageUp:)]; + break; + case NSPageDownFunctionKey: + [self doCommandBySelector: @selector(pageDown:)]; + break; + case 0x0008: + //BackspaceKey + [self doCommandBySelector: @selector(deleteBackward:)]; + break; + case 0x0009: + // TabKey + if ([theEvent modifierFlags] & NSShiftKeyMask) + [self doCommandBySelector: @selector(insertBacktab:)]; + else + [self doCommandBySelector: @selector(insertTab:)]; + break; + case 0x000a: + case 0x000d: + // Enter, Newline + [self doCommandBySelector: @selector(insertNewline:)]; + break; + default: + // If the character(s) was not a special one, simply insert it. + [self insertText: [theEvent characters]]; + } + } } - (void) flushBufferedKeyEvents @@ -135,8 +196,8 @@ */ - (void) flagsChanged: (NSEvent*)theEvent { - if (next_responder) - return [next_responder flagsChanged: theEvent]; + if (_next_responder) + return [_next_responder flagsChanged: theEvent]; else return [self noResponderFor: @selector(flagsChanged:)]; } @@ -146,71 +207,71 @@ if(![[NSHelpManager sharedHelpManager] showContextHelpForObject: self locationHint: [theEvent locationInWindow]]) - if (next_responder) - return [next_responder helpRequested: theEvent]; + if (_next_responder) + return [_next_responder helpRequested: theEvent]; [NSHelpManager setContextHelpModeActive: NO]; } - (void) keyDown: (NSEvent*)theEvent { - if (next_responder) - return [next_responder keyDown: theEvent]; + if (_next_responder) + return [_next_responder keyDown: theEvent]; else return [self noResponderFor: @selector(keyDown:)]; } - (void) keyUp: (NSEvent*)theEvent { - if (next_responder) - return [next_responder keyUp: theEvent]; + if (_next_responder) + return [_next_responder keyUp: theEvent]; else return [self noResponderFor: @selector(keyUp:)]; } - (void) mouseDown: (NSEvent*)theEvent { - if (next_responder) - return [next_responder mouseDown: theEvent]; + if (_next_responder) + return [_next_responder mouseDown: theEvent]; else return [self noResponderFor: @selector(mouseDown:)]; } - (void) mouseDragged: (NSEvent*)theEvent { - if (next_responder) - return [next_responder mouseDragged: theEvent]; + if (_next_responder) + return [_next_responder mouseDragged: theEvent]; else return [self noResponderFor: @selector(mouseDragged:)]; } - (void) mouseEntered: (NSEvent*)theEvent { - if (next_responder) - return [next_responder mouseEntered: theEvent]; + if (_next_responder) + return [_next_responder mouseEntered: theEvent]; else return [self noResponderFor: @selector(mouseEntered:)]; } - (void) mouseExited: (NSEvent*)theEvent { - if (next_responder) - return [next_responder mouseExited: theEvent]; + if (_next_responder) + return [_next_responder mouseExited: theEvent]; else return [self noResponderFor: @selector(mouseExited:)]; } - (void) mouseMoved: (NSEvent*)theEvent { - if (next_responder) - return [next_responder mouseMoved: theEvent]; + if (_next_responder) + return [_next_responder mouseMoved: theEvent]; else return [self noResponderFor: @selector(mouseMoved:)]; } - (void) mouseUp: (NSEvent*)theEvent { - if (next_responder) - return [next_responder mouseUp: theEvent]; + if (_next_responder) + return [_next_responder mouseUp: theEvent]; else return [self noResponderFor: @selector(mouseUp:)]; } @@ -224,9 +285,9 @@ - (void) rightMouseDown: (NSEvent*)theEvent { - if (next_responder != nil) + if (_next_responder != nil) { - return [next_responder rightMouseDown: theEvent]; + return [_next_responder rightMouseDown: theEvent]; } else { @@ -242,16 +303,16 @@ - (void) rightMouseDragged: (NSEvent*)theEvent { - if (next_responder) - return [next_responder rightMouseDragged: theEvent]; + if (_next_responder) + return [_next_responder rightMouseDragged: theEvent]; else return [self noResponderFor: @selector(rightMouseDragged:)]; } - (void) rightMouseUp: (NSEvent*)theEvent { - if (next_responder) - return [next_responder rightMouseUp: theEvent]; + if (_next_responder) + return [_next_responder rightMouseUp: theEvent]; else return [self noResponderFor: @selector(rightMouseUp:)]; } @@ -262,8 +323,8 @@ - (id) validRequestorForSendType: (NSString*)typeSent returnType: (NSString*)typeReturned { - if (next_responder) - return [next_responder validRequestorForSendType: typeSent + if (_next_responder) + return [_next_responder validRequestorForSendType: typeSent returnType: typeReturned]; else return nil; @@ -271,41 +332,46 @@ /* * NSCoding protocol - * NB. Don't encode responder chanin - it's transient information that should - * be reconstructed from elsewhere in the encoded archive. + * NB. Don't encode responder chain - it's transient information that should + * be reconstructed from else where in the encoded archive. */ - (void) encodeWithCoder: (NSCoder*)aCoder { [aCoder encodeValueOfObjCType: @encode(NSInterfaceStyle) - at: &interface_style]; + at: &_interface_style]; + [aCoder encodeObject: _menu]; } - (id) initWithCoder: (NSCoder*)aDecoder { + id obj; + [aDecoder decodeValueOfObjCType: @encode(NSInterfaceStyle) - at: &interface_style]; + at: &_interface_style]; + obj = [aDecoder decodeObject]; + [self setMenu: obj]; + return self; } - (NSMenu*) menu { - // FIXME: We need a slot for the menu - return nil; + return _menu; } - (void) setMenu: (NSMenu*)aMenu { - // FIXME: We need a slot for the menu + ASSIGN(_menu, aMenu); } - (NSInterfaceStyle) interfaceStyle { - return interface_style; + return _interface_style; } - (void) setInterfaceStyle: (NSInterfaceStyle)aStyle { - interface_style = aStyle; + _interface_style = aStyle; } - (NSUndoManager*) undoManager diff --git a/Source/NSText.m b/Source/NSText.m index c89cdffc4..dcf6e4738 100644 --- a/Source/NSText.m +++ b/Source/NSText.m @@ -262,12 +262,12 @@ static NSRange MakeRangeFromAbs (int a1,int a2) // not the same as NSMakeRange! - (NSRect) rectForCharacterIndex: (unsigned)index; - (void) _editedRange: (NSRange)aRange withDelta: (int)delta; -- (int) rebuildLineLayoutInformation; +- (void) _buildUpLayout; - (void) drawRect: (NSRect)rect withSelection: (NSRange)range; // GNU utility methods - +- (void) _illegalMovement: (int) notNumber; - (BOOL) performPasteOperation: (NSPasteboard*)pboard; /* @@ -307,7 +307,6 @@ withAttributedString: (NSAttributedString*) aString; - (void) setAttributedString: (NSAttributedString*) aString; - (NSSize) _sizeOfRange: (NSRange) range; - (NSRect) _textBounds; -- (NSDictionary*) defaultTypingAttributes; - (unsigned) characterIndexForPoint: (NSPoint)point; @@ -339,9 +338,10 @@ withAttributedString: (NSAttributedString*) aString; withAttributedString: (NSAttributedString*)aString { _textHolder = aTextHolder; - ASSIGN(_textStorage, aString); + [self setAttributedString: aString]; return self; } + - (void) setAttributedString: (NSAttributedString*)aString { ASSIGN(_textStorage, aString); @@ -377,11 +377,6 @@ withAttributedString: (NSAttributedString*) aString; return NSZeroRect; } -- (NSDictionary*) defaultTypingAttributes -{ - return [_textHolder defaultTypingAttributes]; -} - - (int) lineLayoutIndexForCharacterIndex: (unsigned)anIndex { NSEnumerator *lineEnum; @@ -519,8 +514,7 @@ withAttributedString: (NSAttributedString*) aString; { NSRect rect = [currentInfo lineRect]; NSSize stringSize - = [self _sizeOfRange: - MakeRangeFromAbs (range.location, index)]; + = [self _sizeOfRange: MakeRangeFromAbs (range.location, index)]; float x = rect.origin.x + stringSize.width; return NSMakeRect (x, rect.origin.y, NSMaxX (rect) - x, @@ -1205,6 +1199,8 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) } } +// Draws the lines in the given rectangle and hands back the drawn +// character range. - (NSRange) drawRectCharacters: (NSRect)rect { NSRange aRange = [self lineRangeForRect: rect]; @@ -1294,8 +1290,8 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) [self setTextColor: [NSColor textColor]]; _default_font = RETAIN([NSFont userFontOfSize: 12]); // sets up the contents object - [self setString: @"Text"]; - [self setSelectedRange: NSMakeRange (0, 0)]; + [self setString: @""]; + //[self setSelectedRange: NSMakeRange (0, 0)]; return self; } @@ -1344,7 +1340,7 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) initWithString: aString attributes: [self defaultTypingAttributes]]; - [self rebuildLineLayoutInformation]; + [self _buildUpLayout]; [self sizeToFit]; [self setSelectedRangeNoDrawing: NSMakeRange (0, 0)]; [self setNeedsDisplay: YES]; @@ -1442,7 +1438,10 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) _tf.is_editable = flag; // If we are editable then we are selectable if (flag) - _tf.is_selectable = YES; + { + _tf.is_selectable = YES; + // FIXME: We should show the insertion point + } } - (void) setFieldEditor: (BOOL)flag @@ -1516,7 +1515,7 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) if (!_window) return; - if (_window && [[self class] focusView] != self) + if ([[self class] focusView] != self) { [self lockFocus]; didLock = YES; @@ -2207,112 +2206,71 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) - (void) keyDown: (NSEvent*)theEvent { - unsigned short keyCode; - // If not editable then don't recognize the key down if (!_tf.is_editable) { [super keyDown: theEvent]; + } + else + { + [self interpretKeyEvents: [NSArray arrayWithObject: theEvent]]; + } +} + +- (void) insertNewline: (id) sender +{ + if (_tf.is_field_editor) + { + [self _illegalMovement: NSReturnTextMovement]; return; } - keyCode = [theEvent keyCode]; + [self insertText: [[self class] newlineString]]; +} - // Some keys are extremely special if we are field editor - if ([self isFieldEditor]) +- (void) insertTab: (id) sender +{ + if (_tf.is_field_editor) { - int notNumber = NSIllegalTextMovement; - - switch (keyCode) - { - case NSUpArrowFunctionKey: - notNumber = NSUpTextMovement; - break; - case NSDownArrowFunctionKey: - notNumber = NSDownTextMovement; - break; - case NSLeftArrowFunctionKey: - //notNumber = NSLeftTextMovement; - break; - case NSRightArrowFunctionKey: - //notNumber = NSRightTextMovement; - break; - case NSCarriageReturnKey: - notNumber = NSReturnTextMovement; - break; - case 0x09: - if ([theEvent modifierFlags] & NSShiftKeyMask) - notNumber = NSBacktabTextMovement; - else - notNumber = NSTabTextMovement; - break; - } - if (notNumber != NSIllegalTextMovement) - { - // This is similar to [self resignFirstResponder], - // with the difference that in the notification we need - // to put the NSTextMovement, which resignFirstResponder - // does not. Also, if we are ending editing, we are going - // to be removed, so it's useless to update any drawing. - NSNumber *number; - NSDictionary *uiDictionary; - - if (([self isEditable]) - && ([_delegate respondsToSelector: - @selector(textShouldEndEditing:)]) - && ([_delegate textShouldEndEditing: self] == NO)) - return; - - // Add any clean-up stuff here - - number = [NSNumber numberWithInt: notNumber]; - uiDictionary = [NSDictionary dictionaryWithObject: number - forKey: @"NSTextMovement"]; - [[NSNotificationCenter defaultCenter] - postNotificationName: NSTextDidEndEditingNotification - object: self - userInfo: uiDictionary]; - return; - } + [self _illegalMovement: NSTabTextMovement]; + return; } - // Special Characters for generic NSText - switch (keyCode) + [self insertText: @"\t"]; +} + +- (void) insertBacktab: (id) sender +{ + if (_tf.is_field_editor) { - case NSUpArrowFunctionKey: - [self moveUp: self]; - return; - case NSDownArrowFunctionKey: - [self moveDown: self]; - return; - case NSLeftArrowFunctionKey: - [self moveLeft: self]; - return; - case NSRightArrowFunctionKey: - [self moveRight: self]; - return; - case NSDeleteFunctionKey: - if (_selected_range.location != [self textLength]) - { - /* Not at the end of text -- delete following character */ - [self deleteRange: - [self selectionRangeForProposedRange: - NSMakeRange (_selected_range.location, 1) - granularity: NSSelectByCharacter] - backspace: NO]; - return; - } - /* end of text: behave the same way as NSBackspaceKey */ - case NSBackspaceKey: - [self deleteRange: _selected_range backspace: YES]; - return; - case NSCarriageReturnKey: - [self insertText: [[self class] newlineString]]; - return; + [self _illegalMovement: NSBacktabTextMovement]; + return; } - // If the character(s) was not a special one, simply insert it. - [self insertText: [theEvent characters]]; + //[self insertText: @"\t"]; +} + +- (void) deleteForward: (id) sender +{ + if (_selected_range.location != [self textLength]) + { + /* Not at the end of text -- delete following character */ + [self deleteRange: + [self selectionRangeForProposedRange: + NSMakeRange (_selected_range.location, 1) + granularity: NSSelectByCharacter] + backspace: NO]; + } + else + { + /* end of text: behave the same way as NSBackspaceKey */ + [self deleteBackward: sender]; + } +} + +- (void) deleteBackward: (id) sender +{ + [self deleteRange: _selected_range backspace: YES]; } // choose granularity according to keyboard modifier flags @@ -2322,6 +2280,12 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) NSPoint cursorPoint; NSRange oldRange = _selected_range; + if (_tf.is_field_editor) + { + [self _illegalMovement: NSUpTextMovement]; + return; + } + /* Do nothing if we are at beginning of text */ if (_selected_range.location == 0) return; @@ -2350,6 +2314,12 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) NSRect cursorRect; NSRange oldRange = _selected_range; + if (_tf.is_field_editor) + { + [self _illegalMovement: NSDownTextMovement]; + return; + } + /* Do nothing if we are at end of text */ if (_selected_range.location == [self textLength]) return; @@ -2575,6 +2545,8 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) _default_font = RETAIN([aDecoder decodeObject]); [aDecoder decodeValueOfObjCType: @encode(NSRange) at: &_selected_range]; + // build upt the layout information that dont get stored + [self _buildUpLayout]; return self; } @@ -2735,7 +2707,7 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) if (!_window) return; - if (_window && [[self class] focusView] != self) + if ([[self class] focusView] != self) { [self lockFocus]; didLock = YES; @@ -2847,6 +2819,35 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) _text_color, NSForegroundColorAttributeName, nil]; } + +- (void) _illegalMovement: (int) textMovement +{ + // This is similar to [self resignFirstResponder], + // with the difference that in the notification we need + // to put the NSTextMovement, which resignFirstResponder + // does not. Also, if we are ending editing, we are going + // to be removed, so it's useless to update any drawing. + NSNumber *number; + NSDictionary *uiDictionary; + + if (([self isEditable]) + && ([_delegate respondsToSelector: + @selector(textShouldEndEditing:)]) + && ([_delegate textShouldEndEditing: self] == NO)) + return; + + // Add any clean-up stuff here + + number = [NSNumber numberWithInt: textMovement]; + uiDictionary = [NSDictionary dictionaryWithObject: number + forKey: @"NSTextMovement"]; + [[NSNotificationCenter defaultCenter] + postNotificationName: NSTextDidEndEditingNotification + object: self + userInfo: uiDictionary]; + return; +} + // begin: dragging of colors and files--------------- - (unsigned int) draggingEntered: (id )sender { @@ -3056,7 +3057,6 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) object: self]; } -// FIXME: The following methods should be move to a seperate class - (unsigned) characterIndexForPoint: (NSPoint) point { return [_layoutManager characterIndexForPoint: point]; @@ -3067,7 +3067,7 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) return [_layoutManager rectForCharacterIndex: index]; } -- (int) rebuildLineLayoutInformation +- (void) _buildUpLayout { if (_layoutManager == nil) _layoutManager = [[GSSimpleLayoutManager alloc] @@ -3075,8 +3075,6 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) withAttributedString: _textStorage]; else [_layoutManager setAttributedString: _textStorage]; - - return [_layoutManager rebuildLineLayoutInformation]; } - (void) _editedRange: (NSRange) aRange @@ -3109,7 +3107,6 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) // We have to redraw the part of the selection that is inside // the redrawn lines - newRange = NSIntersectionRange(selectedCharacterRange, drawnRange); // Was there any overlapping with the selection? if ((selectedCharacterRange.length && @@ -3125,6 +3122,9 @@ scanRange(NSScanner *scanner, NSCharacterSet* aSet) NSRect drawRect = [self rectForCharacterIndex: index]; drawRect.size.width = 1; + if (drawRect.size.height == 0) + drawRect.size.height = 12; + if (flag && color == nil) color = [NSColor blackColor]; diff --git a/Source/NSWindow.m b/Source/NSWindow.m index 12e9432d3..2560763ff 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -3196,12 +3196,12 @@ resetCursorRectsForView(NSView *theView) - (NSInterfaceStyle) interfaceStyle { - return interface_style; + return [super interfaceStyle]; } - (void) setInterfaceStyle: (NSInterfaceStyle)aStyle { - interface_style = aStyle; + [super setInterfaceStyle: aStyle]; } - (void*) windowHandle