source: trunk/ICeCoffEE/ICeCoffEE/ICeCoffEEKeyEquivalents.m @ 319

Last change on this file since 319 was 319, checked in by Nicholas Riley, 13 years ago

VERSION: Starting with 1.5d1.

ICeCoffEEKeyEquivalents.m: Support "collision font" for displaying key
equivalent conflicts.

ICeCoffEE.m: Increase debug ICCF_MAX_URL_LEN to 120 for testing. Set
icons in ICCF_ConsolidateServicesMenu (needs better caching).

ICeCoffEEServicePrefController.m: Display icons, proper key
equivalents (instead of #, what was I thinking?!) and conflicts. Fix
a dumb bug in ICCF_PropagateServiceStateChange. Ellipsize long menu
items rather than chopping them off. Fix key equivalent column
getting moved when expanding disclosure triangles.

ICeCoffEELabeledIconCell.[hm]: An IconRef?-displaying text cell.

Info-APE Module.plist: Update version to 1.5d1.

ICeCoffEE.xcodeproj: Added files, no significant changes.

English.lproj/InfoPlist.strings: Update version to 1.5d1.

English.lproj/APEInfo.rtfd/TXT.rtf: Some overdue documentation
updates.

ICeCoffEEShared.[hm]: Enable debugging; we're now using
kICServiceShortcut (though not yet for customizable shortcuts) so
define its data type.

ICeCoffEETerminal.m: Remove some useless code to "extend to beginning
of string" which seems to have been stolen from the NSTextView
implementation and not well understood. Handle common uses of
parentheses in URLs; still need to do this for NSTextView.

ICeCoffEESetServicesMenu.[hm]: Needs renaming; now with icon
extraction functionality and semi-working code to create a service
info dictionary.

Info-APEManagerPrefPane.plist: Update version to 1.5d1.

File size: 6.6 KB
Line 
1//
2//  ICeCoffEEKeyEquivalents.m
3//  ICeCoffEE APE
4//
5//  Created by Nicholas Riley on Mon Jun 9 2003.
6//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9// Original implementations of these functions are in NSString-NJRExtensions
10// and NSFont-NJRExtensions from Pester.
11
12#import <Carbon/Carbon.h>
13#import <AppKit/AppKit.h>
14
15static NSFont *themeFont(ThemeFontID fontID) {
16    NSFont *themeFont = nil;
17    Str255 pstrFontName;
18    SInt16 fontSize = 0;
19    OSStatus status;
20    // can't simulate algorithmic styles in Cocoa in any case, so here's hoping nothing will be passed back - XXX guess this should at least accommodate the bold system font, but we don't need it
21    status = GetThemeFont(fontID, smSystemScript, pstrFontName, &fontSize, NULL);
22
23    if (status == noErr) {
24        NSString *fontName = (NSString *)CFStringCreateWithPascalString(NULL, pstrFontName, CFStringGetSystemEncoding());
25        themeFont = [NSFont fontWithName: fontName size: fontSize];
26        [fontName release];
27    }
28    if (themeFont == nil) {
29        themeFont = [NSFont systemFontOfSize: fontSize == 0 ? [NSFont systemFontSize] : fontSize];
30    }
31    return themeFont;
32}
33
34static NSString *stringWithCharacter(unichar character) {
35    return [NSString stringWithCharacters: &character length: 1];
36}
37
38static unichar combiningHelpChar[] = {0x003F, 0x20DD};
39
40static NSFont *menuItemCmdKeyFont = nil;
41static NSFont *menuItemFont = nil;
42static NSFont *collisionFont = nil;
43static NSParagraphStyle *keyEquivParaStyle;
44
45static inline void initialize() {
46    if (menuItemCmdKeyFont != nil) return;
47
48    menuItemCmdKeyFont = [themeFont(kThemeMenuItemCmdKeyFont) retain];
49    menuItemFont = [themeFont(kThemeMenuItemFont) retain];
50    collisionFont = [themeFont(kThemeSmallSystemFont) retain];
51
52    NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
53    [paraStyle setTabStops: [NSArray arrayWithObjects:
54        [[[NSTextTab alloc] initWithType: NSRightTabStopType location: 30] autorelease],
55        [[[NSTextTab alloc] initWithType: NSLeftTabStopType location: 30.01] autorelease],
56        nil]];
57    [paraStyle setLineBreakMode: NSLineBreakByClipping];
58    keyEquivParaStyle = [paraStyle copy];
59    [paraStyle release];
60}
61
62// set tabs here, for ICeCoffEE (not in Pester)
63static NSAttributedString *attributedStringWithFont(NSString *self, NSFont *font) {
64    return [[[NSAttributedString alloc] initWithString: self attributes: [NSDictionary dictionaryWithObjectsAndKeys: font, NSFontAttributeName, keyEquivParaStyle, NSParagraphStyleAttributeName, nil]] autorelease];
65}
66
67static NSString *keyEquivalentString(NSString *self) {
68    if ([self length] != 0) {
69        const char *str = [self UTF8String];
70        unichar keyChar;
71        if (str[1] != '\0') {
72            keyChar = [self characterAtIndex: 0];
73            switch (keyChar) {
74                case NSUpArrowFunctionKey: keyChar = 0x21E1; break;
75                case NSDownArrowFunctionKey: keyChar = 0x21E3; break;
76                case NSLeftArrowFunctionKey: keyChar = 0x21E0; break;
77                case NSRightArrowFunctionKey: keyChar = 0x21E2; break;
78                case NSInsertFunctionKey:
79                    return [NSString stringWithCharacters: combiningHelpChar length: 2];
80                case NSDeleteFunctionKey: keyChar = 0x2326; break;
81                case NSHomeFunctionKey: keyChar = 0x2196; break;
82                case NSEndFunctionKey: keyChar = 0x2198; break;
83                case NSPageUpFunctionKey: keyChar = 0x21DE; break;
84                case NSPageDownFunctionKey: keyChar = 0x21DF; break;
85                case NSClearLineFunctionKey: keyChar = 0x2327; break;
86                default:
87                    if (keyChar >= NSF1FunctionKey && keyChar <= NSF35FunctionKey) {
88                        return [NSString stringWithFormat: @"F%u", keyChar - NSF1FunctionKey + 1];
89                    }
90                    return [NSString stringWithFormat: @"[unknown %lX]", keyChar];
91            }
92        } else if (str[0] >= 'A' && str[0] <= 'Z') {
93            return self;
94        } else if (str[0] >= 'a' && str[0] <= 'z') return [self uppercaseString];
95        else switch (str[0]) {
96            case '\t': keyChar = 0x21e5; break;
97            case '\r': keyChar = 0x21a9; break;
98            case '\e': keyChar = 0x238b; break;
99            case ' ': keyChar = 0x2423; break;
100            case 0x7f: keyChar = 0x232b; break; // delete
101            case 0x03: keyChar = 0x2324; break; // enter
102            case 0x19: keyChar = 0x21e4; break; // backtab
103            case 0: return @"";
104                // case '': keyChar = 0x; break;
105            default: return self; // return [NSString stringWithFormat: @"[huh? %x]", (int)str[0]];
106        }
107            return stringWithCharacter(keyChar);
108    }
109    return self;
110}
111
112NSAttributedString *ICCF_KeyEquivalentAttributedStringWithModifierFlags(NSString *self, unsigned int modifierFlags, unsigned count) {
113    initialize();
114    NSString *keyEquivalentStringNoMask = keyEquivalentString(self);
115    // use tabs here, for ICeCoffEE (not in Pester, at least without better subclassing)
116    NSAttributedString *keyEquivalentAttributedString =
117        attributedStringWithFont(
118          [NSString stringWithFormat: @"\t%@%@%@%@\t%@",
119            (modifierFlags & NSControlKeyMask) ? stringWithCharacter(kControlUnicode) : @"",
120            (modifierFlags & NSAlternateKeyMask) ? stringWithCharacter(kOptionUnicode) : @"",
121            (modifierFlags & NSShiftKeyMask) ? stringWithCharacter(kShiftUnicode) : @"",
122            (modifierFlags & NSCommandKeyMask) ? stringWithCharacter(kCommandUnicode) : @"",
123            keyEquivalentStringNoMask], menuItemCmdKeyFont);
124    unsigned noMaskLength = [keyEquivalentStringNoMask length];
125    if (noMaskLength > 3 || // Fxx
126        (noMaskLength == 1 && [keyEquivalentStringNoMask characterAtIndex: 0] <= 0x7F)) {
127        NSMutableAttributedString *astr = [keyEquivalentAttributedString mutableCopy];
128        [astr setAttributes: [NSDictionary dictionaryWithObject: menuItemFont forKey: NSFontAttributeName] range: NSMakeRange([astr length] - noMaskLength, noMaskLength)];
129        keyEquivalentAttributedString = [[astr copy] autorelease];
130        [astr release];
131    }
132    if (count > 1) {
133        NSMutableAttributedString *astr = [keyEquivalentAttributedString mutableCopy];
134        [astr appendAttributedString: [[[NSAttributedString alloc]
135            initWithString: [NSString stringWithFormat: @" (%u)", count]
136                attributes: [NSDictionary dictionaryWithObjectsAndKeys: collisionFont, NSFontAttributeName, [NSColor redColor], NSForegroundColorAttributeName, nil]] autorelease]];
137        keyEquivalentAttributedString = [[astr copy] autorelease];
138        [astr release];
139    }
140    return keyEquivalentAttributedString;
141}
Note: See TracBrowser for help on using the repository browser.