Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ciaran committed Nov 17, 2008
0 parents commit 195d237
Show file tree
Hide file tree
Showing 7 changed files with 512 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
build
*.xcodeproj/*.pbxuser
*.xcodeproj/*.perspectivev3
*.xcodeproj/*.mode1v3
*.xcodeproj/*.tm_build_errors
*.tmproj
37 changes: 37 additions & 0 deletions Info.plist
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>sh.ciaranwal.terminaltabswitching</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSPrincipalClass</key>
<string>TerminalTabSwitching</string>
<key>SIMBLTargetApplications</key>
<array>
<dict>
<key>BundleIdentifier</key>
<string>com.apple.Terminal</string>
<key>MaxBundleVersion</key>
<string>240</string>
<key>MinBundleVersion</key>
<string>237</string>
</dict>
</array>
</dict>
</plist>
13 changes: 13 additions & 0 deletions JRSwizzle.h
@@ -0,0 +1,13 @@
/*******************************************************************************
JRSwizzle.h
Copyright (c) 2007 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
Some rights reserved: <http://opensource.org/licenses/mit-license.php>
***************************************************************************/

#import <Foundation/Foundation.h>

@interface NSObject (JRSwizzle)
+ (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_;
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_;
@end
115 changes: 115 additions & 0 deletions JRSwizzle.m
@@ -0,0 +1,115 @@
/*******************************************************************************
JRSwizzle.m
Copyright (c) 2007 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
Some rights reserved: <http://opensource.org/licenses/mit-license.php>
***************************************************************************/

#import "JRSwizzle.h"
#import <objc/objc-class.h>

#define SetNSError(ERROR_VAR, FORMAT,...) \
if (ERROR_VAR) { \
NSString *errStr = [@"+[NSObject(JRSwizzle) jr_swizzleMethod:withMethod:error:]: " stringByAppendingFormat:FORMAT,##__VA_ARGS__]; \
*ERROR_VAR = [NSError errorWithDomain:@"NSCocoaErrorDomain" \
code:-1 \
userInfo:[NSDictionary dictionaryWithObject:errStr forKey:NSLocalizedDescriptionKey]]; \
}

@implementation NSObject (JRSwizzle)

+ (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ {
#if OBJC_API_VERSION >= 2
Method origMethod = class_getInstanceMethod(self, origSel_);
if (!origMethod) {
SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]);
return NO;
}

Method altMethod = class_getInstanceMethod(self, altSel_);
if (!altMethod) {
SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]);
return NO;
}

class_addMethod(self,
origSel_,
class_getMethodImplementation(self, origSel_),
method_getTypeEncoding(origMethod));
class_addMethod(self,
altSel_,
class_getMethodImplementation(self, altSel_),
method_getTypeEncoding(altMethod));

method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_));
return YES;
#else
// Scan for non-inherited methods.
Method directOriginalMethod = NULL, directAlternateMethod = NULL;

void *iterator = NULL;
struct objc_method_list *mlist = class_nextMethodList(self, &iterator);
while (mlist) {
int method_index = 0;
for (; method_index < mlist->method_count; method_index++) {
if (mlist->method_list[method_index].method_name == origSel_) {
assert(!directOriginalMethod);
directOriginalMethod = &mlist->method_list[method_index];
}
if (mlist->method_list[method_index].method_name == altSel_) {
assert(!directAlternateMethod);
directAlternateMethod = &mlist->method_list[method_index];
}
}
mlist = class_nextMethodList(self, &iterator);
}

// If either method is inherited, copy it up to the target class to make it non-inherited.
if (!directOriginalMethod || !directAlternateMethod) {
Method inheritedOriginalMethod = NULL, inheritedAlternateMethod = NULL;
if (!directOriginalMethod) {
inheritedOriginalMethod = class_getInstanceMethod(self, origSel_);
if (!inheritedOriginalMethod) {
SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]);
return NO;
}
}
if (!directAlternateMethod) {
inheritedAlternateMethod = class_getInstanceMethod(self, altSel_);
if (!inheritedAlternateMethod) {
SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]);
return NO;
}
}

int hoisted_method_count = !directOriginalMethod && !directAlternateMethod ? 2 : 1;
struct objc_method_list *hoisted_method_list = malloc(sizeof(struct objc_method_list) + (sizeof(struct objc_method)*(hoisted_method_count-1)));
hoisted_method_list->method_count = hoisted_method_count;
Method hoisted_method = hoisted_method_list->method_list;

if (!directOriginalMethod) {
bcopy(inheritedOriginalMethod, hoisted_method, sizeof(struct objc_method));
directOriginalMethod = hoisted_method++;
}
if (!directAlternateMethod) {
bcopy(inheritedAlternateMethod, hoisted_method, sizeof(struct objc_method));
directAlternateMethod = hoisted_method;
}
class_addMethods(self, hoisted_method_list);
}

// Swizzle.
IMP temp = directOriginalMethod->method_imp;
directOriginalMethod->method_imp = directAlternateMethod->method_imp;
directAlternateMethod->method_imp = temp;

return YES;
#endif
}

+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ {
assert(0);
return NO;
}

@end
63 changes: 63 additions & 0 deletions TerminalTabSwitching.m
@@ -0,0 +1,63 @@
#import "JRSwizzle.h"

@implementation NSWindowController (Mine)
- (void)updateTabListMenu
{
NSMenu* windowsMenu = [[NSApplication sharedApplication] windowsMenu];

for(NSMenuItem* menuItem in [windowsMenu itemArray])
{
if([menuItem action] == @selector(selectRepresentedTabViewItem:))
[windowsMenu removeItem:menuItem];
}

NSArray* tabViewItems = [[self valueForKey:@"tabView"] tabViewItems];
for(size_t tabIndex = 0; tabIndex < [tabViewItems count]; ++tabIndex)
{
NSString* keyEquivalent = (tabIndex < 10) ? [NSString stringWithFormat:@"%d", (tabIndex+1)%10] : @"";
NSTabViewItem* tabViewItem = [tabViewItems objectAtIndex:tabIndex];
NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:[tabViewItem label]
action:@selector(selectRepresentedTabViewItem:)
keyEquivalent:keyEquivalent];
[menuItem setRepresentedObject:tabViewItem];
[windowsMenu addItem:menuItem];
[menuItem release];
}
}

- (void)TerminalTabSwitching_windowDidBecomeMain:(id)fp8;
{
[self TerminalTabSwitching_windowDidBecomeMain:fp8];
[self updateTabListMenu];
}

- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView*)aTabView
{
[self updateTabListMenu];
}

- (void)TerminalTabSwitching_awakeFromNib;
{
[[NSApplication sharedApplication] removeWindowsItem:[self window]];
[[self window] setExcludedFromWindowsMenu:YES];
[self TerminalTabSwitching_awakeFromNib];
}

- (void)selectRepresentedTabViewItem:(NSMenuItem*)item
{
NSTabViewItem* tabViewItem = [item representedObject];
[[tabViewItem tabView] selectTabViewItem:tabViewItem];
}
@end

@interface TerminalTabSwitching : NSObject
@end

@implementation TerminalTabSwitching
+ (void)load
{
[[[NSApplication sharedApplication] windowsMenu] addItem:[NSMenuItem separatorItem]];
[NSClassFromString(@"TTWindowController") jr_swizzleMethod:@selector(windowDidBecomeMain:) withMethod:@selector(TerminalTabSwitching_windowDidBecomeMain:) error:NULL];
[NSClassFromString(@"TTWindowController") jr_swizzleMethod:@selector(awakeFromNib) withMethod:@selector(TerminalTabSwitching_awakeFromNib) error:NULL];
}
@end

0 comments on commit 195d237

Please sign in to comment.