Bug Summary

File:Source/NSCell.m
Location:line 2833, column 3
Description:Incorrect decrement of the reference count of an object that is not owned at this point by the caller
Code is compiled to use reference counts

Annotated Source Code

1/** <title>NSCell</title>
2
3 <abstract>The abstract cell class</abstract>
4
5 Copyright (C) 1996-2012 Free Software Foundation, Inc.
6
7 Author: Scott Christley <scottc@net-community.com>
8 Date: 1996
9 Modifications: Felipe A. Rodriguez <far@ix.netcom.com>
10 Date: August 1998
11 Rewrite: Multiple authors
12 Date: 1999
13 Editing, formatters: Nicola Pero <nicola@brainstorm.co.uk>
14 Date: 2000
15
16 This file is part of the GNUstep GUI Library.
17
18 This library is free software; you can redistribute it and/or
19 modify it under the terms of the GNU Lesser General Public
20 License as published by the Free Software Foundation; either
21 version 2 of the License, or (at your option) any later version.
22
23 This library is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 Lesser General Public License for more details.
27
28 You should have received a copy of the GNU Lesser General Public
29 License along with this library; see the file COPYING.LIB.
30 If not, see <http://www.gnu.org/licenses/> or write to the
31 Free Software Foundation, 51 Franklin Street, Fifth Floor,
32 Boston, MA 02110-1301, USA.
33*/
34
35#import "config.h"
36#import <Foundation/NSCoder.h>
37#import <Foundation/NSDebug.h>
38#import <Foundation/NSException.h>
39#import <Foundation/NSFormatter.h>
40#import <Foundation/NSValue.h>
41#import <Foundation/NSNotification.h>
42#import <Foundation/NSNumberFormatter.h>
43#import <Foundation/NSRunLoop.h>
44#import <Foundation/NSString.h>
45#import <Foundation/NSGeometry.h>
46
47#import "AppKit/AppKitExceptions.h"
48#import "AppKit/NSAttributedString.h"
49#import "AppKit/NSApplication.h"
50#import "AppKit/NSControl.h"
51#import "AppKit/NSCell.h"
52#import "AppKit/NSClipView.h"
53#import "AppKit/NSColor.h"
54#import "AppKit/NSCursor.h"
55#import "AppKit/NSEvent.h"
56#import "AppKit/NSFont.h"
57#import "AppKit/NSGraphics.h"
58#import "AppKit/NSImage.h"
59#import "AppKit/NSMenu.h"
60#import "AppKit/NSParagraphStyle.h"
61#import "AppKit/NSStringDrawing.h"
62#import "AppKit/NSTextView.h"
63#import "AppKit/NSTextContainer.h"
64#import "AppKit/NSView.h"
65#import "AppKit/NSWindow.h"
66#import "GNUstepGUI/GSTheme.h"
67#import "GSGuiPrivate.h"
68
69static Class colorClass;
70static Class cellClass;
71static Class fontClass;
72static Class imageClass;
73
74static NSColor *txtCol;
75static NSColor *dtxtCol;
76
77@interface NSCell (PrivateColor)
78+ (void) _systemColorsChanged: (NSNotification*)n;
79@end
80
81
82@implementation NSCell (PrivateColor)
83+ (void) _systemColorsChanged: (NSNotification*)n
84{
85 ASSIGN (txtCol, [colorClass controlTextColor])({ id __object = txtCol; txtCol = [([colorClass controlTextColor
]) retain]; [__object release]; })
;
86 ASSIGN (dtxtCol, [colorClass disabledControlTextColor])({ id __object = dtxtCol; dtxtCol = [([colorClass disabledControlTextColor
]) retain]; [__object release]; })
;
87}
88@end
89
90
91/**
92 *<p> TODO Desctiption</p>
93 */
94
95@implementation NSCell
96
97/*
98 * Class methods
99 */
100+ (void) initialize
101{
102 if (self == [NSCell class])
103 {
104 [self setVersion: 3];
105 colorClass = [NSColor class];
106 cellClass = [NSCell class];
107 fontClass = [NSFont class];
108 imageClass = [NSImage class];
109 /*
110 * Watch for changes to system colors, and simulate an initial change
111 * in order to set up our defaults.
112 */
113 [[NSNotificationCenter defaultCenter]
114 addObserver: self
115 selector: @selector(_systemColorsChanged:)
116 name: NSSystemColorsDidChangeNotification
117 object: nil((id)((void*)0))];
118 [self _systemColorsChanged: nil((id)((void*)0))];
119 }
120}
121
122+ (NSMenu*) defaultMenu
123{
124 return nil((id)((void*)0));
125}
126
127+ (NSFocusRingType) defaultFocusRingType
128{
129 return NSFocusRingTypeDefault;
130}
131
132/**<p>This class method returns NO. This method should be overrided by
133 subclasses.</p>
134 */
135+ (BOOL) prefersTrackingUntilMouseUp
136{
137 return NO((BOOL)0);
138}
139
140/*
141 * Instance methods
142 */
143- (id) init
144{
145 return [self initTextCell: @""];
146}
147
148/**<p>Initializes and returns a new NSCell with a NSImage <var>anImage</var>.
149 This method sets the image position to <ref type="type"
150 id="NSCellImagePosition">NSImageOnly</ref> and the cell's type to
151 <ref type="type" id="NSCellType">NSImageCellType</ref>.</p>
152 <p>See Also: -initTextCell: </p>
153 */
154- (id) initImageCell: (NSImage*)anImage
155{
156 _cell.type = NSImageCellType;
157 _cell_image = RETAIN (anImage)[(anImage) retain];
158 _cell.image_position = NSImageOnly;
159 _font = RETAIN ([fontClass systemFontOfSize: 0])[([fontClass systemFontOfSize: 0]) retain];
160
161 // Implicitly set by allocation:
162 //
163 //_font = nil;
164 //_cell.contents_is_attributed_string = NO;
165 //_cell.is_highlighted = NO;
166 //_cell.is_disabled = NO;
167 //_cell.is_editable = NO;
168 //_cell.is_rich_text = NO;
169 //_cell.imports_graphics = NO;
170 //_cell.shows_first_responder = NO;
171 //_cell.refuses_first_responder = NO;
172 //_cell.sends_action_on_end_editing = NO;
173 //_cell.is_bordered = NO;
174 //_cell.is_bezeled = NO;
175 //_cell.is_scrollable = NO;
176 //_cell.is_selectable = NO;
177 //_cell.state = 0;
178 //_cell.line_break_mode = NSLineBreakByWordWrapping;
179 _action_mask = NSLeftMouseUpMask;
180 _menu = [object_getClass(self) defaultMenu];
181 [self setFocusRingType: [object_getClass(self) defaultFocusRingType]];
182
183 return self;
184}
185/**<p>Initializes and returns a new NSCell with a NSString aString.
186 This method sets the cell's type to <ref type="type" id="NSCellType">
187 NSTextCellType</ref>.</p>
188 <p>See Also: -initImageCell: </p>
189 */
190- (id) initTextCell: (NSString*)aString
191{
192 _cell.type = NSTextCellType;
193 _contents = RETAIN (aString)[(aString) retain];
194 _font = RETAIN ([fontClass systemFontOfSize: 0])[([fontClass systemFontOfSize: 0]) retain];
195
196 // Implicitly set by allocation:
197 //
198 //_cell.contents_is_attributed_string = NO;
199 //_cell_image = nil;
200 //_cell.image_position = NSNoImage;
201 //_cell.is_disabled = NO;
202 //_cell.state = 0;
203 //_cell.is_highlighted = NO;
204 //_cell.is_editable = NO;
205 //_cell.is_bordered = NO;
206 //_cell.is_bezeled = NO;
207 //_cell.is_scrollable = NO;
208 //_cell.is_selectable = NO;
209 //_cell.line_break_mode = NSLineBreakByWordWrapping;
210 _action_mask = NSLeftMouseUpMask;
211 _menu = [object_getClass(self) defaultMenu];
212 [self setFocusRingType: [object_getClass(self) defaultFocusRingType]];
213
214 return self;
215}
216
217- (void) dealloc
218{
219 TEST_RELEASE (_contents)({id __object = (_contents); if (__object != ((id)((void*)0))
) [__object release]; })
;
220 TEST_RELEASE (_cell_image)({id __object = (_cell_image); if (__object != ((id)((void*)0
))) [__object release]; })
;
221 TEST_RELEASE (_font)({id __object = (_font); if (__object != ((id)((void*)0))) [__object
release]; })
;
222 TEST_RELEASE (_represented_object)({id __object = (_represented_object); if (__object != ((id)(
(void*)0))) [__object release]; })
;
223 TEST_RELEASE (_object_value)({id __object = (_object_value); if (__object != ((id)((void*
)0))) [__object release]; })
;
224 TEST_RELEASE (_formatter)({id __object = (_formatter); if (__object != ((id)((void*)0)
)) [__object release]; })
;
225 TEST_RELEASE (_menu)({id __object = (_menu); if (__object != ((id)((void*)0))) [__object
release]; })
;
226
227 [super dealloc];
228}
229
230/*
231 * Setting the NSCell's Value
232 */
233- (id) objectValue
234{
235 if (_cell.has_valid_object_value)
236 {
237 return _object_value;
238 }
239 else
240 {
241 return nil((id)((void*)0));
242 }
243}
244
245- (BOOL) hasValidObjectValue
246{
247 return _cell.has_valid_object_value;
248}
249
250/**<p>Returns the NSCell's value as a double. </p>
251 *<p>See Also: -setDoubleValue: </p>
252 */
253- (double) doubleValue
254{
255 if ((_cell.has_valid_object_value == YES((BOOL)1)) &&
256 ([_object_value respondsToSelector: @selector(doubleValue)]))
257 {
258 return [_object_value doubleValue];
259 }
260 else
261 {
262 return [[self stringValue] doubleValue];
263 }
264}
265
266/**<p>Returns the cell's value as a float. </p>
267 *<p>See Also: -setFloatValue: </p>
268 */
269- (float) floatValue
270{
271 if ((_cell.has_valid_object_value == YES((BOOL)1)) &&
272 ([_object_value respondsToSelector: @selector(floatValue)]))
273 {
274 return [_object_value floatValue];
275 }
276 else
277 {
278 return [[self stringValue] floatValue];
279 }
280}
281
282/**<p>Returns the cell's value as an int. </p>
283 *<p>See Also: -setIntValue:</p>
284 */
285- (int) intValue
286{
287 if ((_cell.has_valid_object_value == YES((BOOL)1)) &&
288 ([_object_value respondsToSelector: @selector(intValue)]))
289 {
290 return [_object_value intValue];
291 }
292 else
293 {
294 return [[self stringValue] intValue];
295 }
296}
297
298/**<p>Returns the cell's value as an NSInteger. </p>
299 *<p>See Also: -setIntegerValue:</p>
300 */
301- (NSInteger) integerValue
302{
303 if ((_cell.has_valid_object_value == YES((BOOL)1)) &&
304 ([_object_value respondsToSelector: @selector(integerValue)]))
305 {
306 return [_object_value integerValue];
307 }
308 else
309 {
310 return [[self stringValue] integerValue];
311 }
312}
313
314/**<p>Returns the cell's value as a NSString.</p>
315 *<p>See Also: -setStringValue: </p>
316 */
317- (NSString*) stringValue
318{
319 if (nil((id)((void*)0)) == _contents)
320 {
321 return @"";
322 }
323
324 if (_cell.contents_is_attributed_string == NO((BOOL)0))
325 {
326 // If we have a formatter this is also the string of the _object_value
327 return (NSString *)_contents;
328 }
329 else
330 {
331 return [(NSAttributedString *)_contents string];
332 }
333}
334
335- (void) setObjectValue: (id)object
336{
337 id newContents;
338
339 ASSIGN (_object_value, object)({ id __object = _object_value; _object_value = [(object) retain
]; [__object release]; })
;
340
341 if (_formatter == nil((id)((void*)0)))
342 {
343 if (object == nil((id)((void*)0)) || [object isKindOfClass: [NSString class]] == YES((BOOL)1))
344 {
345 newContents = object;
346 _cell.contents_is_attributed_string = NO((BOOL)0);
347 _cell.has_valid_object_value = YES((BOOL)1);
348 }
349 else if ([object isKindOfClass: [NSAttributedString class]] == YES((BOOL)1))
350 {
351 newContents = object;
352 _cell.contents_is_attributed_string = YES((BOOL)1);
353 _cell.has_valid_object_value = YES((BOOL)1);
354 }
355 else if ([_object_value respondsToSelector: @selector(attributedStringValue)])
356 {
357 newContents = [_object_value attributedStringValue];
358 _cell.contents_is_attributed_string = YES((BOOL)1);
359 _cell.has_valid_object_value = YES((BOOL)1);
360 }
361 else if ([_object_value respondsToSelector: @selector(stringValue)])
362 {
363 // If the thing that was assigned is not a string, but
364 // responds to stringValue then get that.
365 newContents = [_object_value stringValue];
366 _cell.contents_is_attributed_string = NO((BOOL)0);
367 _cell.has_valid_object_value = YES((BOOL)1);
368 }
369 else
370 {
371 newContents = [_object_value description];
372 _cell.contents_is_attributed_string = NO((BOOL)0);
373 _cell.has_valid_object_value = YES((BOOL)1);
374 }
375 }
376 else
377 {
378 newContents = [_formatter stringForObjectValue: _object_value];
379 _cell.contents_is_attributed_string = NO((BOOL)0);
380 if (newContents != nil((id)((void*)0)))
381 {
382 _cell.has_valid_object_value = YES((BOOL)1);
383 }
384 else
385 {
386 _cell.has_valid_object_value = NO((BOOL)0);
387 }
388 }
389
390 ASSIGNCOPY(_contents, newContents)({ id __object = _contents; _contents = [(newContents) copy];
[__object release]; })
;
391}
392
393
394/**<p>Sets the NSCell's value to aDouble.</p>
395 *<p>See Also: -doubleValue</p>
396 */
397- (void) setDoubleValue: (double)aDouble
398{
399 NSNumber *number;
400
401 // NB: GNUstep can set a double value for an image cell
402
403 number = [NSNumber numberWithDouble: aDouble];
404 [self setObjectValue: number];
405}
406
407/**
408 *<p>Sets the NSCell's value to a aFloat. This used for example in
409 NSSliderCell</p>
410 *<p>See Also: -floatValue</p>
411 */
412- (void) setFloatValue: (float)aFloat
413{
414 NSNumber *number;
415
416 // NB: GNUstep can set a float value for an image cell.
417 // NSSliderCell is an example of it!
418
419 number = [NSNumber numberWithFloat: aFloat];
420 [self setObjectValue: number];
421}
422
423
424/**
425 *<p>Sets the NSCell's value to anInt.</p>
426 *<p>See Also: -intValue</p>
427 */
428- (void) setIntValue: (int)anInt
429{
430 NSNumber *number;
431
432 // NB: GNUstep can set an int value for an image cell.
433
434 number = [NSNumber numberWithInt: anInt];
435 [self setObjectValue: number];
436}
437
438/**
439 *<p>Sets the NSCell's value to anInt.</p>
440 *<p>See Also: -integerValue</p>
441 */
442- (void) setIntegerValue: (NSInteger)anInt
443{
444 NSNumber *number;
445
446 // NB: GNUstep can set an int value for an image cell.
447
448 number = [NSNumber numberWithInteger: anInt];
449 [self setObjectValue: number];
450}
451
452/**<p>Sets the cell's value to a NSString.
453 The NSCell's type is set to NSTextCellType if needed</p>
454 <p>See Also: -stringValue</p>
455 */
456- (void) setStringValue: (NSString*)aString
457{
458 /* We warn about nil for compatibiliy with MacOS X, which refuses
459 nil. */
460 if (aString == nil((id)((void*)0)))
461 {
462 NSDebugMLLog (@"MacOSXCompatibility",do { if (GSDebugSet(@"MacOSXCompatibility") == ((BOOL)1)) { NSString
*s = GSDebugFunctionMsg( __PRETTY_FUNCTION__, "NSCell.m", 463
, [NSString stringWithFormat: @"Attempt to use nil as string value"
]); NSLog(@"%@", s); }} while (0)
463 @"Attempt to use nil as string value")do { if (GSDebugSet(@"MacOSXCompatibility") == ((BOOL)1)) { NSString
*s = GSDebugFunctionMsg( __PRETTY_FUNCTION__, "NSCell.m", 463
, [NSString stringWithFormat: @"Attempt to use nil as string value"
]); NSLog(@"%@", s); }} while (0)
;
464 }
465
466 if (_cell.type != NSTextCellType)
467 {
468 [self setType: NSTextCellType];
469 }
470
471 if (_formatter == nil((id)((void*)0)))
472 {
473 [self setObjectValue: aString];
474 }
475 else
476 {
477 id newObjectValue;
478
479 if ([_formatter getObjectValue: &newObjectValue
480 forString: aString
481 errorDescription: NULL((void *)0)])
482 {
483 [self setObjectValue: newObjectValue];
484 }
485 else
486 {
487 ASSIGNCOPY(_contents, aString)({ id __object = _contents; _contents = [(aString) copy]; [__object
release]; })
;
488 _cell.contents_is_attributed_string = NO((BOOL)0);
489 _cell.has_valid_object_value = NO((BOOL)0);
490 }
491 }
492}
493
494/**<p>Returns some NSCell's attributes for the specified <ref type="type"
495 id="NSCellAttribute">NSCellAttribute</ref></p>
496 <p>See Also: -setCellAttribute:to:</p>
497 */
498- (int) cellAttribute: (NSCellAttribute)aParameter
499{
500 switch (aParameter)
501 {
502 case NSCellDisabled: return _cell.is_disabled;
503 case NSCellState: return _cell.state;
504 case NSCellEditable: return _cell.is_editable;
505 case NSCellHighlighted: return _cell.is_highlighted;
506 case NSCellIsBordered: return _cell.is_bordered;
507 case NSCellAllowsMixedState: return _cell.allows_mixed_state;
508
509 /*
510 case NSPushInCell: return 0;
511 case NSChangeGrayCell: return 0;
512 case NSCellLightsByContents: return 0;
513 case NSCellLightsByGray: return 0;
514 case NSChangeBackgroundCell: return 0;
515 case NSCellLightsByBackground: return 0;
516 case NSCellChangesContents: return 0;
517 case NSCellIsInsetButton: return 0;
518 */
519 case NSCellHasOverlappingImage:
520 {
521 return _cell.image_position == NSImageOverlaps;
522 }
523 case NSCellHasImageHorizontal:
524 {
525 return (_cell.image_position == NSImageRight)
526 || (_cell.image_position == NSImageLeft);
527 }
528 case NSCellHasImageOnLeftOrBottom:
529 {
530 return (_cell.image_position == NSImageBelow)
531 || (_cell.image_position == NSImageLeft);
532 }
533 default:
534 {
535 NSWarnLog (@"cell attribute %d not supported", aParameter)do { if (GSDebugSet(@"NoWarn") == ((BOOL)0)) { NSLog(@"cell attribute %d not supported"
, aParameter); }} while (0)
;
536 break;
537 }
538 }
539
540 return 0;
541}
542
543
544/**<p>TODO</p>
545 *<p>See Also: -cellAttribute:</p>
546 */
547- (void) setCellAttribute: (NSCellAttribute)aParameter to: (int)value
548{
549 switch (aParameter)
550 {
551 case NSCellDisabled:
552 {
553 _cell.is_disabled = value;
554 break;
555 }
556 case NSCellState:
557 {
558 _cell.state = value;
559 break;
560 }
561 case NSCellEditable:
562 {
563 _cell.is_editable = value;
564 break;
565 }
566 case NSCellHighlighted:
567 {
568 _cell.is_highlighted = value;
569 break;
570 }
571 case NSCellHasOverlappingImage:
572 {
573 if (value)
574 {
575 _cell.image_position = NSImageOverlaps;
576 }
577 else
578 {
579 if (_cell.image_position == NSImageOverlaps)
580 {
581 _cell.image_position = NSImageLeft;
582 }
583 }
584 break;
585 }
586 case NSCellHasImageHorizontal:
587 {
588 if (value)
589 {
590 if (_cell.image_position != NSImageLeft
591 && _cell.image_position != NSImageRight)
592 {
593 _cell.image_position = NSImageLeft;
594 }
595 }
596 else
597 {
598 if (_cell.image_position == NSImageLeft)
599 {
600 _cell.image_position = NSImageAbove;
601 }
602 else if (_cell.image_position == NSImageRight)
603 {
604 _cell.image_position = NSImageBelow;
605 }
606 }
607 break;
608 }
609 case NSCellHasImageOnLeftOrBottom:
610 {
611 if (value)
612 {
613 if (_cell.image_position == NSImageAbove)
614 {
615 _cell.image_position = NSImageBelow;
616 }
617 else
618 {
619 _cell.image_position = NSImageLeft;
620 }
621 }
622 else
623 {
624 if (_cell.image_position == NSImageBelow)
625 {
626 _cell.image_position = NSImageAbove;
627 }
628 else
629 {
630 _cell.image_position = NSImageRight;
631 }
632 }
633 break;
634 }
635 /*
636 case NSCellChangesContents:
637 _cell. = value;
638 break;
639 case NSCellIsInsetButton:
640 _cell. = value;
641 break;
642*/
643 case NSCellIsBordered:
644 {
645 _cell.is_bordered = value;
646 break;
647 }
648 case NSCellAllowsMixedState:
649 {
650 _cell.allows_mixed_state = value;
651 break;
652 }
653 default:
654 {
655 NSWarnLog (@"cell attribute %d not supported", aParameter)do { if (GSDebugSet(@"NoWarn") == ((BOOL)0)) { NSLog(@"cell attribute %d not supported"
, aParameter); }} while (0)
;
656 break;
657 }
658 }
659}
660
661/**<p>Sets the NSCell's type. See <ref type="type" id="NSCellType">NSCellType
662 </ref>.If the cell is set to NSTextCellType, the cell is given
663 a default title and is reset to the default system font.</p>
664 <p>See Also: -type</p>
665*/
666- (void) setType: (NSCellType)aType
667{
668 if (_cell.type == aType)
669 {
670 return;
671 }
672
673 _cell.type = aType;
674 switch (_cell.type)
675 {
676 case NSTextCellType:
677 {
678 ASSIGN (_contents, @"title")({ id __object = _contents; _contents = [(@"title") retain]; [
__object release]; })
;
679 _cell.contents_is_attributed_string = NO((BOOL)0);
680 /* Doc says we have to reset the font too. */
681 ASSIGN (_font, [fontClass systemFontOfSize: 0])({ id __object = _font; _font = [([fontClass systemFontOfSize
: 0]) retain]; [__object release]; })
;
682 break;
683 }
684 case NSImageCellType:
685 {
686 TEST_RELEASE (_cell_image)({id __object = (_cell_image); if (__object != ((id)((void*)0
))) [__object release]; })
;
687 _cell_image = nil((id)((void*)0));
688 break;
689 }
690 }
691}
692
693/**<p>Returns the cell's type. Returns NSNullCellType if the
694 cell's type flag is set to NSImageCellType and if the cell's image
695 is nil. See <ref type="type" id="NSCellType">NSCellType</ref> for more
696 information.</p><p>See Also -setType:</p>
697 */
698- (NSCellType) type
699{
700 if (_cell.type == NSImageCellType && _cell_image == nil((id)((void*)0)))
701 return NSNullCellType;
702
703 return _cell.type;
704}
705
706
707/**<p>Returns whether the NSCell can respond to mouse events.</p>
708 *<p>See Also: -setEnabled:</p>
709 */
710- (BOOL) isEnabled
711{
712 return !_cell.is_disabled;
713}
714
715/**<p>Sets whether the NSCell can respond to mouse events</p>
716 <p>See Also: -isEnabled</p>
717 */
718- (void) setEnabled: (BOOL)flag
719{
720 _cell.is_disabled = !flag;
721}
722
723/**<p>Returns whether the NSCell has a bezeled border. By default a NSCell
724 has no bezeled border</p><p>See Also: -setBezeled:</p>
725 */
726- (BOOL) isBezeled
727{
728 return _cell.is_bezeled;
729}
730
731/**<p>Returns whether the NSCell has a border. By default a NSCell has
732 border</p><p>See Also: -setBordered: -setBezeled: -isBezeled</p>
733 */
734- (BOOL) isBordered
735{
736 return _cell.is_bordered;
737}
738
739/**<p>Returns whether the cell is opaque. Return NO by default</p>
740 */
741- (BOOL) isOpaque
742{
743 return NO((BOOL)0);
744}
745
746/**<p>Sets whether the cell has a bezeled border.
747 If this method is called, the bordered flag is turn off.
748 By default a NSCell has no bezeled border</p>
749 <p>See Also: -isBezeled -setBordered: -isBordered</p>
750 */
751- (void) setBezeled: (BOOL)flag
752{
753 _cell.is_bezeled = flag;
754 _cell.is_bordered = NO((BOOL)0);
755}
756
757/**<p>Sets whether the cell has a border. If this method is called,
758 the bezeled flag is turn off. By default a NSCell has no border</p>
759 <p>See Also: -isBordered -setBezeled: -isBezeled</p>
760 */
761- (void) setBordered: (BOOL)flag
762{
763 _cell.is_bordered = flag;
764 _cell.is_bezeled = NO((BOOL)0);
765}
766
767- (NSFocusRingType) focusRingType
768{
769 return _cell.focus_ring_type;
770}
771
772- (void) setFocusRingType: (NSFocusRingType)type
773{
774 _cell.focus_ring_type = type;
775}
776
777/**<p>Sets the NSCell's state. Please use always symbolic constants when
778 calling this method. The integer values could be changed in the this
779 implementation. (Currently they match the Cocoa values but they are
780 quite strange)</p> <p>See Also: -state</p>
781 */
782- (void) setState: (NSInteger)value
783{
784 /* We do exactly as in macosx when value is not NSOnState,
785 * NSOffState, NSMixedState, even if their behaviour (value < 0 ==>
786 * NSMixedState) is a bit strange. We could decide to do
787 * differently in the future, so please use always symbolic
788 * constants when calling this method, this way your code won't be
789 * broken by changes. */
790 if (value > 0 || (value < 0 && _cell.allows_mixed_state == NO((BOOL)0)))
791 {
792 _cell.state = NSOnState;
793 }
794 else if (value == 0)
795 {
796 _cell.state = NSOffState;
797 }
798 else
799 {
800 _cell.state = NSMixedState;
801 }
802}
803
804/**<p>Returns the NSCell's state</p>
805 <p>See Also: -setState: </p>
806*/
807- (NSInteger) state
808{
809 return _cell.state;
810}
811
812- (BOOL) allowsMixedState
813{
814 return _cell.allows_mixed_state;
815}
816
817- (void) setAllowsMixedState: (BOOL)flag
818{
819 _cell.allows_mixed_state = flag;
820 if (!flag && _cell.state == NSMixedState)
821 {
822 [self setNextState];
823 }
824}
825
826- (NSInteger) nextState
827{
828 switch (_cell.state)
829 {
830 case NSOnState:
831 {
832 return NSOffState;
833 }
834 case NSOffState:
835 {
836 if (_cell.allows_mixed_state)
837 {
838 return NSMixedState;
839 }
840 else
841 {
842 return NSOnState;
843 }
844 }
845 case NSMixedState:
846 default:
847 {
848 return NSOnState;
849 }
850 }
851}
852
853- (void) setNextState
854{
855 [self setState: [self nextState]];
856}
857
858/**<p>Returns the alignment of the text used in the NSCell. See
859 <ref type="type" id="NSTextAlignment">NSTextAlignment</ref> for more
860 informations. By default the text alignment is <ref type="type"
861 id="NSTextAlignment">NSJustifiedTextAlignment</ref></p>
862 <p>See Also: -setAlignment:</p>
863 */
864- (NSTextAlignment) alignment
865{
866 return _cell.text_align;
867}
868
869/** <p>Returns the font of the text used in the NSCell</p>
870 <p>See Also: -setFont:</p>
871 */
872- (NSFont*) font
873{
874 return _font;
875}
876
877/**<p>Returns whether the cell is editable.By default a NSCell is not editable.
878 </p><p>See Also: -setEditable:</p>
879 */
880- (BOOL) isEditable
881{
882 return _cell.is_editable;
883}
884
885/**<p>Returns whether the cell is selectable. This method returns YES if
886 the cell is selectable or editable. NO otherwise</p>
887 <p>See Also: -setSelectable: -isEditable -setEditable: </p>
888 */
889- (BOOL) isSelectable
890{
891 return _cell.is_selectable || _cell.is_editable;
892}
893
894/**<p>Returns whether the NSCell is scrollable. By default a NSCell is not
895 scrollable</p><p>See Also: -setScrollable:</p>
896 */
897- (BOOL) isScrollable
898{
899 return _cell.is_scrollable;
900}
901
902/**<p>Sets the alignment of the text. See <ref type="type"
903 id="NSTextAlignment">NSTextAlignment</ref>.</p><p>See Also: -alignment </p>
904 */
905- (void) setAlignment: (NSTextAlignment)mode
906{
907 // This does not have any influence on attributed strings
908 _cell.text_align = mode;
909}
910
911/**<p>Sets whether the NSCell's text is editable.</p>
912 <p>See Also: -isEditable -setSelectable: -isSelectable</p>
913*/
914- (void) setEditable: (BOOL)flag
915{
916 /*
917 * The cell_editable flag is also checked to see if the cell is
918 * selectable so turning edit on also turns selectability on (until
919 * edit is turned off again).
920 */
921 _cell.is_editable = flag;
922}
923
924/**<p>Sets the text font. The NSCell's type is set to NSTextCellType if needed
925 </p><p>See Also: -font -setType: -type</p>
926 */
927- (void) setFont: (NSFont*)fontObject
928{
929 if (_cell.type != NSTextCellType)
930 {
931 [self setType: NSTextCellType];
932 }
933
934 // This does not have any influence on attributed strings
935 ASSIGN (_font, fontObject)({ id __object = _font; _font = [(fontObject) retain]; [__object
release]; })
;
936}
937
938/**<p>Sets whether the cell selectable. Making a cell unselectable also
939 * makes it uneditable until a -setEditable: re-enables it.</p>
940 *<p>See Also: -isSelectable -setEditable: -isEditable</p>
941 */
942- (void) setSelectable: (BOOL)flag
943{
944 _cell.is_selectable = flag;
945
946 if (!flag)
947 _cell.is_editable = NO((BOOL)0);
948}
949
950/**<p>Sets whether the NCell is scrollable. By default a NSCell is not
951 scrollable</p><p>See Also: -isSelectable</p>
952 */
953- (void) setScrollable: (BOOL)flag
954{
955 _cell.is_scrollable = flag;
956 if (flag)
957 {
958 [self setWraps: NO((BOOL)0)];
959 }
960}
961
962- (void) setWraps: (BOOL)flag
963{
964 if (flag)
965 {
966 if (![self wraps])
967 [self setLineBreakMode: NSLineBreakByWordWrapping];
968 }
969 else
970 {
971 if ([self wraps])
972 [self setLineBreakMode: NSLineBreakByClipping];
973 }
974}
975
976- (BOOL) wraps
977{
978 return _cell.line_break_mode == NSLineBreakByWordWrapping
979 || _cell.line_break_mode == NSLineBreakByCharWrapping;
980}
981
982- (void) setAttributedStringValue: (NSAttributedString*)attribStr
983{
984 /* Hmm. FIXME. Not sure what to do here. */
985 if (_formatter != nil((id)((void*)0)))
986 {
987 id newObjectValue;
988
989 if ([_formatter getObjectValue: &newObjectValue
990 forString: [attribStr string]
991 errorDescription: NULL((void *)0)] == YES((BOOL)1))
992 {
993 [self setObjectValue: newObjectValue];
994 /* What about the attributed string ? We are loosing it. */
995 return;
996 }
997 _cell.has_valid_object_value = NO((BOOL)0);
998 }
999 else
1000 {
1001 _cell.has_valid_object_value = YES((BOOL)1);
1002 ASSIGN (_object_value, attribStr)({ id __object = _object_value; _object_value = [(attribStr) retain
]; [__object release]; })
;
1003 }
1004
1005 ASSIGN (_contents, attribStr)({ id __object = _contents; _contents = [(attribStr) retain];
[__object release]; })
;
1006 _cell.contents_is_attributed_string = YES((BOOL)1);
1007}
1008
1009- (NSAttributedString*) attributedStringValue
1010{
1011 if (_formatter != nil((id)((void*)0)))
1012 {
1013 NSDictionary *attributes;
1014 NSAttributedString *attrStr;
1015
1016 attributes = [self _nonAutoreleasedTypingAttributes];
1017 attrStr = [_formatter attributedStringForObjectValue: _object_value
1018 withDefaultAttributes: attributes];
1019 RELEASE(attributes)[(attributes) release];
1020 if (attrStr != nil((id)((void*)0)))
1021 {
1022 return attrStr;
1023 }
1024 }
1025
1026 /* In all other cases */
1027 if (_cell.contents_is_attributed_string &&
1028 nil((id)((void*)0)) != _contents)
1029 {
1030 return (NSAttributedString *)_contents;
1031 }
1032 else
1033 {
1034 NSDictionary *dict;
1035 NSAttributedString *attrStr;
1036
1037 dict = [self _nonAutoreleasedTypingAttributes];
1038 attrStr = [[NSAttributedString alloc] initWithString: [self stringValue]
1039 attributes: dict];
1040 RELEASE(dict)[(dict) release];
1041 return AUTORELEASE(attrStr)[(attrStr) autorelease];
1042 }
1043}
1044
1045- (void) setAllowsEditingTextAttributes: (BOOL)flag
1046{
1047 _cell.is_rich_text = flag;
1048 if (!flag)
1049 _cell.imports_graphics = NO((BOOL)0);
1050}
1051
1052- (BOOL) allowsEditingTextAttributes
1053{
1054 return _cell.is_rich_text;
1055}
1056
1057- (void) setImportsGraphics: (BOOL)flag
1058{
1059 _cell.imports_graphics = flag;
1060 if (flag)
1061 _cell.is_rich_text = YES((BOOL)1);
1062}
1063
1064- (BOOL) importsGraphics
1065{
1066 return _cell.imports_graphics;
1067}
1068
1069- (NSString*) title
1070{
1071 return [self stringValue];
1072}
1073
1074- (void) setTitle: (NSString*)aString
1075{
1076 [self setStringValue: aString];
1077}
1078
1079- (NSLineBreakMode) lineBreakMode
1080{
1081 return _cell.line_break_mode;
1082}
1083
1084- (void) setLineBreakMode: (NSLineBreakMode)mode
1085{
1086 if (mode == NSLineBreakByCharWrapping || mode == NSLineBreakByWordWrapping)
1087 {
1088 _cell.is_scrollable = NO((BOOL)0);
1089 }
1090 _cell.line_break_mode = mode;
1091}
1092
1093- (NSWritingDirection) baseWritingDirection
1094{
1095 return _cell.base_writing_direction;
1096}
1097
1098- (void) setBaseWritingDirection: (NSWritingDirection)direction
1099{
1100 _cell.base_writing_direction = direction;
1101}
1102
1103/**<p>Implemented by subclasses to return the action method.
1104 The NSCell implementaiton returns NULL.</p>
1105 <p>See Also: -setAction: -setTarget: -target</p>
1106 */
1107- (SEL) action
1108{
1109 return NULL((void *)0);
1110}
1111
1112/** <p>Implemented by subclasses to set the action method.
1113 The NSCell implementation raises a NSInternalInconsistencyException</p>
1114 <p>See Also: -action -setTarget: -target</p>
1115*/
1116- (void) setAction: (SEL)aSelector
1117{
1118 [NSException raise: NSInternalInconsistencyException
1119 format: @"attempt to set an action in an NSCell"];
1120}
1121
1122/**<p>Implemented by subclasses to set the target object.
1123 The NSCell implementation raises a NSInternalInconsistencyException</p>
1124 <p>See Also: -target -setAction: -action</p>
1125 */
1126- (void) setTarget: (id)anObject
1127{
1128 [NSException raise: NSInternalInconsistencyException
1129 format: @"attempt to set a target in an NSCell"];
1130}
1131
1132/**<p>Implemented by subclass to return the target object.
1133 The NSCell implementation returns nil</p>
1134 <p>See Also: -setTarget: -setAction: -action</p>
1135 */
1136- (id) target
1137{
1138 return nil((id)((void*)0));
1139}
1140
1141/**<p>Returns whether the cell can continuously send its action messages.</p>
1142 <p>See Also: -setContinuous:</p>
1143 */
1144- (BOOL) isContinuous
1145{
1146 // Some subclasses should redefine this with NSLeftMouseDraggedMask
1147 return (_action_mask & NSPeriodicMask) != 0;
1148}
1149
1150/**<p>Sets whether the cell can continuously send its action messages.</p>
1151 *<p>See Also: -isContinuous</p>
1152 */
1153- (void) setContinuous: (BOOL)flag
1154{
1155 // Some subclasses should redefine this with NSLeftMouseDraggedMask
1156 if (flag)
1157 {
1158 _action_mask |= NSPeriodicMask;
1159 }
1160 else
1161 {
1162 _action_mask &= ~NSPeriodicMask;
1163 }
1164}
1165
1166/**<p>TODO Explain</p>
1167 */
1168- (int) sendActionOn: (int)mask
1169{
1170 unsigned int previousMask = _action_mask;
1171
1172 _action_mask = mask;
1173
1174 return previousMask;
1175}
1176
1177/**<p>Returns the NSCell's image if the NSCell's type is <ref type="type"
1178 id="NSCellType">NSImageCellType</ref>,
1179 returns nil otherwise.</p>
1180 <p>See Also: -setImage: -setType: -type</p>
1181 */
1182- (NSImage*) image
1183{
1184 if (_cell.type == NSImageCellType)
1185 {
1186 return _cell_image;
1187 }
1188 else
1189 return nil((id)((void*)0));
1190}
1191
1192/**<p>Sets the NSCell's image to anImage. This method sets the cell's type
1193 to NSImageCellType if needed. Raises an NSInvalidArgumentException if
1194 the anImage is not an NSImage (sub)class. The new image is retained and the
1195 old one is released</p><p>See Also: -image</p>
1196 */
1197- (void) setImage: (NSImage*)anImage
1198{
1199 if (anImage)
1200 {
1201 NSAssert ([anImage isKindOfClass: imageClass],do { if (!(([anImage isKindOfClass: imageClass]))) { [[NSAssertionHandler
currentHandler] handleFailureInMethod: _cmd object: self file
: [NSString stringWithUTF8String: "NSCell.m"] lineNumber: 1202
description: ((NSInvalidArgumentException))]; } } while(0)
1202 NSInvalidArgumentException)do { if (!(([anImage isKindOfClass: imageClass]))) { [[NSAssertionHandler
currentHandler] handleFailureInMethod: _cmd object: self file
: [NSString stringWithUTF8String: "NSCell.m"] lineNumber: 1202
description: ((NSInvalidArgumentException))]; } } while(0)
;
1203 }
1204
1205 if (_cell.type != NSImageCellType)
1206 {
1207 [self setType: NSImageCellType];
1208 }
1209
1210 ASSIGN (_cell_image, anImage)({ id __object = _cell_image; _cell_image = [(anImage) retain
]; [__object release]; })
;
1211}
1212
1213/**<p>Implemented by sublclasses to assigns the tag <var>anInt</var>.
1214 The NSCell implementation raises an NSInvalidArgumentException.</p>
1215 <p>See Also: -tag</p>
1216 */
1217- (void) setTag: (NSInteger)anInt
1218{
1219 [NSException raise: NSInternalInconsistencyException
1220 format: @"attempt to set a tag in an NSCell"];
1221}
1222
1223/**<p>Implemented by subclasses to Return the tag.
1224 The NSCell implementation returns -1 </p><p>See Also: -setTag:</p>
1225 */
1226- (NSInteger) tag
1227{
1228 return -1;
1229}
1230
1231/*
1232 * Formatting Data
1233 */
1234- (void) setFloatingPointFormat: (BOOL)autoRange
1235 left: (unsigned int)leftDigits
1236 right: (unsigned int)rightDigits
1237{
1238 NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
1239 NSMutableString *format = [[NSMutableString alloc] init];
1240
1241 if (autoRange)
1242 {
1243 unsigned fieldWidth = leftDigits + rightDigits + 1;
1244
1245 // FIXME: this does not fully match the documentation.
1246 while (fieldWidth--)
1247 {
1248 [format appendString: @"#"];
1249 }
1250 }
1251 else
1252 {
1253 while (leftDigits--)
1254 {
1255 [format appendString: @"#"];
1256 }
1257 [format appendString: @"."];
1258 while (rightDigits--)
1259 {
1260 [format appendString: @"0"];
1261 }
1262 }
1263
1264 [formatter setFormat: format];
1265 RELEASE(format)[(format) release];
1266 [self setFormatter: formatter];
1267 RELEASE(formatter)[(formatter) release];
1268}
1269
1270- (void) setFormatter: (NSFormatter*)newFormatter
1271{
1272 ASSIGN(_formatter, newFormatter)({ id __object = _formatter; _formatter = [(newFormatter) retain
]; [__object release]; })
;
1273}
1274
1275- (id) formatter
1276{
1277 return _formatter;
1278}
1279
1280/**<p> TODO</p>
1281 */
1282- (int) entryType
1283{
1284 return _cell.entry_type;
1285}
1286
1287/** <p>TODO</p>
1288 */
1289- (void) setEntryType: (int)aType
1290{
1291 [self setType: NSTextCellType];
1292 // TODO: This should select a suitable formatter
1293 _cell.entry_type = aType;
1294}
1295
1296- (BOOL) isEntryAcceptable: (NSString*)aString
1297{
1298 if ((_formatter != nil((id)((void*)0))) && ![aString isEqualToString: @""])
1299 {
1300 id newObjectValue;
1301
1302 return [_formatter getObjectValue: &newObjectValue
1303 forString: aString
1304 errorDescription: NULL((void *)0)];
1305 }
1306 else
1307 {
1308 return YES((BOOL)1);
1309 }
1310}
1311
1312/*
1313 * Menu
1314 */
1315- (void) setMenu: (NSMenu*)aMenu
1316{
1317 ASSIGN (_menu, aMenu)({ id __object = _menu; _menu = [(aMenu) retain]; [__object release
]; })
;
1318}
1319
1320- (NSMenu*) menu
1321{
1322 return _menu;
1323}
1324
1325- (NSMenu*) menuForEvent: (NSEvent*)anEvent
1326 inRect: (NSRect)cellFrame
1327 ofView: (NSView*)aView
1328{
1329 return [self menu];
1330}
1331
1332/**
1333 * Compares the reciever to another to another NSCell.
1334 * The argument must be an NSCell sublclass and have
1335 * the NSCellType NSTextCellType. Returns the result
1336 * of the comparison of each cell's stringValue.
1337 */
1338- (NSComparisonResult) compare: (id)otherCell
1339{
1340 if ([otherCell isKindOfClass: cellClass] == NO((BOOL)0))
1341 {
1342 [NSException raise: NSBadComparisonException
1343 format: @"NSCell comparison with non-NSCell"];
1344 }
1345 if (_cell.type != NSTextCellType
1346 || ((NSCell*)otherCell)->_cell.type != NSTextCellType)
1347 {
1348 [NSException raise: NSBadComparisonException
1349 format: @"Comparison between non-text cells"];
1350 }
1351 /* We shouldn't access instance variables directly as subclasses
1352 may override stringValue to retrieve the value from somewhere else. */
1353 return [[self stringValue] compare: [(NSCell*)otherCell stringValue]];
1354}
1355
1356/*
1357 * Should this cell respond to keyboard input?
1358 */
1359- (BOOL) acceptsFirstResponder
1360{
1361 return _cell.is_disabled == NO((BOOL)0) && _cell.refuses_first_responder == NO((BOOL)0);
1362}
1363
1364- (void) setShowsFirstResponder: (BOOL)flag
1365{
1366 _cell.shows_first_responder = flag;
1367}
1368
1369- (BOOL) showsFirstResponder
1370{
1371 return _cell.shows_first_responder;
1372}
1373
1374- (void) setTitleWithMnemonic: (NSString*)aString
1375{
1376 NSRange r = [aString rangeOfString: @"&"];
1377
1378 if (r.length > 0)
1379 {
1380 unsigned int location = r.location;
1381
1382
1383 [self setTitle: [[aString substringToIndex: location]
1384 stringByAppendingString:
1385 [aString substringFromIndex: NSMaxRange(r)]]];
1386 // TODO: We should underline this character
1387 [self setMnemonicLocation: location];
1388 }
1389}
1390
1391- (NSString*) mnemonic
1392{
1393 NSUInteger location = [self mnemonicLocation];
1394 NSString *c = [self title];
1395
1396 if ((location == NSNotFound) || location >= [c length])
1397 return @"";
1398
1399 return [c substringWithRange: NSMakeRange (location, 1)];
1400}
1401
1402- (void) setMnemonicLocation: (NSUInteger)location
1403{
1404 _cell.mnemonic_location = location;
1405}
1406
1407- (NSUInteger) mnemonicLocation
1408{
1409 return _cell.mnemonic_location;
1410}
1411
1412- (BOOL) refusesFirstResponder
1413{
1414 return _cell.refuses_first_responder;
1415}
1416
1417- (void) setRefusesFirstResponder: (BOOL)flag
1418{
1419 _cell.refuses_first_responder = flag;
1420}
1421
1422/**
1423 * Simulates a single click in the cell (only works with controls which have
1424 * no more than one cell). This method is deprecated,
1425 * performClickWithFrame:inView: is the right method to use now.
1426 */
1427- (void) performClick: (id)sender
1428{
1429 NSView *cv = [self controlView];
1430
1431 if (cv != nil((id)((void*)0)))
1432 [self performClickWithFrame: [cv bounds] inView: cv];
1433}
1434
1435/*
1436 * Helper method used to send actions. Sender normally is [self controlView].
1437 */
1438- (BOOL) _sendActionFrom: (id)sender
1439{
1440 SEL action = [self action];
1441
1442 if ([sender respondsToSelector: @selector(sendAction:to:)])
1443 {
1444 return [sender sendAction: action to: [self target]];
1445 }
1446 else
1447 {
1448 if (sender == nil((id)((void*)0)))
1449 sender = self;
1450
1451 if (action)
1452 {
1453 return [NSApp sendAction: action to: [self target] from: sender];
1454 }
1455 }
1456
1457 return NO((BOOL)0);
1458}
1459
1460/**
1461 * Simulates a single click in the cell.
1462 * The display of the cell with this event
1463 * occurs in the area delimited by <var>cellFrame</var> within
1464 * <var>controlView</var>.
1465 */
1466- (void) performClickWithFrame: (NSRect)cellFrame inView: (NSView *)controlView
1467{
1468 if (_cell.is_disabled == YES((BOOL)1))
1469 {
1470 return;
1471 }
1472
1473 [self setNextState];
1474
1475 if (controlView != nil((id)((void*)0)))
1476 {
1477 NSWindow *cvWin = [controlView window];
1478 NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: 0.1];
1479
1480 [controlView lockFocus];
1481 [self highlight: YES((BOOL)1) withFrame: cellFrame inView: controlView];
1482 [cvWin flushWindow];
1483
1484 // Wait approx 1/10 seconds
1485 [[NSRunLoop currentRunLoop] runUntilDate: limit];
1486
1487 [self highlight: NO((BOOL)0) withFrame: cellFrame inView: controlView];
1488 [cvWin flushWindow];
1489 [controlView unlockFocus];
1490 }
1491
1492 [self _sendActionFrom: controlView];
1493}
1494
1495/*
1496 * Deriving values from other objects (not necessarily cells)
1497 */
1498- (void) takeObjectValueFrom: (id)sender
1499{
1500 [self setObjectValue: [sender objectValue]];
1501}
1502
1503/** <p>Sets the NSCell's double value to sender's double value</p>
1504 <p>See Also: -setDoubleValue:</p>
1505 */
1506- (void) takeDoubleValueFrom: (id)sender
1507{
1508 [self setDoubleValue: [sender doubleValue]];
1509}
1510
1511/** <p>Sets the NSCell's float value to sender's float value</p>
1512 <p>See Also: -setFloatValue:</p>
1513 */
1514- (void) takeFloatValueFrom: (id)sender
1515{
1516 [self setFloatValue: [sender floatValue]];
1517}
1518
1519/** <p>Sets the NSCell's int value to sender's int value</p>
1520 <p>See Also: -setIntValue:</p>
1521 */
1522- (void) takeIntValueFrom: (id)sender
1523{
1524 [self setIntValue: [sender intValue]];
1525}
1526
1527/** <p>Sets the NSCell's NSInteger value to sender's NSInteger value</p>
1528 <p>See Also: -setIntegerValue:</p>
1529 */
1530- (void) takeIntegerValueFrom: (id)sender
1531{
1532 [self setIntegerValue: [sender integerValue]];
1533}
1534
1535/** <p>Sets the NSCell's NSString value to sender's NSSting value</p>
1536 <p>See Also: -setStringValue:</p>
1537 */
1538- (void) takeStringValueFrom: (id)sender
1539{
1540 [self setStringValue: [sender stringValue]];
1541}
1542
1543/** <p>Returns the NSCell's represented object</p>
1544 <p>See Also: -setRepresentedObject:</p>
1545 */
1546- (id) representedObject
1547{
1548 return _represented_object;
1549}
1550
1551/** <p>Sets the NSCell's represented object to <var>anObject</var>.
1552 anObject will be retain.</p><p>See Also: -representedObject</p>
1553 */
1554- (void) setRepresentedObject: (id)anObject
1555{
1556 /* Ahm - not nice - the RETAIN here could cause retain cycles - anyway. */
1557 ASSIGN (_represented_object, anObject)({ id __object = _represented_object; _represented_object = [
(anObject) retain]; [__object release]; })
;
1558}
1559
1560/** <p>Returns YES. Subclasses should overrided this method if you want
1561 stop tracking the mouse. This method is call in the
1562 -trackMouse:inRect:ofView:untilMouseUp: main loop.</p>
1563 <p>See Also: -trackMouse:inRect:ofView:untilMouseUp:</p>
1564 */
1565- (BOOL) continueTracking: (NSPoint)lastPoint
1566 at: (NSPoint)currentPoint
1567 inView: (NSView*)controlView
1568{
1569 return YES((BOOL)1);
1570}
1571
1572/**<p>Returns the mouse flags. This flags are usally sets in
1573 the -trackMouse:inRect:ofView:untilMouseUp: method</p>
1574 */
1575- (int) mouseDownFlags
1576{
1577 return _mouse_down_flags;
1578}
1579
1580/**<p>Gets the NSCell's <var>delay</var> and the <var>interval</var>
1581 parameters used when NSCell sends continouly action messages.
1582 The NSCell implementation sets both <var>delay</var> and <var>interval</var>
1583 to 0.1.</p>
1584 <p>See Also: -trackMouse:inRect:ofView:untilMouseUp:</p>
1585 */
1586- (void) getPeriodicDelay: (float*)delay interval: (float*)interval
1587{
1588 *delay = 0.1;
1589 *interval = 0.1;
1590}
1591
1592/**<p>Returns whether tracking starts. The NSCell implementation
1593 returns YES when the <var>startPoint</var> is into the control view
1594 retangle, NO otherwise. This method is call at the early stage of
1595 -trackMouse:inRect:ofView:untilMouseUp:</p><p>See Also:
1596 [NSView-mouse:inRect:] -trackMouse:inRect:ofView:untilMouseUp:
1597 </p>
1598 */
1599- (BOOL) startTrackingAt: (NSPoint)startPoint inView: (NSView*)controlView
1600{
1601 // If the point is in the view then yes start tracking
1602 if ([controlView mouse: startPoint inRect: [controlView bounds]])
1603 return YES((BOOL)1);
1604 else
1605 return NO((BOOL)0);
1606}
1607
1608/**<p>Default implementation of this method in NSCell does nothing.</p>
1609 */
1610- (void) stopTracking: (NSPoint)lastPoint
1611 at: (NSPoint)stopPoint
1612 inView: (NSView*)controlView
1613 mouseIsUp: (BOOL)flag
1614{
1615}
1616
1617- (BOOL) trackMouse: (NSEvent*)theEvent
1618 inRect: (NSRect)cellFrame
1619 ofView: (NSView*)controlView
1620 untilMouseUp: (BOOL)flag
1621{
1622 NSApplication *theApp = [NSApplication sharedApplication];
1623 unsigned event_mask = NSLeftMouseDownMask | NSLeftMouseUpMask
1624 | NSMouseMovedMask | NSLeftMouseDraggedMask | NSOtherMouseDraggedMask
1625 | NSRightMouseDraggedMask;
1626 NSPoint location = [theEvent locationInWindow];
1627 NSPoint point = [controlView convertPoint: location fromView: nil((id)((void*)0))];
1628 float delay;
1629 float interval;
1630 NSPoint last_point = point;
1631 BOOL done;
1632 BOOL mouseWentUp;
1633 unsigned periodCount = 0;
1634
1635 NSDebugLLog(@"NSCell", @"cell start tracking in rect %@ initial point %f %f",do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell start tracking in rect %@ initial point %f %f"
, NSStringFromRect(cellFrame), point.x, point.y); } while (0
)
1636 NSStringFromRect(cellFrame), point.x, point.y)do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell start tracking in rect %@ initial point %f %f"
, NSStringFromRect(cellFrame), point.x, point.y); } while (0
)
;
1637
1638 _mouse_down_flags = [theEvent modifierFlags];
1639 if (![self startTrackingAt: point inView: controlView])
1640 return NO((BOOL)0);
1641
1642 if (![controlView mouse: point inRect: cellFrame])
1643 return NO((BOOL)0); // point is not in cell
1644
1645 if ((_action_mask & NSLeftMouseDownMask)
1646 && [theEvent type] == NSLeftMouseDown)
1647 [self _sendActionFrom: controlView];
1648
1649 if (_action_mask & NSPeriodicMask)
1650 {
1651 [self getPeriodicDelay: &delay interval: &interval];
1652 [NSEvent startPeriodicEventsAfterDelay: delay withPeriod: interval];
1653 event_mask |= NSPeriodicMask;
1654 }
1655
1656 NSDebugLLog(@"NSCell", @"cell get mouse events\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell get mouse events\n"
); } while (0)
;
1657 mouseWentUp = NO((BOOL)0);
1658 done = NO((BOOL)0);
1659 if (theEvent != [NSApp currentEvent])
1660 theEvent = [NSApp currentEvent];
1661 else
1662 theEvent = [theApp nextEventMatchingMask: event_mask
1663 untilDate: [NSDate distantFuture]
1664 inMode: NSEventTrackingRunLoopMode
1665 dequeue: YES((BOOL)1)];
1666
1667 while (!done)
1668 {
1669 NSEventType eventType;
1670 BOOL pointIsInCell;
1671
1672 eventType = [theEvent type];
1673
1674 if (eventType != NSPeriodic || periodCount == 4)
1675 {
1676 last_point = point;
1677 if (eventType == NSPeriodic)
1678 {
1679 NSWindow *w = [controlView window];
1680
1681 /*
1682 * Too many periodic events in succession -
1683 * update the mouse location and reset the counter.
1684 */
1685 location = [w mouseLocationOutsideOfEventStream];
1686 periodCount = 0;
1687 }
1688 else
1689 {
1690 location = [theEvent locationInWindow];
1691 }
1692 point = [controlView convertPoint: location fromView: nil((id)((void*)0))];
1693 NSDebugLLog(@"NSCell", @"location %f %f\n", location.x, location.y)do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"location %f %f\n"
, location.x, location.y); } while (0)
;
1694 NSDebugLLog(@"NSCell", @"point %f %f\n", point.x, point.y)do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"point %f %f\n"
, point.x, point.y); } while (0)
;
1695 }
1696 else
1697 {
1698 periodCount++;
1699 NSDebugLLog (@"NSCell", @"cell got a periodic event")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell got a periodic event"
); } while (0)
;
1700 }
1701
1702 if (![controlView mouse: point inRect: cellFrame])
1703 {
1704 NSDebugLLog(@"NSCell", @"point not in cell frame\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"point not in cell frame\n"
); } while (0)
;
1705
1706 pointIsInCell = NO((BOOL)0);
1707 if (flag == NO((BOOL)0))
1708 {
1709 NSDebugLLog(@"NSCell", @"cell return immediately\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell return immediately\n"
); } while (0)
;
1710 done = YES((BOOL)1);
1711 }
1712 }
1713 else
1714 {
1715 pointIsInCell = YES((BOOL)1);
1716 }
1717
1718 if (!done && ![self continueTracking: last_point // should continue
1719 at: point // tracking?
1720 inView: controlView])
1721 {
1722 NSDebugLLog(@"NSCell", @"cell stop tracking\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell stop tracking\n"
); } while (0)
;
1723 done = YES((BOOL)1);
1724 }
1725
1726 // Did the mouse go up?
1727 if (eventType == NSLeftMouseUp)
1728 {
1729 NSDebugLLog(@"NSCell", @"cell mouse went up\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"cell mouse went up\n"
); } while (0)
;
1730 mouseWentUp = YES((BOOL)1);
1731 done = YES((BOOL)1);
1732 }
1733 else
1734 {
1735 if (pointIsInCell && ((eventType == NSLeftMouseDragged
1736 && (_action_mask & NSLeftMouseDraggedMask))
1737 || ((eventType == NSPeriodic)
1738 && (_action_mask & NSPeriodicMask))))
1739 [self _sendActionFrom: controlView];
1740 }
1741
1742 if (!done)
1743 theEvent = [theApp nextEventMatchingMask: event_mask
1744 untilDate: [NSDate distantFuture]
1745 inMode: NSEventTrackingRunLoopMode
1746 dequeue: YES((BOOL)1)];
1747 }
1748
1749 // Hook called when stop tracking
1750 [self stopTracking: last_point
1751 at: point
1752 inView: controlView
1753 mouseIsUp: mouseWentUp];
1754
1755 if (_action_mask & NSPeriodicMask)
1756 [NSEvent stopPeriodicEvents];
1757
1758 if (mouseWentUp)
1759 {
1760 [self setNextState];
1761 if ((_action_mask & NSLeftMouseUpMask))
1762 [self _sendActionFrom: controlView];
1763 }
1764
1765 // Return YES only if the mouse went up within the cell
1766 if (mouseWentUp && (flag || [controlView mouse: point inRect: cellFrame]))
1767 {
1768 NSDebugLLog(@"NSCell", @"mouse went up in cell\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"mouse went up in cell\n"
); } while (0)
;
1769 return YES((BOOL)1);
1770 }
1771
1772 NSDebugLLog(@"NSCell", @"mouse did not go up in cell\n")do { if (GSDebugSet(@"NSCell") == ((BOOL)1)) NSLog(@"mouse did not go up in cell\n"
); } while (0)
;
1773 return NO((BOOL)0); // Otherwise return NO
1774}
1775
1776/** <p>TODO</p>
1777 */
1778- (void) resetCursorRect: (NSRect)cellFrame inView: (NSView*)controlView
1779{
1780 if (_cell.type == NSTextCellType && _cell.is_disabled == NO((BOOL)0)
1781 && (_cell.is_selectable == YES((BOOL)1) || _cell.is_editable == YES((BOOL)1)))
1782 {
1783 static NSCursor *cursor = nil((id)((void*)0));
1784 NSRect rect;
1785
1786 if (cursor== nil((id)((void*)0)))
1787 {
1788 cursor = RETAIN([NSCursor IBeamCursor])[([NSCursor IBeamCursor]) retain];
1789 }
1790 rect = NSIntersectionRect(cellFrame, [controlView visibleRect]);
1791 /*
1792 * Here we depend on an undocumented feature of NSCursor which may or
1793 * may not exist in OPENSTEP or MacOS-X ...
1794 * If we add a cursor rect to a view and don't set it to be set on
1795 * either entry to or exit from the view, we push it on entry and
1796 * pop it from the cursor stack on exit.
1797 */
1798 [controlView addCursorRect: rect cursor: cursor];
1799 }
1800}
1801
1802/**<p>Implemented by subclasses to returns the key equivalent.
1803 The NSCell implementation returns an empty NSString. </p>
1804 */
1805- (NSString*) keyEquivalent
1806{
1807 return @"";
1808}
1809
1810/**<p>Does nothing. This method is used by subclasses to recalculate sizes</p>
1811 <p>It is usally called from a NSControl object</p>
1812 <p>See Also: [NSControl-calcSize]</p>
1813 */
1814- (void) calcDrawInfo: (NSRect)aRect
1815{
1816}
1817
1818/**Returns the minimun size needed to display the NSCell.
1819 This size is calculate by adding :
1820 <list>
1821 <item> the borders (plain or bezeled) size</item>
1822 <item> the spacing between the border and inside the cell</item>
1823 <item> the TODO ... if the cell is type of NSTextCellType
1824 or the image size if the cell has a NSImageCellType type.</item>
1825 </list>
1826 <p>This method returns NSZeroSize if the cell has a NSNullCellType type
1827 (Cocoa returns a very big size instead).
1828 </p>
1829 */
1830- (NSSize) cellSize
1831{
1832 NSSize borderSize, s;
1833 NSBorderType aType;
1834
1835 // Get border size
1836 if (_cell.is_bordered)
1837 aType = NSLineBorder;
1838 else if (_cell.is_bezeled)
1839 aType = NSBezelBorder;
1840 else
1841 aType = NSNoBorder;
1842
1843 borderSize = [[GSTheme theme] sizeForBorderType: aType];
1844
1845 // Add spacing between border and inside
1846 if (_cell.is_bordered || _cell.is_bezeled)
1847 {
1848 borderSize.height += 1;
1849 borderSize.width += 3;
1850 }
1851
1852 // Get Content Size
1853 switch (_cell.type)
1854 {
1855 case NSTextCellType:
1856 {
1857 NSAttributedString *attrStr;
1858
1859 attrStr = [self attributedStringValue];
1860 if ([attrStr length] != 0)
1861 {
1862 s = [attrStr size];
1863 }
1864 else
1865 {
1866 s = [self _sizeText: @"A"];
1867 }
1868 }
1869 break;
1870
1871 case NSImageCellType:
1872 if (_cell_image == nil((id)((void*)0)))
1873 {
1874 s = NSZeroSize;
1875 }
1876 else
1877 {
1878 s = [_cell_image size];
1879 }
1880 break;
1881
1882 default:
1883 case NSNullCellType:
1884 // macosx instead returns a 'very big size' here; we return NSZeroSize
1885 s = NSZeroSize;
1886 break;
1887 }
1888
1889 // Add in border size
1890 s.width += 2 * borderSize.width;
1891 s.height += 2 * borderSize.height;
1892
1893 return s;
1894}
1895
1896/**<p>TODO. Currently the GNUstep implementation returns -cellSize</p>
1897 <p>See Also: -cellSize</p>
1898 */
1899- (NSSize) cellSizeForBounds: (NSRect)aRect
1900{
1901 if (_cell.type == NSTextCellType)
1902 {
1903 // TODO: Resize the text to fit
1904 }
1905
1906 return [self cellSize];
1907}
1908
1909/**<p>TODO</p>
1910 */
1911- (NSRect) drawingRectForBounds: (NSRect)theRect
1912{
1913 NSSize borderSize;
1914 NSBorderType aType;
1915
1916 // Get border size
1917 if (_cell.is_bordered)
1918 aType = NSLineBorder;
1919 else if (_cell.is_bezeled)
1920 aType = NSBezelBorder;
1921 else
1922 aType = NSNoBorder;
1923
1924 borderSize = [[GSTheme theme] sizeForBorderType: aType];
1925 return NSInsetRect(theRect, borderSize.width, borderSize.height);
1926}
1927
1928/**<p>The GNUstep implementation returns -drawingRectForBounds:</p>
1929 */
1930- (NSRect) imageRectForBounds: (NSRect)theRect
1931{
1932 return [self drawingRectForBounds: theRect];
1933}
1934
1935/** <p>TODO</p>
1936 */
1937- (NSRect) titleRectForBounds: (NSRect)theRect
1938{
1939 if (_cell.type == NSTextCellType)
1940 {
1941 NSRect frame = [self drawingRectForBounds: theRect];
1942
1943 // Add spacing between border and inside
1944 if (_cell.is_bordered || _cell.is_bezeled)
1945 {
1946 frame.origin.x += 3;
1947 frame.size.width -= 6;
1948 frame.origin.y += 1;
1949 frame.size.height -= 2;
1950 }
1951 return frame;
1952 }
1953 else
1954 {
1955 return theRect;
1956 }
1957}
1958
1959- (void) setControlSize: (NSControlSize)controlSize
1960{
1961 _cell.control_size = controlSize;
1962}
1963
1964- (NSControlSize) controlSize
1965{
1966 return _cell.control_size;
1967}
1968
1969- (void) setControlTint: (NSControlTint)controlTint
1970{
1971 _cell.control_tint = controlTint;
1972}
1973
1974- (NSControlTint) controlTint
1975{
1976 return _cell.control_tint;
1977}
1978
1979/**<p>This method is used by subclasses to get the control view.
1980 This method returns nil.</p>
1981 */
1982- (NSView*) controlView
1983{
1984 return nil((id)((void*)0));
1985}
1986
1987/**<p>This method is used by subclasses to specify the control view.</p>
1988 */
1989- (void) setControlView: (NSView*)view
1990{
1991 // Do nothing
1992}
1993
1994/** <p>This drawing is minimal and with no background,
1995 * to make it easier for subclass to customize drawing. </p>
1996 */
1997- (void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
1998{
1999 NSRect drawingRect = [self drawingRectForBounds: cellFrame];
2000
2001 //FIXME: Check if this is also neccessary for images,
2002 // Add spacing between border and inside
2003 if (_cell.is_bordered || _cell.is_bezeled)
2004 {
2005 drawingRect.origin.x += 3;
2006 drawingRect.size.width -= 6;
2007 drawingRect.origin.y += 1;
2008 drawingRect.size.height -= 2;
2009 }
2010
2011 switch (_cell.type)
2012 {
2013 case NSTextCellType:
2014 if (_cell.in_editing)
2015 [self _drawEditorWithFrame: cellFrame inView: controlView];
2016 else
2017 [self _drawAttributedText: [self _drawAttributedString]
2018 inFrame: drawingRect];
2019 break;
2020
2021 case NSImageCellType:
2022 if (_cell_image)
2023 {
2024 NSSize size;
2025 NSPoint position;
2026
2027 size = [_cell_image size];
2028 position.x = MAX(NSMidX(drawingRect) - (size.width/2.),0.)(((NSMidX(drawingRect) - (size.width/2.))>(0.))?(NSMidX(drawingRect
) - (size.width/2.)):(0.))
;
2029 position.y = MAX(NSMidY(drawingRect) - (size.height/2.),0.)(((NSMidY(drawingRect) - (size.height/2.))>(0.))?(NSMidY(drawingRect
) - (size.height/2.)):(0.))
;
2030
2031 [_cell_image drawInRect: NSMakeRect(position.x, position.y, size.width, size.height)
2032 fromRect: NSZeroRect
2033 operation: NSCompositeSourceOver
2034 fraction: 1.0
2035 respectFlipped: YES((BOOL)1)
2036 hints: nil((id)((void*)0))];
2037 }
2038 break;
2039
2040 case NSNullCellType:
2041 break;
2042 }
2043
2044 // NB: We don't do any highlighting to make it easier for subclasses
2045 // to reuse this code while doing their own custom highlighting and
2046 // prettyfying
2047}
2048
2049/**<p>Draws the cell in <var>controlView</var></p>
2050 */
2051- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
2052{
2053 // do nothing if cell's frame rect is zero
2054 if (NSIsEmptyRect(cellFrame))
2055 return;
2056
2057 // draw the border if needed
2058 [self _drawBorderAndBackgroundWithFrame: cellFrame inView: controlView];
2059 // draw interior
2060 [self drawInteriorWithFrame: cellFrame inView: controlView];
2061 // Draw first responder
2062 [self _drawFocusRingWithFrame: cellFrame inView: controlView];
2063}
2064
2065/**<p>Sets whether the NSCell is highlighted.</p>
2066 <p>See Also: -isHighlighted</p>
2067 */
2068- (void) setHighlighted: (BOOL) flag
2069{
2070 _cell.is_highlighted = flag;
2071}
2072
2073/**<p>Returns whether the cell is highlighted. By default NO</p>
2074 <p>See Also: -setHighlighted:</p>
2075 */
2076- (BOOL) isHighlighted
2077{
2078 return _cell.is_highlighted;
2079}
2080
2081/**
2082 *<p>TODO explain</p>
2083 */
2084
2085- (void) highlight: (BOOL)lit
2086 withFrame: (NSRect)cellFrame
2087 inView: (NSView*)controlView
2088{
2089 if (_cell.is_highlighted != lit)
2090 {
2091 _cell.is_highlighted = lit;
2092 /*
2093 * NB: This has a visible effect only if subclasses override
2094 * drawWithFrame:inView: to draw something special when the
2095 * cell is highlighted.
2096 * NSCell simply draws border+text/image and makes no highlighting,
2097 * for easier subclassing.
2098 */
2099 if ([self isOpaque] == NO((BOOL)0))
2100 {
2101 /* FIXME - This looks like potentially generating an
2102 * infinite loop! The control asking the cell to draw
2103 * itself in the rect, the cell asking the control to draw
2104 * the rect, the control asking the cell to draw itself in
2105 * the rect, the cell ...
2106 *
2107 * I think we should remove it. The control is responsible
2108 * for using the cell to draw, not vice versa.
2109 */
2110 [controlView displayRect: cellFrame];
2111 }
2112 [self drawWithFrame: cellFrame inView: controlView];
2113 }
2114}
2115
2116- (NSColor*) highlightColorWithFrame: (NSRect)cellFrame
2117 inView: (NSView *)controlView
2118{
2119 return [NSColor selectedControlColor];
2120}
2121
2122- (NSText*) setUpFieldEditorAttributes: (NSText*)textObject
2123{
2124 NSDictionary *attr;
2125
2126 // Reset the string to have a well defined state. The real string gets set later on.
2127 [textObject setString: @""];
2128
2129 [textObject setTextColor: [self textColor]];
2130 if ([self isBezeled])
2131 {
2132 [textObject setBackgroundColor: [NSColor textBackgroundColor]];
2133 [textObject setDrawsBackground: YES((BOOL)1)];
2134 }
2135 else
2136 {
2137 [textObject setDrawsBackground: NO((BOOL)0)];
2138 }
2139 [textObject setFont: [self font]];
2140 [textObject setAlignment: [self alignment]];
2141 // FIXME: Add base writing direction
2142
2143 [textObject setEditable: [self isEditable]];
2144 [textObject setSelectable: [self isSelectable]];
2145 [textObject setRichText: [self allowsEditingTextAttributes]];
2146 [textObject setImportsGraphics: [self importsGraphics]];
2147 [(NSTextView*)textObject setAllowsUndo: [self allowsUndo]];
2148 attr = [self _nonAutoreleasedTypingAttributes];
2149 [(NSTextView*)textObject setTypingAttributes: attr];
2150 RELEASE(attr)[(attr) release];
2151
2152 return textObject;
2153}
2154
2155- (void) _setupTextWithFrame: (NSRect)aRect
2156 inView: (NSView*)controlView
2157 editor: (NSText*)textObject
2158 delegate: (id)anObject
2159 range: (NSRange)selection
2160{
2161 BOOL needsClipView;
2162 BOOL wraps = [self wraps];
2163 NSTextContainer *ct;
2164 NSSize maxSize;
2165 NSRect titleRect = [self titleRectForBounds: aRect];
2166
2167 /* We always add a clip view if the cell is editable so that the user
2168 can edit the whole contents even if the cell's contents normally is
2169 clipped. */
2170 needsClipView = [self isScrollable] || [self isEditable];
2171 if (needsClipView)
2172 {
2173 NSClipView *cv;
2174
2175 cv = [[NSClipView alloc] initWithFrame: titleRect];
2176 [cv setDocumentView: textObject];
2177 [controlView addSubview: cv];
2178 RELEASE(cv)[(cv) release];
2179 }
2180 else
2181 [controlView addSubview: textObject];
2182
2183 /* Note: The order of statements matters here. We must set the text object's
2184 horizontallyResizable and verticallyResizable attributes before setting
2185 its frame size. Otherwise, the text object's width and/or height might
2186 incorrectly be reduced to zero (since the text object has no contents at
2187 this point) if the text object was resizable by its text container before.
2188 Of course we could also have set the text object's minimum size to the
2189 intended frame size, but then we must update the minimum size whenever
2190 the field editor's frame is changed in -_drawEditorWithFrame:inView:.
2191 Note that the minimum size is not relevant when a clip view is used. */
2192 [textObject setMinSize: NSZeroSize];
2193 [textObject setMaxSize: NSMakeSize(1e6, 1e6)];
2194 [textObject setHorizontallyResizable: needsClipView && !wraps];
2195 [textObject setVerticallyResizable: needsClipView];
2196 [textObject setFrame: titleRect];
2197 if (needsClipView)
2198 [textObject setAutoresizingMask: NSViewWidthSizable + NSViewHeightSizable];
2199 else
2200 [textObject setAutoresizingMask: NSViewNotSizable];
2201
2202 /* Note: Order of statements matters again. The heightTracksTextView
2203 and widthTracksTextView container attributes must be set after setting
2204 the horizontallyResizable and verticallyResizable text view attributes
2205 because NSTextView's setter methods include "safety code", which
2206 always updates the container attributes along with the text view
2207 attributes.
2208 FIXME Fix NSTextView to only reset the text container attributes, but
2209 never set them. However note that this may break some sloppily written
2210 code which forgets to set the text container attributes. */
2211 /* See comments in NSStringDrawing.m about the choice of maximum size. */
2212 ct = [(NSTextView*)textObject textContainer];
2213 if (wraps)
2214 maxSize = NSMakeSize(NSWidth(titleRect), 1e6);
2215 else
2216 maxSize = NSMakeSize(1e6, 1e6);
2217 [ct setContainerSize: maxSize];
2218 [ct setWidthTracksTextView: wraps];
2219 [ct setHeightTracksTextView: NO((BOOL)0)];
2220
2221 [self _updateFieldEditor: textObject];
2222
2223 [textObject setSelectedRange: selection];
2224 [textObject scrollRangeToVisible: selection];
2225
2226 [textObject setDelegate: anObject];
2227 [[controlView window] makeFirstResponder: textObject];
2228 _cell.in_editing = YES((BOOL)1);
2229}
2230
2231/**<p>Ends any text editing. This method sets the text object's delegate
2232 to nil, and remove the NSClipView and the text object used for editing</p>
2233 <p>See Also: -editWithFrame:inView:editor:delegate:event:</p>
2234 */
2235- (void) endEditing: (NSText*)textObject
2236{
2237 NSClipView *clipView;
2238
2239 _cell.in_editing = NO((BOOL)0);
2240 [textObject setString: @""];
2241 [textObject setDelegate: nil((id)((void*)0))];
2242
2243 clipView = (NSClipView*)[textObject superview];
2244 if ([clipView isKindOfClass: [NSClipView class]])
2245 {
2246 [clipView setDocumentView: nil((id)((void*)0))];
2247 [clipView removeFromSuperview];
2248 }
2249 else
2250 [textObject removeFromSuperview];
2251}
2252
2253/*
2254 * Editing Text
2255 */
2256/** <p>.This method does nothing if a the <var>controlView</var> is nil,
2257 if text object does not exist or if the cell's type is not <ref type="type"
2258 id="NSCellType">NSTextCellType</ref></p>
2259 */
2260- (void) editWithFrame: (NSRect)aRect
2261 inView: (NSView*)controlView
2262 editor: (NSText*)textObject
2263 delegate: (id)anObject
2264 event: (NSEvent*)theEvent
2265{
2266 if (!controlView || !textObject || (_cell.type != NSTextCellType))
2267 return;
2268
2269 [self _setupTextWithFrame: aRect
2270 inView: controlView
2271 editor: textObject
2272 delegate: anObject
2273 range: NSMakeRange(0, 0)];
2274
2275 if ([theEvent type] == NSLeftMouseDown)
2276 {
2277 [textObject mouseDown: theEvent];
2278 }
2279}
2280
2281/** <p> This method does nothing if the <var>controlView</var> is nil,
2282 if text object does not exist or if the cell's type is not <ref type="type"
2283 id="NSCellType">NSTextCellType</ref> </p>
2284 */
2285- (void) selectWithFrame: (NSRect)aRect
2286 inView: (NSView*)controlView
2287 editor: (NSText*)textObject
2288 delegate: (id)anObject
2289 start: (int)selStart
2290 length: (int)selLength
2291{
2292 if (!controlView || !textObject || (_cell.type != NSTextCellType))
2293 return;
2294
2295 [self _setupTextWithFrame: aRect
2296 inView: controlView
2297 editor: textObject
2298 delegate: anObject
2299 range: NSMakeRange(selStart, selLength)];
2300}
2301
2302- (BOOL) sendsActionOnEndEditing
2303{
2304 return _cell.sends_action_on_end_editing;
2305}
2306
2307- (void) setSendsActionOnEndEditing: (BOOL)flag
2308{
2309 _cell.sends_action_on_end_editing = flag;
2310}
2311
2312- (BOOL) allowsUndo
2313{
2314 return _cell.allows_undo;
2315}
2316
2317- (void) setAllowsUndo: (BOOL)flag
2318{
2319 _cell.allows_undo = flag;
2320}
2321
2322/*
2323 * Copying
2324 */
2325- (id) copyWithZone: (NSZone*)zone
2326{
2327 NSCell *c = (NSCell*)NSCopyObject (self, 0, zone);
2328
2329 /* Hmmm. */
2330 c->_contents = [_contents copyWithZone: zone];
2331 /* Because of performance issues (and because so the doc says) only
2332 pointers to the objects are copied. We need to RETAIN them all
2333 though. */
2334 _font = TEST_RETAIN (_font)({id __object = (_font); (__object != ((id)((void*)0))) ? [__object
retain] : ((id)((void*)0)); })
;
2335 _object_value = TEST_RETAIN (_object_value)({id __object = (_object_value); (__object != ((id)((void*)0)
)) ? [__object retain] : ((id)((void*)0)); })
;
2336 _menu = TEST_RETAIN (_menu)({id __object = (_menu); (__object != ((id)((void*)0))) ? [__object
retain] : ((id)((void*)0)); })
;
2337 _cell_image = TEST_RETAIN (_cell_image)({id __object = (_cell_image); (__object != ((id)((void*)0)))
? [__object retain] : ((id)((void*)0)); })
;
2338 _formatter = TEST_RETAIN (_formatter)({id __object = (_formatter); (__object != ((id)((void*)0))) ?
[__object retain] : ((id)((void*)0)); })
;
2339 _formatter = TEST_RETAIN (_represented_object)({id __object = (_represented_object); (__object != ((id)((void
*)0))) ? [__object retain] : ((id)((void*)0)); })
;
2340
2341 return c;
2342}
2343
2344/*
2345 * NSCoding protocol
2346 */
2347- (void) encodeWithCoder: (NSCoder*)aCoder
2348{
2349 if ([aCoder allowsKeyedCoding])
2350 {
2351 unsigned long cFlags = 0;
2352 unsigned int cFlags2 = 0;
2353 id contents;
2354
2355 // encode contents
2356 if (_cell.type == NSTextCellType)
2357 {
2358 contents = _contents;
2359 }
2360 else if (_cell.type == NSImageCellType)
2361 {
2362 contents = _cell_image;
2363 }
2364 else
2365 {
2366 contents = [self objectValue];
2367 }
2368 [aCoder encodeObject: contents forKey: @"NSContents"];
2369
2370 // flags
2371 cFlags |= [self focusRingType];
2372 cFlags |= [self showsFirstResponder] ? 0x4 : 0;
2373 cFlags |= (_action_mask & NSLeftMouseUpMask) ? 0 : 0x20;
2374 cFlags |= [self wraps] ? 0x40 : 0;
2375 cFlags |= (_action_mask & NSLeftMouseDraggedMask) ? 0x100 : 0;
2376 cFlags |= (_action_mask & NSLeftMouseDownMask) ? 0x40000 : 0;
2377 cFlags |= [self isContinuous] ? 0x80000 : 0;
2378 cFlags |= [self isScrollable] ? 0x100000 : 0;
2379 cFlags |= [self isSelectable] ? 0x200000 : 0;
2380 cFlags |= [self isBezeled] ? 0x400000 : 0;
2381 cFlags |= [self isBordered] ? 0x800000 : 0;
2382 cFlags |= ([self type] << 26);
2383 cFlags |= [self isEditable] ? 0x10000000 : 0;
2384 cFlags |= ([self isEnabled] == NO((BOOL)0)) ? 0x20000000 : 0;
2385 cFlags |= [self isHighlighted] ? 0x40000000 : 0;
2386 cFlags |= ([self state] == NSOnState) ? 0x80000000 : 0;
2387 [aCoder encodeInt: cFlags forKey: @"NSCellFlags"];
2388
2389 // flags part 2
2390 cFlags2 |= ([self controlTint] << 5);
2391 cFlags2 |= ([self lineBreakMode] << 9);
2392 cFlags2 |= ([self controlSize] << 17);
2393 cFlags2 |= [self sendsActionOnEndEditing] ? 0x400000 : 0;
2394 cFlags2 |= [self allowsMixedState] ? 0x1000000 : 0;
2395 cFlags2 |= [self refusesFirstResponder] ? 0x2000000 : 0;
2396 cFlags2 |= ([self alignment] << 26);
2397 cFlags2 |= [self importsGraphics] ? 0x20000000 : 0;
2398 cFlags2 |= [self allowsEditingTextAttributes] ? 0x40000000 : 0;
2399 [aCoder encodeInt: cFlags2 forKey: @"NSCellFlags2"];
2400
2401 if (_cell.type == NSTextCellType)
2402 {
2403 // font and formatter.
2404 if ([self font])
2405 {
2406 [aCoder encodeObject: [self font] forKey: @"NSSupport"];
2407 }
2408
2409 if ([self formatter])
2410 {
2411 [aCoder encodeObject: [self formatter] forKey: @"NSFormatter"];
2412 }
2413 }
2414 else if ([self image])
2415 {
2416 [aCoder encodeObject: [self image] forKey: @"NSSupport"];
2417 }
2418 }
2419 else
2420 {
2421 BOOL flag;
2422 unsigned int tmp_int;
2423
2424 [aCoder encodeObject: _contents];
2425 [aCoder encodeObject: _cell_image];
2426 [aCoder encodeObject: _font];
2427 [aCoder encodeObject: _object_value];
2428 flag = _cell.contents_is_attributed_string;
2429 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2430 flag = _cell.is_highlighted;
2431 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2432 flag = _cell.is_disabled;
2433 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2434 flag = _cell.is_editable;
2435 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2436 flag = _cell.is_rich_text;
2437 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2438 flag = _cell.imports_graphics;
2439 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2440 flag = _cell.shows_first_responder;
2441 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2442 flag = _cell.refuses_first_responder;
2443 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2444 flag = _cell.sends_action_on_end_editing;
2445 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2446 flag = _cell.is_bordered;
2447 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2448 flag = _cell.is_bezeled;
2449 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2450 flag = _cell.is_scrollable;
2451 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2452 flag = _cell.is_selectable;
2453 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2454 // This used to be is_continuous, which has been replaced.
2455 /* Ayers 20.03.2003: But we must continue to encode it for backward
2456 compatibility or current releases will have undefined behavior when
2457 decoding archives (i.e. .gorm files) encoded by this version. */
2458 flag = [self isContinuous];
2459 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2460 flag = _cell.allows_mixed_state;
2461 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2462 flag = [self wraps];
2463 [aCoder encodeValueOfObjCType: @encode(BOOL) at: &flag];
2464 tmp_int = _cell.text_align;
2465 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2466 tmp_int = _cell.type;
2467 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2468 tmp_int = _cell.image_position;
2469 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2470 tmp_int = _cell.entry_type;
2471 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2472 // FIXME: State may be -1, why do we encode it as unsigned?
2473 tmp_int = _cell.state;
2474 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2475 tmp_int = _cell.mnemonic_location;
2476 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2477 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &_mouse_down_flags];
2478 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &_action_mask];
2479 [aCoder encodeValueOfObjCType: @encode(id) at: &_formatter];
2480 [aCoder encodeValueOfObjCType: @encode(id) at: &_menu];
2481 [aCoder encodeValueOfObjCType: @encode(id) at: &_represented_object];
2482
2483 tmp_int = _cell.allows_undo;
2484 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2485 tmp_int = _cell.line_break_mode;
2486 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2487 tmp_int = _cell.control_tint;
2488 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2489 tmp_int = _cell.control_size;
2490 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2491 tmp_int = _cell.focus_ring_type;
2492 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2493 tmp_int = _cell.base_writing_direction;
2494 [aCoder encodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2495 }
2496}
2497
2498- (id) initWithCoder: (NSCoder*)aDecoder
2499{
2500 if ([aDecoder allowsKeyedCoding])
2501 {
2502 id contents = [aDecoder decodeObjectForKey: @"NSContents"];
2503
2504 // initialize based on content...
2505 if ([contents isKindOfClass: [NSString class]])
2506 {
2507 self = [self initTextCell: contents];
2508 }
2509 else if ([contents isKindOfClass: [NSImage class]])
2510 {
2511 self = [self initImageCell: contents];
2512 }
2513 else
2514 {
2515 self = [self init];
2516 [self setObjectValue: contents];
2517 }
2518
2519 if ([aDecoder containsValueForKey: @"NSCellFlags"])
2520 {
2521 unsigned long cFlags;
2522 unsigned long mask = 0;
2523 cFlags = [aDecoder decodeIntForKey: @"NSCellFlags"];
2524
2525 [self setFocusRingType: (cFlags & 0x3)];
2526 [self setShowsFirstResponder: ((cFlags & 0x4) == 0x4)];
2527 // This bit flag is the other way around!
2528 if ((cFlags & 0x20) != 0x20)
2529 mask |= NSLeftMouseUpMask;
2530 // This bit flag is the other way around!
2531 [self setWraps: ((cFlags & 0x40) != 0x40)];
2532 if ((cFlags & 0x100) == 0x100)
2533 mask |= NSLeftMouseDraggedMask;
2534 if ((cFlags & 0x40000) == 0x40000)
2535 mask |= NSLeftMouseDownMask;
2536 if ((cFlags & 0x80000) == 0x80000)
2537 mask |= NSPeriodicMask;
2538 [self sendActionOn: mask];
2539 [self setScrollable: ((cFlags & 0x100000) == 0x100000)];
2540 [self setSelectable: ((cFlags & 0x200000) == 0x200000)];
2541 [self setBezeled: ((cFlags & 0x400000) == 0x400000)];
2542 [self setBordered: ((cFlags & 0x800000) == 0x800000)];
2543 [self setType: ((cFlags & 0xC000000) >> 26)];
2544 [self setEditable: ((cFlags & 0x10000000) == 0x10000000)];
2545 // This bit flag is the other way around!
2546 [self setEnabled: ((cFlags & 0x20000000) != 0x20000000)];
2547 [self setHighlighted: ((cFlags & 0x40000000) == 0x40000000)];
2548 [self setState: ((cFlags & 0x80000000) == 0x80000000) ? NSOnState : NSOffState];
2549 }
2550 if ([aDecoder containsValueForKey: @"NSCellFlags2"])
2551 {
2552 int cFlags2;
2553
2554 cFlags2 = [aDecoder decodeIntForKey: @"NSCellFlags2"];
2555 [self setControlTint: ((cFlags2 & 0xE0) >> 5)];
2556 [self setLineBreakMode: ((cFlags2 & 0xE00) >> 9)];
2557 [self setControlSize: ((cFlags2 & 0xE0000) >> 17)];
2558 [self setSendsActionOnEndEditing: ((cFlags2 & 0x400000) == 0x400000)];
2559 [self setAllowsMixedState: ((cFlags2 & 0x1000000) == 0x1000000)];
2560 [self setRefusesFirstResponder: ((cFlags2 & 0x2000000) == 0x2000000)];
2561 [self setAlignment: ((cFlags2 & 0x1C000000) >> 26)];
2562 [self setImportsGraphics: ((cFlags2 & 0x20000000) == 0x20000000)];
2563 [self setAllowsEditingTextAttributes: ((cFlags2 & 0x40000000) == 0x40000000)];
2564 }
2565 if ([aDecoder containsValueForKey: @"NSSupport"])
2566 {
2567 id support = [aDecoder decodeObjectForKey: @"NSSupport"];
2568
2569 if ([support isKindOfClass: [NSFont class]])
2570 {
2571 [self setFont: support];
2572 }
2573 else if ([support isKindOfClass: [NSImage class]])
2574 {
2575 [self setImage: support];
2576 }
2577 }
2578 if ([aDecoder containsValueForKey: @"NSFormatter"])
2579 {
2580 NSFormatter *formatter = [aDecoder decodeObjectForKey: @"NSFormatter"];
2581
2582 [self setFormatter: formatter];
2583 }
2584 }
2585 else
2586 {
2587 BOOL flag, wraps;
2588 unsigned int tmp_int;
2589 id formatter, menu;
2590 int version = [aDecoder versionForClassName: @"NSCell"];
2591
2592 [aDecoder decodeValueOfObjCType: @encode(id) at: &_contents];
2593 [aDecoder decodeValueOfObjCType: @encode(id) at: &_cell_image];
2594 [aDecoder decodeValueOfObjCType: @encode(id) at: &_font];
2595 [aDecoder decodeValueOfObjCType: @encode(id) at: &_object_value];
2596 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2597 _cell.contents_is_attributed_string = flag;
2598 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2599 _cell.is_highlighted = flag;
2600 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2601 _cell.is_disabled = flag;
2602 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2603 _cell.is_editable = flag;
2604 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2605 _cell.is_rich_text = flag;
2606 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2607 _cell.imports_graphics = flag;
2608 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2609 _cell.shows_first_responder = flag;
2610 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2611 _cell.refuses_first_responder = flag;
2612 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2613 _cell.sends_action_on_end_editing = flag;
2614 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2615 _cell.is_bordered = flag;
2616 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2617 _cell.is_bezeled = flag;
2618 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2619 _cell.is_scrollable = flag;
2620 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2621 _cell.is_selectable = flag;
2622 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2623 // This used to be is_continuous, which has been replaced.
2624 //_cell.is_continuous = flag;
2625 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2626 _cell.allows_mixed_state = flag;
2627 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &flag];
2628 /* The wraps attribute has been superseded by lineBreakMode. However,
2629 we may need it to set lineBreakMode when reading old archives. */
2630 wraps = flag;
2631 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2632 _cell.text_align = tmp_int;
2633 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2634 _cell.type = tmp_int;
2635 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2636 _cell.image_position = tmp_int;
2637 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2638 _cell.entry_type = tmp_int;
2639 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2640 _cell.state = tmp_int;
2641 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2642 _cell.mnemonic_location = tmp_int;
2643 [aDecoder decodeValueOfObjCType: @encode(unsigned int)
2644 at: &_mouse_down_flags];
2645 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &_action_mask];
2646 if (version < 3)
2647 {
2648 unsigned int mask = 0;
2649
2650 // Convert old GNUstep mask value to Cocoa values
2651 if ((_action_mask & 0x1) == 0x1)
2652 {
2653 mask |= NSLeftMouseDownMask;
2654 }
2655 if ((_action_mask & 0x2) == 0x2)
2656 {
2657 mask |= NSLeftMouseUpMask;
2658 }
2659 if ((_action_mask & 0x4) == 0x4)
2660 {
2661 mask |= NSOtherMouseDownMask;
2662 }
2663 if ((_action_mask & 0x8) == 0x8)
2664 {
2665 mask |= NSOtherMouseUpMask;
2666 }
2667 if ((_action_mask & 0x10) == 0x10)
2668 {
2669 mask |= NSRightMouseDownMask;
2670 }
2671 if ((_action_mask & 0x20) == 0x20)
2672 {
2673 mask |= NSRightMouseUpMask;
2674 }
2675 if ((_action_mask & 0x40) == 0x40)
2676 {
2677 mask |= NSMouseMovedMask;
2678 }
2679 if ((_action_mask & 0x80) == 0x80)
2680 {
2681 mask |= NSLeftMouseDraggedMask;
2682 }
2683 if ((_action_mask & 0x100) == 0x100)
2684 {
2685 mask |= NSOtherMouseDraggedMask;
2686 }
2687 if ((_action_mask & 0x200) == 0x200)
2688 {
2689 mask |= NSRightMouseDraggedMask;
2690 }
2691 if ((_action_mask & 0x400) == 0x400)
2692 {
2693 mask |= NSMouseEnteredMask;
2694 }
2695 if ((_action_mask & 0x800) == 0x800)
2696 {
2697 mask |= NSMouseExitedMask;
2698 }
2699 if ((_action_mask & 0x1000) == 0x1000)
2700 {
2701 mask |= NSKeyDownMask;
2702 }
2703 if ((_action_mask & 0x2000) == 0x2000)
2704 {
2705 mask |= NSKeyUpMask;
2706 }
2707 if ((_action_mask & 0x4000) == 0x4000)
2708 {
2709 mask |= NSFlagsChangedMask;
2710 }
2711 if ((_action_mask & 0x8000) == 0x8000)
2712 {
2713 mask |= NSAppKitDefinedMask;
2714 }
2715 if ((_action_mask & 0x10000) == 0x10000)
2716 {
2717 mask |= NSSystemDefinedMask;
2718 }
2719 if ((_action_mask & 0x20000) == 0x20000)
2720 {
2721 mask |= NSApplicationDefinedMask;
2722 }
2723 if ((_action_mask & 0x40000) == 0x40000)
2724 {
2725 mask |= NSPeriodicMask;
2726 }
2727 if ((_action_mask & 0x80000) == 0x80000)
2728 {
2729 mask |= NSCursorUpdateMask;
2730 }
2731 if ((_action_mask & 0x100000) == 0x100000)
2732 {
2733 mask |= NSScrollWheelMask;
2734 }
2735 _action_mask = mask;
2736 }
2737 _action_mask |= NSLeftMouseUpMask;
2738 [aDecoder decodeValueOfObjCType: @encode(id) at: &formatter];
2739 [self setFormatter: formatter];
2740 [aDecoder decodeValueOfObjCType: @encode(id) at: &menu];
2741 [self setMenu: menu];
2742 [aDecoder decodeValueOfObjCType: @encode(id) at: &_represented_object];
2743
2744 if (_formatter != nil((id)((void*)0)))
2745 {
2746 NSString *contents;
2747
2748 contents = [_formatter stringForObjectValue: _object_value];
2749 if (contents != nil((id)((void*)0)))
2750 {
2751 _cell.has_valid_object_value = YES((BOOL)1);
2752 ASSIGN (_contents, contents)({ id __object = _contents; _contents = [(contents) retain]; [
__object release]; })
;
2753 _cell.contents_is_attributed_string = NO((BOOL)0);
2754 }
2755 }
2756
2757 if (version >= 2)
2758 {
2759 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2760 _cell.allows_undo = tmp_int;
2761 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2762 _cell.line_break_mode = tmp_int;
2763 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2764 _cell.control_tint = tmp_int;
2765 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2766 _cell.control_size = tmp_int;
2767 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2768 _cell.focus_ring_type = tmp_int;
2769 [aDecoder decodeValueOfObjCType: @encode(unsigned int) at: &tmp_int];
2770 _cell.base_writing_direction = tmp_int;
2771 }
2772 else
2773 {
2774 /* Backward compatibility: Derive lineBreakMode from the superseded
2775 wraps attribute. */
2776 [self setWraps: wraps];
2777 }
2778 }
2779 return self;
2780}
2781@end
2782
2783@implementation NSCell (PrivateMethods)
2784
2785- (NSColor*) textColor
2786{
2787 if (_cell.is_disabled)
2788 return dtxtCol;
2789 else
2790 return txtCol;
2791}
2792
2793/* This method is an exception and returns a non-autoreleased
2794 dictionary, so that calling methods can deallocate it immediately
2795 using release. Otherwise if many cells are drawn/their size
2796 computed, we pile up hundreds or thousands of these objects before they
2797 are deallocated at the end of the run loop. */
2798- (NSDictionary*) _nonAutoreleasedTypingAttributes
2799{
2800 NSDictionary *attr;
2801 NSColor *color;
2802 NSMutableParagraphStyle *paragraphStyle;
2803
2804 color = [self textColor];
2805 /* Note: There are only a few possible paragraph styles for cells.
2806 TODO: Cache them and reuse them for the whole app lifetime. */
2807 paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
2808 [paragraphStyle setLineBreakMode: [self lineBreakMode]];
2809 [paragraphStyle setBaseWritingDirection: [self baseWritingDirection]];
2810 [paragraphStyle setAlignment: [self alignment]];
2811
2812 attr = [[NSDictionary alloc] initWithObjectsAndKeys:
2813 _font, NSFontAttributeName,
2814 color, NSForegroundColorAttributeName,
2815 paragraphStyle, NSParagraphStyleAttributeName,
2816 nil((id)((void*)0))];
2817 RELEASE (paragraphStyle)[(paragraphStyle) release];
2818 return attr;
2819}
2820
2821- (NSSize) _sizeText: (NSString*)title
2822{
2823 NSSize size;
2824 NSDictionary *dict;
2825
2826 if (title == nil((id)((void*)0)))
1
Assuming 'title' is equal to nil
2
Taking false branch
2827 {
2828 return NSMakeSize (0,0);
2829 }
2830
2831 dict = [self _nonAutoreleasedTypingAttributes];
3
Method returns an Objective-C object with a +0 retain count
2832 size = [title sizeWithAttributes: dict];
2833 RELEASE (dict)[(dict) release];
4
Within the expansion of the macro 'RELEASE':
a
Incorrect decrement of the reference count of an object that is not owned at this point by the caller
2834 return size;
2835}
2836
2837/**
2838 * Private internal method, returns an attributed string to display.
2839 */
2840- (NSAttributedString*) _drawAttributedString
2841{
2842 if (!_cell.is_disabled)
2843 {
2844 return [self attributedStringValue];
2845 }
2846 else
2847 {
2848 NSAttributedString *attrStr = [self attributedStringValue];
2849 NSDictionary *attribs;
2850 NSMutableDictionary *newAttribs;
2851
2852 attribs = [attrStr attributesAtIndex: 0
2853 effectiveRange: NULL((void *)0)];
2854 newAttribs = [NSMutableDictionary dictionaryWithDictionary: attribs];
2855 [newAttribs setObject: [NSColor disabledControlTextColor]
2856 forKey: NSForegroundColorAttributeName];
2857
2858 return AUTORELEASE([[NSAttributedString alloc][([[NSAttributedString alloc] initWithString: [attrStr string
] attributes: newAttribs]) autorelease]
2859 initWithString: [attrStr string][([[NSAttributedString alloc] initWithString: [attrStr string
] attributes: newAttribs]) autorelease]
2860 attributes: newAttribs])[([[NSAttributedString alloc] initWithString: [attrStr string
] attributes: newAttribs]) autorelease]
;
2861 }
2862}
2863
2864/**
2865 * Private internal method to display an attributed string.
2866 */
2867- (void) _drawAttributedText: (NSAttributedString*)aString
2868 inFrame: (NSRect)aRect
2869{
2870 NSSize titleSize;
2871
2872 if (aString == nil((id)((void*)0)))
2873 return;
2874
2875 titleSize = [aString size];
2876
2877 /** Important: text should always be vertically centered without
2878 * considering descender [as if descender did not exist].
2879 * This is particularly important for single line texts.
2880 * Please make sure the output remains always correct.
2881 */
2882 aRect.origin.y = NSMidY (aRect) - titleSize.height/2;
2883 aRect.size.height = titleSize.height;
2884
2885 [aString drawInRect: aRect];
2886}
2887
2888- (void) _drawText: (NSString*)aString inFrame: (NSRect)cellFrame
2889{
2890 NSSize titleSize;
2891 NSDictionary *attributes;
2892
2893 if (aString == nil((id)((void*)0)))
2894 return;
2895
2896 attributes = [self _nonAutoreleasedTypingAttributes];
2897 titleSize = [aString sizeWithAttributes: attributes];
2898
2899 /** Important: text should always be vertically centered without
2900 * considering descender [as if descender did not exist].
2901 * This is particularly important for single line texts.
2902 * Please make sure the output remains always correct.
2903 */
2904 cellFrame.origin.y = NSMidY (cellFrame) - titleSize.height/2;
2905 cellFrame.size.height = titleSize.height;
2906
2907 [aString drawInRect: cellFrame withAttributes: attributes];
2908 RELEASE (attributes)[(attributes) release];
2909}
2910
2911// Private helper method overridden in subclasses
2912- (void) _drawBorderAndBackgroundWithFrame: (NSRect)cellFrame
2913 inView: (NSView*)controlView
2914{
2915 NSBorderType aType;
2916
2917 // Get border size
2918 if (_cell.is_bordered)
2919 aType = NSLineBorder;
2920 else if (_cell.is_bezeled)
2921 aType = NSBezelBorder;
2922 else
2923 aType = NSNoBorder;
2924
2925 [[GSTheme theme] drawBorderType: aType frame: cellFrame view: controlView];
2926}
2927
2928// Private helper method
2929- (void) _drawFocusRingWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
2930{
2931 if (_cell.shows_first_responder
2932 && [[controlView window] firstResponder] == controlView)
2933 {
2934 switch (_cell.focus_ring_type)
2935 {
2936 case NSFocusRingTypeDefault:
2937 [[GSTheme theme] drawFocusFrame: [self drawingRectForBounds:
2938 cellFrame]
2939 view: controlView];
2940 break;
2941 case NSFocusRingTypeExterior:
2942 [[GSTheme theme] drawFocusFrame: cellFrame
2943 view: controlView];
2944 break;
2945 case NSFocusRingTypeNone:
2946 default:
2947 break;
2948 }
2949 }
2950}
2951
2952- (void) _drawEditorWithFrame: (NSRect)cellFrame
2953 inView: (NSView *)controlView
2954{
2955 /* Look Ma', no drawing here... */
2956
2957 if ([controlView isKindOfClass: [NSControl class]])
2958 {
2959 /* Adjust the text editor's frame to match cell's frame (w/o border) */
2960 NSRect titleRect = [self titleRectForBounds: cellFrame];
2961 NSText *textObject = [(NSControl*)controlView currentEditor];
2962 NSView *clipView = [textObject superview];
2963
2964 if ([clipView isKindOfClass: [NSClipView class]])
2965 {
2966 [clipView setFrame: titleRect];
2967 }
2968 else
2969 {
2970 [textObject setFrame: titleRect];
2971 }
2972 }
2973}
2974
2975- (BOOL) _sendsActionOn:(int)eventTypeMask
2976{
2977 return (_action_mask & eventTypeMask);
2978}
2979
2980- (void) _setInEditing: (BOOL)flag
2981{
2982 _cell.in_editing = flag;
2983}
2984
2985- (void) _updateFieldEditor: (NSText*)textObject
2986{
2987 if (_formatter != nil((id)((void*)0)))
2988 {
2989 NSString *contents;
2990
2991 contents = [_formatter editingStringForObjectValue: _object_value];
2992 if (contents == nil((id)((void*)0)))
2993 {
2994 // We cannot call the stringValue method as this will call
2995 // validateEditing in NSActionCell subclasses
2996 if (nil((id)((void*)0)) == _contents)
2997 {
2998 contents = @"";
2999 }
3000 else
3001 {
3002 if (_cell.contents_is_attributed_string == NO((BOOL)0))
3003 {
3004 contents = (NSString *)_contents;
3005 }
3006 else
3007 {
3008 contents = [(NSAttributedString *)_contents string];
3009 }
3010 }
3011 }
3012 if (![contents isEqualToString: [textObject string]])
3013 [textObject setText: contents];
3014 }
3015 else
3016 {
3017 NSString *contents;
3018
3019 if (nil((id)((void*)0)) == _contents)
3020 {
3021 contents = @"";
3022 }
3023 else
3024 {
3025 if (_cell.contents_is_attributed_string == NO((BOOL)0))
3026 {
3027 contents = (NSString *)_contents;
3028 }
3029 else
3030 {
3031 contents = [(NSAttributedString *)_contents string];
3032 }
3033 }
3034 if (![contents isEqualToString: [textObject string]])
3035 {
3036 if (_cell.contents_is_attributed_string == NO((BOOL)0))
3037 {
3038 [textObject setText: contents];
3039 }
3040 else
3041 {
3042 // FIXME what about attribute changes?
3043 NSRange range = NSMakeRange(0, [[textObject string] length]);
3044 [textObject replaceCharactersInRange: range
3045 withAttributedString: (NSAttributedString *)_contents];
3046 }
3047 }
3048 }
3049}
3050
3051/**
3052 * Private method used by NSImageCell and NSButtonCell for calculating
3053 * scaled image size
3054 */
3055
3056static inline NSSize
3057scaleProportionally(NSSize imageSize, NSSize canvasSize, BOOL scaleUpOrDown)
3058{
3059 CGFloat ratio;
3060
3061 if (imageSize.width <= 0
3062 || imageSize.height <= 0)
3063 {
3064 return NSMakeSize(0, 0);
3065 }
3066
3067 /* Get the smaller ratio and scale the image size by it. */
3068 ratio = MIN(canvasSize.width / imageSize.width,(((canvasSize.width / imageSize.width)<(canvasSize.height /
imageSize.height))?(canvasSize.width / imageSize.width):(canvasSize
.height / imageSize.height))
3069 canvasSize.height / imageSize.height)(((canvasSize.width / imageSize.width)<(canvasSize.height /
imageSize.height))?(canvasSize.width / imageSize.width):(canvasSize
.height / imageSize.height))
;
3070
3071 /* Only scale down, unless scaleUpOrDown is YES */
3072 if (ratio < 1.0 || scaleUpOrDown)
3073 {
3074 imageSize.width *= ratio;
3075 imageSize.height *= ratio;
3076 }
3077
3078 return imageSize;
3079}
3080
3081- (NSSize) _scaleImageWithSize: (NSSize)imageSize
3082 toFitInSize: (NSSize)canvasSize
3083 scalingType: (NSImageScaling)scalingType
3084{
3085 NSSize result;
3086 switch (scalingType)
3087 {
3088 case NSImageScaleProportionallyDown: // == NSScaleProportionally
3089 {
3090 result = scaleProportionally (imageSize, canvasSize, NO((BOOL)0));
3091 break;
3092 }
3093 case NSImageScaleAxesIndependently: // == NSScaleToFit
3094 {
3095 result = canvasSize;
3096 break;
3097 }
3098 default:
3099 case NSImageScaleNone: // == NSScaleNone
3100 {
3101 result = imageSize;
3102 break;
3103 }
3104 case NSImageScaleProportionallyUpOrDown:
3105 {
3106 result = scaleProportionally (imageSize, canvasSize, YES((BOOL)1));
3107 break;
3108 }
3109 }
3110 return result;
3111}
3112
3113@end