// -*- mode:objc -*-
// $Id: PseudoTerminal.m,v 1.425 2008/09/24 08:47:35 delx Exp $
//
/*
** PseudoTerminal.m
**
** Copyright (c) 2002, 2003
**
** Author: Fabian, Ujwal S. Setlur
** Initial code by Kiichi Kusama
**
** Project: iTerm
**
** Description: Session and window controller for iTerm.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Debug option
#define DEBUG_ALLOC 0
#define DEBUG_METHOD_TRACE 0
#import <iTerm/iTerm.h>
#import <iTerm/PseudoTerminal.h>
#import <iTerm/PTYScrollView.h>
#import <iTerm/NSStringITerm.h>
#import <iTerm/PTYSession.h>
#import <iTerm/VT100Screen.h>
#import <iTerm/PTYTabView.h>
#import <iTerm/PreferencePanel.h>
#import <iTerm/iTermController.h>
#import <iTerm/PTYTask.h>
#import <iTerm/PTYTextView.h>
#import <iTerm/VT100Terminal.h>
#import <iTerm/VT100Screen.h>
#import <iTerm/PTYSession.h>
#import <iTerm/PTToolbarController.h>
#import <iTerm/FindPanelWindowController.h>
#import <iTerm/ITAddressBookMgr.h>
#import <iTerm/ITConfigPanelController.h>
#import <iTerm/iTermTerminalProfileMgr.h>
#import <iTerm/iTermDisplayProfileMgr.h>
#import <iTerm/Tree.h>
#import <PSMTabBarControl.h>
#import <PSMTabStyle.h>
#import <iTermBookmarkController.h>
#import <iTermOutlineView.h>
#import <iTerm/iTermGrowlDelegate.h>
#include <unistd.h>
@interface PSMTabBarControl (Private)
- (void)update;
@end
@interface NSWindow (private)
- (void)setBottomCornerRounded:(BOOL)rounded;
@end
// keys for attributes:
NSString *columnsKey = @"columns";
NSString *rowsKey = @"rows";
// keys for to-many relationships:
NSString *sessionsKey = @"sessions";
#define TABVIEW_TOP_OFFSET 29
#define TABVIEW_BOTTOM_OFFSET 27
#define TABVIEW_LEFT_RIGHT_OFFSET 29
#define TOOLBAR_OFFSET 0
// just to keep track of available window positions
#define CACHED_WINDOW_POSITIONS 100
static unsigned int windowPositions[CACHED_WINDOW_POSITIONS];
@implementation PseudoTerminal
// Utility
+ (void) breakDown:(NSString *)cmdl cmdPath: (NSString **) cmd cmdArgs: (NSArray **) path
{
int i,j,k,qf,slen;
char tmp[100];
const char *s;
NSMutableArray *p;
p=[[NSMutableArray alloc] init];
s=[cmdl cString];
slen = strlen(s);
i=j=qf=0;
k=-1;
while (i<=slen) {
if (qf) {
if (s[i]=='\"') {
qf=0;
}
else {
tmp[j++]=s[i];
}
}
else {
if (s[i]=='\"') {
qf=1;
}
else if (s[i]==' ' || s[i]=='\t' || s[i]=='\n'||s[i]==0) {
tmp[j]=0;
if (k==-1) {
*cmd=[NSString stringWithCString:tmp];
}
else
[p addObject:[NSString stringWithCString:tmp]];
j=0;
k++;
while (i<slen&&s[i+1]==' '||s[i+1]=='\t'||s[i+1]=='\n'||s[i+1]==0) i++;
}
else {
tmp[j++]=s[i];
}
}
i++;
}
*path = [NSArray arrayWithArray:p];
[p release];
}
- (id)initWithWindowNibName: (NSString *) windowNibName
{
NSScrollView *aScrollView;
NSTableColumn *aTableColumn;
NSSize aSize;
NSRect aRect;
unsigned int styleMask;
PTYWindow *myWindow;
NSDrawer *myDrawer;
if ((self = [super initWithWindowNibName: windowNibName]) == nil)
return nil;
//enforce the nib to load
[self window];
[commandField retain];
[commandField setDelegate:self];
// create the window programmatically with appropriate style mask
styleMask = NSTitledWindowMask |
NSClosableWindowMask |
NSMiniaturizableWindowMask |
NSResizableWindowMask;
// set the window style according to preference
if([[PreferencePanel sharedInstance] windowStyle] == 0)
styleMask |= NSTexturedBackgroundWindowMask;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
else if([[PreferencePanel sharedInstance] windowStyle] == 2)
styleMask |= NSUnifiedTitleAndToolbarWindowMask;
#endif
myWindow = [[PTYWindow alloc] initWithContentRect: [[NSScreen mainScreen] frame]
styleMask: styleMask
backing: NSBackingStoreBuffered
defer: NO];
[self setWindow: myWindow];
[myWindow release];
_fullScreen = NO;
// create and set up drawer
myDrawer = [[NSDrawer alloc] initWithContentSize: NSMakeSize(20, 100) preferredEdge: NSMinXEdge];
[myDrawer setParentWindow: myWindow];
[myDrawer setDelegate:self];
[myWindow setDrawer: myDrawer];
float aWidth = [[NSUserDefaults standardUserDefaults] floatForKey: @"BookmarksDrawerWidth"];
if (aWidth<=0) aWidth = 150.0;
[myDrawer setContentSize: NSMakeSize(aWidth, 0)];
[myDrawer release];
aScrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 20, 100)];
[aScrollView setBorderType:NSBezelBorder];
[aScrollView setHasHorizontalScroller: NO];
[aScrollView setHasVerticalScroller: YES];
[[aScrollView verticalScroller] setControlSize:NSSmallControlSize];
[aScrollView setAutohidesScrollers: YES];
aSize = [aScrollView contentSize];
aRect = NSZeroRect;
aRect.size = aSize;
bookmarksView = [[iTermOutlineView alloc] initWithFrame:aRect];
aTableColumn = [[NSTableColumn alloc] initWithIdentifier: @"Name"];
[[aTableColumn headerCell] setStringValue: NSLocalizedStringFromTableInBundle(@"Bookmarks",@"iTerm", [NSBundle bundleForClass: [self class]], @"Bookmarks")];
[bookmarksView addTableColumn: aTableColumn];
[aTableColumn release];
[bookmarksView setOutlineTableColumn: aTableColumn];
[bookmarksView setDelegate: self];
[bookmarksView setTarget: self];
[bookmarksView setDoubleAction: @selector(doubleClickedOnBookmarksView:)];
[bookmarksView setDataSource: [iTermBookmarkController sharedInstance]];
[aScrollView setDocumentView:bookmarksView];
[bookmarksView release];
[myDrawer setContentView: aScrollView];
[aScrollView release];
[self _commonInit];
#if DEBUG_ALLOC
NSLog(@"%s: 0x%x", __PRETTY_FUNCTION__, self);
#endif
_resizeInProgressFlag = NO;
return self;
}
- (id)initWithFullScreenWindowNibName: (NSString *) windowNibName
{
PTYWindow *myWindow;
NSScreen *currentScreen = [[[[iTermController sharedInstance] currentTerminal] window]screen];
if ((self = [super initWithWindowNibName: windowNibName]) == nil)
return nil;
myWindow = [[PTYWindow alloc] initWithContentRect: [currentScreen frame]
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreBuffered
defer: NO];
[self setWindow: myWindow];
[self hideMenuBar];
[myWindow release];
_fullScreen = YES;
[self _commonInit];
#if DEBUG_ALLOC
NSLog(@"%s: 0x%x", __PRETTY_FUNCTION__, self);
#endif
_resizeInProgressFlag = NO;
return self;
}
- (id)init
{
self = ([self initWithWindowNibName: @"PseudoTerminal"]);
// Look for an available window position
for (int i = 0; i < CACHED_WINDOW_POSITIONS; i++)
{
if(windowPositions[i] == 0)
{
[[self window] setFrameAutosaveName: [NSString stringWithFormat: @"iTerm Window %d", i]];
windowPositions[i] = (unsigned int) self;
break;
}
}
return self;
}
// Do not use both initViewWithFrame and initWindow
// initViewWithFrame is mainly meant for embedding a terminal view in a non-iTerm window.
- (PTYTabView*) initViewWithFrame: (NSRect) frame
{
NSFont *aFont1, *aFont2;
NSSize contentSize;
NSString *displayProfile;
// sanity check
if(TABVIEW != nil)
return (TABVIEW);
// Create the tabview
TABVIEW = [[PTYTabView alloc] initWithFrame: frame];
[TABVIEW setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
[TABVIEW setAllowsTruncatedLabels: NO];
[TABVIEW setControlSize: NSSmallControlSize];
[TABVIEW setAutoresizesSubviews: YES];
// Tell us whenever something happens with the tab view
[TABVIEW setDelegate: self];
aFont1 = FONT;
if(aFont1 == nil)
{
NSDictionary *defaultSession = [[ITAddressBookMgr sharedInstance] defaultBookmarkData];
displayProfile = [defaultSession objectForKey: KEY_DISPLAY_PROFILE];
if(displayProfile == nil)
displayProfile = [[iTermDisplayProfileMgr singleInstance] defaultProfileName];
aFont1 = [[iTermDisplayProfileMgr singleInstance] windowFontForProfile: displayProfile];
aFont2 = [[iTermDisplayProfileMgr singleInstance] windowNAFontForProfile: displayProfile];
[self setFont: aFont1 nafont: aFont2];
}
NSParameterAssert(aFont1 != nil);
// Calculate the size of the terminal
contentSize = [NSScrollView contentSizeForFrameSize: [TABVIEW contentRect].size
hasHorizontalScroller: NO
hasVerticalScroller: ![[PreferencePanel sharedInstance] hideScrollbar]
borderType: NSNoBorder];
[self setCharSizeUsingFont: aFont1];
[self setWidth: (int) ((contentSize.width - MARGIN * 2)/charWidth + 0.1)
height: (int) ((contentSize.height) /charHeight + 0.1)];
return ([TABVIEW autorelease]);
}
// Do not use both initViewWithFrame and initWindow
- (void)initWindowWithAddressbook:(NSDictionary *)entry;
{
NSRect aRect;
// sanity check
if(TABVIEW != nil)
return;
if (!_fullScreen) {
_toolbarController = [[PTToolbarController alloc] initWithPseudoTerminal:self];
if ([[self window] respondsToSelector:@selector(setBottomCornerRounded:)])
[[self window] setBottomCornerRounded:NO];
}
// create the tab bar control
aRect = [[[self window] contentView] bounds];
aRect.size.height = 22;
tabBarControl = [[PSMTabBarControl alloc] initWithFrame: aRect];
[tabBarControl setAutoresizingMask: (NSViewWidthSizable | NSViewMinYMargin)];
[[[self window] contentView] addSubview: tabBarControl];
[tabBarControl release];
// create the tabview
aRect = [[[self window] contentView] bounds];
//aRect.size.height -= [tabBarControl frame].size.height;
TABVIEW = [[PTYTabView alloc] initWithFrame: aRect];
[TABVIEW setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
[TABVIEW setAutoresizesSubviews: YES];
[TABVIEW setAllowsTruncatedLabels: NO];
[TABVIEW setControlSize: NSSmallControlSize];
[TABVIEW setTabViewType: NSNoTabsNoBorder];
// Add to the window
[[[self window] contentView] addSubview: TABVIEW];
[TABVIEW release];
// assign tabview and delegates
[tabBarControl setTabView: TABVIEW];
[TABVIEW setDelegate: tabBarControl];
[tabBarControl setDelegate: self];
[tabBarControl setHideForSingleTab: NO];
[tabBarControl setHidden:_fullScreen];
// set the style of tabs to match window style
switch ([[PreferencePanel sharedInstance] windowStyle]) {
case 0:
[tabBarControl setStyleNamed:@"Metal"];
break;
case 1:
[tabBarControl setStyleNamed:@"Aqua"];
break;
case 2:
[tabBarControl setStyleNamed:@"Unified"];
break;
default:
[tabBarControl setStyleNamed:@"Adium"];
break;
}
[[[self window] contentView] setAutoresizesSubviews: YES];
[[self window] setDelegate: self];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(_reloadAddressBook:)
name: @"iTermReloadAddressBook"
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(_refreshTerminal:)
name: @"iTermRefreshTerminal"
object: nil];
[self setWindowInited: YES];
if (entry) {
NSString *displayProfile;
iTermDisplayProfileMgr *displayProfileMgr;
displayProfileMgr = [iTermDisplayProfileMgr singleInstance];
// grab the profiles
displayProfile = [entry objectForKey: KEY_DISPLAY_PROFILE];
if(displayProfile == nil)
displayProfile = [displayProfileMgr defaultProfileName];
[self setAntiAlias: [displayProfileMgr windowAntiAliasForProfile: displayProfile]];
[self setBlur: [displayProfileMgr windowBlurForProfile: displayProfile]];
[self setFont: [displayProfileMgr windowFontForProfile: displayProfile]
nafont: [displayProfileMgr windowNAFontForProfile: displayProfile]];
[self setCharacterSpacingHorizontal: [displayProfileMgr windowHorizontalCharSpacingForProfile: displayProfile]
vertical: [displayProfileMgr windowVerticalCharSpacingForProfile: displayProfile]];
if (_fullScreen) {
aRect = [TABVIEW frame];
WIDTH = (int)((aRect.size.width - MARGIN * 2)/charWidth);
HEIGHT = (int)((aRect.size.height)/charHeight);
}
else {
WIDTH = [displayProfileMgr windowColumnsForProfile: displayProfile];
HEIGHT = [displayProfileMgr windowRowsForProfile: displayProfile];
}
}
// position the tabview and control
if (_fullScreen) {
aRect = [[[self window] contentView] bounds];
aRect = NSMakeRect(floor((aRect.size.width-WIDTH*charWidth-MARGIN*2)/2),floor((aRect.size.height-charHeight*HEIGHT)/2),WIDTH*charWidth+MARGIN*2, charHeight*HEIGHT);
[TABVIEW setFrame: aRect];
}
else {
aRect = [TABVIEW frame];
aRect.origin.x = 0;
aRect.origin.y = 0;
[TABVIEW setFrame: aRect];
aRect = [tabBarControl frame];
aRect.origin.x = 0;
aRect.origin.y = [TABVIEW frame].size.height;
aRect.size.width = [[[self window] contentView] bounds].size.width;
[tabBarControl setFrame: aRect];
[tabBarControl setSizeCellsToFit:NO];
[tabBarControl setCellMinWidth:75];
[tabBarControl setCellOptimumWidth:175];
}
}
- (void)initWindowWithSettingsFrom:(PseudoTerminal *)aPseudoTerminal
{
NSRect aRect;
// sanity check
if(TABVIEW != nil)
return;
// Take over the window position
for (int i = 0; i < CACHED_WINDOW_POSITIONS; i++)
{
if (windowPositions[i] == (unsigned int)aPseudoTerminal)
{
if (!_fullScreen)
[[self window] setFrameAutosaveName: [NSString stringWithFormat: @"iTerm Window %d", i]];
windowPositions[i] = (unsigned int)self;
break;
}
}
if (!_fullScreen) {
_toolbarController = [[PTToolbarController alloc] initWithPseudoTerminal:self];
if ([[self window] respondsToSelector:@selector(setBottomCornerRounded:)])
[[self window] setBottomCornerRounded:NO];
}
// create the tab bar control
aRect = [[[self window] contentView] bounds];
aRect.size.height = 22;
tabBarControl = [[PSMTabBarControl alloc] initWithFrame: aRect];
[tabBarControl setAutoresizingMask: (NSViewWidthSizable | NSViewMinYMargin)];
[[[self window] contentView] addSubview: tabBarControl];
[tabBarControl release];
// create the tabview
aRect = [[[self window] contentView] bounds];
//aRect.size.height -= [tabBarControl frame].size.height;
TABVIEW = [[PTYTabView alloc] initWithFrame: aRect];
[TABVIEW setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
[TABVIEW setAutoresizesSubviews: YES];
[TABVIEW setAllowsTruncatedLabels: NO];
[TABVIEW setControlSize: NSSmallControlSize];
[TABVIEW setTabViewType: NSNoTabsNoBorder];
// Add to the window
[[[self window] contentView] addSubview: TABVIEW];
[TABVIEW release];
// assign tabview and delegates
[tabBarControl setTabView: TABVIEW];
[TABVIEW setDelegate: tabBarControl];
[tabBarControl setDelegate: self];
[tabBarControl setHideForSingleTab: NO];
[tabBarControl setHidden:_fullScreen];
// set the style of tabs to match window style
switch ([[PreferencePanel sharedInstance] windowStyle]) {
case 0:
[tabBarControl setStyleNamed:@"Metal"];
break;
case 1:
[tabBarControl setStyleNamed:@"Aqua"];
break;
case 2:
[tabBarControl setStyleNamed:@"Unified"];
break;
default:
[tabBarControl setStyleNamed:@"Adium"];
break;
}
[[[self window] contentView] setAutoresizesSubviews: YES];
[[self window] setDelegate: self];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(_reloadAddressBook:)
name: @"iTermReloadAddressBook"
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(_refreshTerminal:)
name: @"iTermRefreshTerminal"
object: nil];
[self setWindowInited: YES];
if (aPseudoTerminal) {
[self setAntiAlias: [aPseudoTerminal antiAlias]];
[self setBlur: [aPseudoTerminal blur]];
[self setFont: [aPseudoTerminal font]
nafont: [aPseudoTerminal nafont]];
oldFont = [FONT retain];
oldNAFont = [NAFONT retain];
fontSizeFollowWindowResize = [aPseudoTerminal fontSizeFollowWindowResize];
useTransparency = [aPseudoTerminal useTransparency];
[self setCharacterSpacingHorizontal: [aPseudoTerminal charSpacingHorizontal]
vertical: [aPseudoTerminal charSpacingVertical]];
if (_fullScreen) {
// we are entering full screen mode. store the original size
WIDTH = oldWidth = [aPseudoTerminal width];
HEIGHT = oldHeight = [aPseudoTerminal height];
charHorizontalSpacingMultiplier = oldCharHorizontalSpacingMultiplier = [aPseudoTerminal charSpacingHorizontal];
charVerticalSpacingMultiplier= oldCharVerticalSpacingMultiplier = [aPseudoTerminal charSpacingVertical];
aRect = [TABVIEW frame];
if (fontSizeFollowWindowResize) {
float scale = (aRect.size.height) / HEIGHT / charHeight;
NSFont *font = [[NSFontManager sharedFontManager] convertFont:FONT toSize:(int)(([FONT pointSize] * scale))];
font = [self _getMaxFont:font height:aRect.size.height lines:HEIGHT];
float height = [font defaultLineHeightForFont] * charVerticalSpacingMultiplier;
if (height != charHeight) {
//NSLog(@"Old size: %f\t proposed New size:%f\tWindow Height: %f",[FONT pointSize], [font pointSize],frame.size.height);
NSFont *nafont = [[NSFontManager sharedFontManager] convertFont:FONT toSize:(int)(([NAFONT pointSize] * scale))];
nafont = [self _getMaxFont:nafont height:aRect.size.height lines:HEIGHT];
[self setFont:font nafont:nafont];
}
}
else {
WIDTH = (int)((aRect.size.width - MARGIN * 2)/charWidth);
HEIGHT = (int)((aRect.size.height)/charHeight);
}
}
else {
if ([aPseudoTerminal fullScreen]) {
// we are exiting full screen mode. restore the original size.
WIDTH = [aPseudoTerminal oldWidth];
HEIGHT = [aPseudoTerminal oldHeight];
charHorizontalSpacingMultiplier =[aPseudoTerminal oldCharSpacingHorizontal];
charVerticalSpacingMultiplier= [aPseudoTerminal oldCharSpacingVertical];
[self setFont:[aPseudoTerminal oldFont] nafont:[aPseudoTerminal oldNAFont]];
}
else {
WIDTH = [aPseudoTerminal width];
HEIGHT = [aPseudoTerminal height];
}
}
}
// position the tabview and control
if (_fullScreen) {
aRect = [[[self window] contentView] bounds];
aRect = NSMakeRect(floor((aRect.size.width-WIDTH*charWidth-MARGIN*2)/2),floor((aRect.size.height-charHeight*HEIGHT)/2),WIDTH*charWidth+MARGIN*2, charHeight*HEIGHT);
[TABVIEW setFrame: aRect];
}
else {
aRect = [TABVIEW frame];
aRect.origin.x = 0;
aRect.origin.y = 0;
[TABVIEW setFrame: aRect];
aRect = [tabBarControl frame];
aRect.origin.x = 0;
aRect.origin.y = [TABVIEW frame].size.height;
aRect.size.width = [[[self window] contentView] bounds].size.width;
[tabBarControl setFrame: aRect];
[tabBarControl setSizeCellsToFit:NO];
[tabBarControl setCellMinWidth:75];
[tabBarControl setCellOptimumWidth:175];
}
}
- (id) commandField
{
return commandField;
}
- (void)setupSession: (PTYSession *) aSession
title: (NSString *)title
{
NSDictionary *addressBookPreferences;
NSDictionary *tempPrefs;
NSString *terminalProfile, *displayProfile;
iTermTerminalProfileMgr *terminalProfileMgr;
iTermDisplayProfileMgr *displayProfileMgr;
ITAddressBookMgr *bookmarkManager;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal setupSession]",
__FILE__, __LINE__);
#endif
NSParameterAssert(aSession != nil);
// get our shared managers
terminalProfileMgr = [iTermTerminalProfileMgr singleInstance];
displayProfileMgr = [iTermDisplayProfileMgr singleInstance];
bookmarkManager = [ITAddressBookMgr sharedInstance];
// Init the rest of the session
[aSession setParent: self];
// set some default parameters
if([aSession addressBookEntry] == nil)
{
// get the default entry
addressBookPreferences = [[ITAddressBookMgr sharedInstance] defaultBookmarkData];
[aSession setAddressBookEntry:addressBookPreferences];
tempPrefs = addressBookPreferences;
}
else
{
tempPrefs = [aSession addressBookEntry];
}
terminalProfile = [tempPrefs objectForKey: KEY_TERMINAL_PROFILE];
displayProfile = [tempPrefs objectForKey: KEY_DISPLAY_PROFILE];
if(WIDTH == 0 && HEIGHT == 0)
{
WIDTH = [displayProfileMgr windowColumnsForProfile: displayProfile];
HEIGHT = [displayProfileMgr windowRowsForProfile: displayProfile];
[self setAntiAlias: [displayProfileMgr windowAntiAliasForProfile: displayProfile]];
[self setBlur: [displayProfileMgr windowBlurForProfile: displayProfile]];
}
if ([aSession initScreen: [TABVIEW contentRect] width:WIDTH height:HEIGHT]) {
if(FONT == nil)
{
[self setFont: [displayProfileMgr windowFontForProfile: displayProfile]
nafont: [displayProfileMgr windowNAFontForProfile: displayProfile]];
[self setCharacterSpacingHorizontal: [displayProfileMgr windowHorizontalCharSpacingForProfile: displayProfile]
vertical: [displayProfileMgr windowVerticalCharSpacingForProfile: displayProfile]];
}
[aSession setPreferencesFromAddressBookEntry: tempPrefs];
[[aSession SCREEN] setDisplay:[aSession TEXTVIEW]];
[[aSession TEXTVIEW] setFont:FONT nafont:NAFONT];
[[aSession TEXTVIEW] setAntiAlias: antiAlias];
[[aSession TEXTVIEW] setLineHeight: charHeight];
[[aSession TEXTVIEW] setLineWidth: WIDTH * charWidth];
[[aSession TEXTVIEW] setCharWidth: charWidth];
// NSLog(@"%d,%d",WIDTH,HEIGHT);
[[aSession TERMINAL] setTrace:YES]; // debug vt100 escape sequence decode
// tell the shell about our size
[[aSession SHELL] setWidth:WIDTH height:HEIGHT];
if (title)
{
[self setWindowTitle: title];
[aSession setName: title];
[aSession setDefaultName: title];
}
}
else {
};
}
- (void)selectSessionAtIndexAction:(id)sender
{
[TABVIEW selectTabViewItemAtIndex:[sender tag]];
}
- (void) newSessionInTabAtIndex: (id) sender
{
[self addNewSession: [sender representedObject]];
}
- (void) insertSession: (PTYSession *) aSession atIndex: (int) index
{
NSTabViewItem *aTabViewItem;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal insertSession: 0x%x atIndex: %d]",
__FILE__, __LINE__, aSession, index);
#endif
if(aSession == nil)
return;
if ([TABVIEW indexOfTabViewItemWithIdentifier: aSession] == NSNotFound)
{
// create a new tab
aTabViewItem = [[NSTabViewItem alloc] initWithIdentifier: aSession];
[aSession setTabViewItem: aTabViewItem];
NSParameterAssert(aTabViewItem != nil);
[aTabViewItem setLabel: [aSession name]];
[aTabViewItem setView: [aSession view]];
//[[aSession SCROLLVIEW] setLineScroll: charHeight];
//[[aSession SCROLLVIEW] setPageScroll: HEIGHT*charHeight/2];
[TABVIEW insertTabViewItem: aTabViewItem atIndex: index];
[aTabViewItem release];
[TABVIEW selectTabViewItemAtIndex: index];
if([self windowInited] && !_fullScreen)
[[self window] makeKeyAndOrderFront: self];
[[iTermController sharedInstance] setCurrentTerminal: self];
[self setWindowSize];
}
}
- (void) closeSession: (PTYSession*) aSession
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s: 0x%x", __PRETTY_FUNCTION__, aSession);
#endif
NSTabViewItem *aTabViewItem;
int numberOfSessions;
if([TABVIEW indexOfTabViewItemWithIdentifier: aSession] == NSNotFound)
return;
numberOfSessions = [TABVIEW numberOfTabViewItems];
if(numberOfSessions == 1 && [self windowInited])
{
[[self window] close];
}
else {
// now get rid of this session
aTabViewItem = [aSession tabViewItem];
[aSession terminate];
[TABVIEW removeTabViewItem: aTabViewItem];
}
}
- (IBAction) closeCurrentSession: (id) sender
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal closeCurrentSession]",
__FILE__, __LINE__);
#endif
PTYSession *aSession = [[TABVIEW selectedTabViewItem] identifier];
if ([aSession exited] ||
![[PreferencePanel sharedInstance] promptOnClose] || [[PreferencePanel sharedInstance] onlyWhenMoreTabs] ||
(NSRunAlertPanel([NSString stringWithFormat:@"%@ #%d", [aSession name], [aSession realObjectCount]],
NSLocalizedStringFromTableInBundle(@"This session will be closed.",@"iTerm", [NSBundle bundleForClass: [self class]], @"Close Session"),
NSLocalizedStringFromTableInBundle(@"OK",@"iTerm", [NSBundle bundleForClass: [self class]], @"OK"),
NSLocalizedStringFromTableInBundle(@"Cancel",@"iTerm", [NSBundle bundleForClass: [self class]], @"Cancel")
,nil) == NSAlertDefaultReturn))
[self closeSession:[[TABVIEW selectedTabViewItem] identifier]];
}
- (IBAction)previousSession:(id)sender
{
NSTabViewItem *tvi=[TABVIEW selectedTabViewItem];
[TABVIEW selectPreviousTabViewItem: sender];
if (tvi==[TABVIEW selectedTabViewItem]) [TABVIEW selectTabViewItemAtIndex: [TABVIEW numberOfTabViewItems]-1];
}
- (IBAction) nextSession:(id)sender
{
NSTabViewItem *tvi=[TABVIEW selectedTabViewItem];
[TABVIEW selectNextTabViewItem: sender];
if (tvi==[TABVIEW selectedTabViewItem]) [TABVIEW selectTabViewItemAtIndex: 0];
}
- (NSString *) currentSessionName
{
return ([[[TABVIEW selectedTabViewItem] identifier] defaultName]);
}
- (void) setCurrentSessionName: (NSString *) theSessionName
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal setCurrentSessionName]",
__FILE__, __LINE__);
#endif
NSMutableString *title = [NSMutableString string];
PTYSession *aSession = [[TABVIEW selectedTabViewItem] identifier];
if(theSessionName != nil)
{
[aSession setName: theSessionName];
[aSession setDefaultName: theSessionName];
}
else {
NSString *progpath = [NSString stringWithFormat: @"%@ #%d", [[[[aSession SHELL] path] pathComponents] lastObject], [TABVIEW indexOfTabViewItem:[TABVIEW selectedTabViewItem]]];
if ([aSession exited])
[title appendString:@"Finish"];
else
[title appendString:progpath];
[aSession setName: title];
[aSession setDefaultName: title];
}
}
- (PTYSession *) currentSession
{
return [[TABVIEW selectedTabViewItem] identifier];
}
- (int) currentSessionIndex
{
return ([TABVIEW indexOfTabViewItem:[TABVIEW selectedTabViewItem]]);
}
- (void)dealloc
{
#if DEBUG_ALLOC
NSLog(@"%s: 0x%x", __PRETTY_FUNCTION__, self);
#endif
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Release all our sessions
NSTabViewItem *aTabViewItem;
for(;[TABVIEW numberOfTabViewItems];)
{
aTabViewItem = [TABVIEW tabViewItemAtIndex:0];
[[aTabViewItem identifier] terminate];
[TABVIEW removeTabViewItem: aTabViewItem];
}
[commandField release];
[FONT release];
[NAFONT release];
[oldFont release];
[oldNAFont release];
[_toolbarController release];
[super dealloc];
}
- (void)startProgram:(NSString *)program
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal startProgram:%@]",
__FILE__, __LINE__, program );
#endif
[[self currentSession] startProgram:program
arguments:[NSArray array]
environment:[NSDictionary dictionary]];
}
- (void)startProgram:(NSString *)program arguments:(NSArray *)prog_argv
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal startProgram:%@ arguments:%@]",
__FILE__, __LINE__, program, prog_argv );
#endif
[[self currentSession] startProgram:program
arguments:prog_argv
environment:[NSDictionary dictionary]];
}
- (void)startProgram:(NSString *)program
arguments:(NSArray *)prog_argv
environment:(NSDictionary *)prog_env
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal startProgram:%@ arguments:%@]",
__FILE__, __LINE__, program, prog_argv );
#endif
[[self currentSession] startProgram:program
arguments:prog_argv
environment:prog_env];
if ([[[self window] title] compare:@"Window"]==NSOrderedSame)
[self setWindowTitle];
}
- (void) setWidth: (int) width height: (int) height
{
WIDTH = width;
HEIGHT = height;
}
- (int)width;
{
return WIDTH;
}
- (int)height;
{
return HEIGHT;
}
- (int)oldWidth;
{
return oldWidth;
}
- (int)oldHeight;
{
return oldHeight;
}
- (void)setCharSizeUsingFont: (NSFont *)font
{
int i;
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSSize sz;
[dic setObject:font forKey:NSFontAttributeName];
sz = [@"W" sizeWithAttributes:dic];
charWidth = (sz.width * charHorizontalSpacingMultiplier);
charHeight = ([font defaultLineHeightForFont] * charVerticalSpacingMultiplier);
for(i=0;i<[TABVIEW numberOfTabViewItems]; i++)
{
PTYSession* session = [[TABVIEW tabViewItemAtIndex:i] identifier];
[[session TEXTVIEW] setCharWidth: charWidth];
[[session TEXTVIEW] setLineHeight: charHeight];
[[session TEXTVIEW] resetCharCache];
}
[[self window] setResizeIncrements: NSMakeSize(charWidth, charHeight)];
}
- (int)charWidth
{
return charWidth;
}
- (int)charHeight
{
return charHeight;
}
- (float) charSpacingHorizontal
{
return (charHorizontalSpacingMultiplier);
}
- (float) charSpacingVertical
{
return (charVerticalSpacingMultiplier);
}
- (float) oldCharSpacingVertical
{
return (oldCharVerticalSpacingMultiplier);
}
- (float) oldCharSpacingHorizontal
{
return (oldCharHorizontalSpacingMultiplier);
}
- (void)setWindowSize
{
NSSize size, vsize, winSize, tabViewSize;
NSWindow *thisWindow = [self window];
NSRect aRect;
NSPoint topLeft;
float max_height;
BOOL vmargin_added = NO;
BOOL hasScrollbar = !_fullScreen && ![[PreferencePanel sharedInstance] hideScrollbar];
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal setWindowSize] (%d,%d)", __FILE__, __LINE__, WIDTH, HEIGHT );
#endif
if([self windowInited] == NO)
return;
if (!_resizeInProgressFlag) {
_resizeInProgressFlag = YES;
if (!_fullScreen) {
aRect = [thisWindow contentRectForFrameRect:[[thisWindow screen] visibleFrame]];
if ([TABVIEW numberOfTabViewItems] > 1 || ![[PreferencePanel sharedInstance] hideTab])
aRect.size.height -= [tabBarControl frame].size.height;
max_height = aRect.size.height / charHeight;
if (WIDTH<20) WIDTH=20;
if (HEIGHT<2) HEIGHT=2;
if (HEIGHT>max_height) HEIGHT=max_height;
// desired size of textview
vsize.width = charWidth * WIDTH + MARGIN * 2;
vsize.height = charHeight * HEIGHT;
// NSLog(@"width=%d,height=%d",[[[_sessionMgr currentSession] SCREEN] width],[[[_sessionMgr currentSession] SCREEN] height]);
// desired size of scrollview
size = [PTYScrollView frameSizeForContentSize:vsize
hasHorizontalScroller:NO
hasVerticalScroller:hasScrollbar
borderType:NSNoBorder];
[thisWindow setShowsResizeIndicator: hasScrollbar];
#if 0
NSLog(@"%s: scrollview content size %.1f, %.1f", __PRETTY_FUNCTION__,
size.width, size.height);
#endif
// desired size of tabview
tabViewSize = [PTYTabView frameSizeForContentSize:size
tabViewType:[TABVIEW tabViewType]
controlSize:[TABVIEW controlSize]];
#if 0
NSLog(@"%s: tabview content size %.1f, %.1f", __PRETTY_FUNCTION__,
tabViewSize.width, tabViewSize.height);
#endif
// desired size of window content
winSize = tabViewSize;
if([TABVIEW numberOfTabViewItems] == 1 && [[PreferencePanel sharedInstance] hideTab])
{
[tabBarControl setHidden: YES];
aRect.origin.x = 0;
aRect.origin.y = [[PreferencePanel sharedInstance] useBorder] ? VMARGIN : 0;
aRect.size = tabViewSize;
[TABVIEW setFrame: aRect];
if ([[PreferencePanel sharedInstance] useBorder]) {
winSize.height += VMARGIN;
vmargin_added = YES;
}
}
else
{
[tabBarControl setHidden: NO];
[tabBarControl setTabLocation: [[PreferencePanel sharedInstance] tabViewType]];
winSize.height += [tabBarControl frame].size.height;
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_TopTab) {
aRect.origin.x = 0;
aRect.origin.y = [[PreferencePanel sharedInstance] useBorder] ? VMARGIN : 0;
aRect.size = tabViewSize;
[TABVIEW setFrame: aRect];
aRect.origin.y += aRect.size.height;
aRect.size.height = [tabBarControl frame].size.height;
[tabBarControl setFrame: aRect];
if ([[PreferencePanel sharedInstance] useBorder]) {
winSize.height += VMARGIN;
vmargin_added = YES;
}
}
else {
aRect.origin.x = 0;
aRect.origin.y = 0;
aRect.size.width = tabViewSize.width;
aRect.size.height = [tabBarControl frame].size.height;
[tabBarControl setFrame: aRect];
aRect.origin.y = [tabBarControl frame].size.height;
aRect.size.height = tabViewSize.height;
//[TABVIEW setAutoresizesSubviews: NO];
[TABVIEW setFrame: aRect];
//[TABVIEW setAutoresizesSubviews: YES];
}
}
// set the style of tabs to match window style
switch ([[PreferencePanel sharedInstance] windowStyle]) {
case 0:
[tabBarControl setStyleNamed:@"Metal"];
break;
case 1:
[tabBarControl setStyleNamed:@"Aqua"];
break;
case 2:
[tabBarControl setStyleNamed:@"Unified"];
break;
default:
[tabBarControl setStyleNamed:@"Adium"];
break;
}
[tabBarControl setDisableTabClose:[[PreferencePanel sharedInstance] useCompactLabel]];
[tabBarControl setCellMinWidth: [[PreferencePanel sharedInstance] useCompactLabel]?
[[PreferencePanel sharedInstance] minCompactTabWidth]:
[[PreferencePanel sharedInstance] minTabWidth]];
[tabBarControl setSizeCellsToFit: [[PreferencePanel sharedInstance] useUnevenTabs]];
[tabBarControl setCellOptimumWidth: [[PreferencePanel sharedInstance] optimumTabWidth]];
#if 0
NSLog(@"%s: window content size %.1f, %.1f", __PRETTY_FUNCTION__,
winSize.width, winSize.height);
#endif
}
else {
aRect = [thisWindow frame];
WIDTH = (int)((aRect.size.width - MARGIN * 2)/charWidth);
HEIGHT = (int)((aRect.size.height)/charHeight);
aRect = NSMakeRect(floor((aRect.size.width-WIDTH*charWidth-MARGIN*2)/2),floor((aRect.size.height-charHeight*HEIGHT)/2),WIDTH*charWidth+MARGIN*2, charHeight*HEIGHT);
[TABVIEW setFrame: aRect];
/*[[thisWindow contentView] lockFocus];
[[NSColor blackColor] set];
NSRectFill([thisWindow frame]);
[[thisWindow contentView] unlockFocus];*/
}
int i, c;
for (i=0;i<[TABVIEW numberOfTabViewItems];i++)
{
PTYSession *aSession = [[TABVIEW tabViewItemAtIndex: i] identifier];
[aSession setObjectCount:i+1];
c = [[aSession SCREEN] changeSize];
[[aSession SCREEN] resizeWidth:WIDTH height:HEIGHT];
[[aSession SCREEN] setChangeSize:c];
[[aSession SHELL] setWidth:WIDTH height:HEIGHT];
[[aSession SCROLLVIEW] setLineScroll: [[aSession TEXTVIEW] lineHeight]];
[[aSession SCROLLVIEW] setPageScroll: 2*[[aSession TEXTVIEW] lineHeight]];
[[aSession SCROLLVIEW] setHasVerticalScroller:hasScrollbar];
if ([aSession backgroundImagePath]) [aSession setBackgroundImagePath:[aSession backgroundImagePath]];
}
if (!_fullScreen) {
// preserve the top left corner of the frame
aRect = [thisWindow frame];
topLeft.x = aRect.origin.x;
topLeft.y = aRect.origin.y + aRect.size.height;
[[thisWindow contentView] setAutoresizesSubviews: NO];
[thisWindow setContentSize:winSize];
[[thisWindow contentView] setAutoresizesSubviews: YES];
[thisWindow setFrameTopLeftPoint: topLeft];
if (vmargin_added) {
[[thisWindow contentView] lockFocus];
[[NSColor windowFrameColor] set];
NSRectFill(NSMakeRect(0,0,vsize.width,VMARGIN));
[[thisWindow contentView] unlockFocus];
}
}
_resizeInProgressFlag = NO;
}
[[[self currentSession] TEXTVIEW] setForceUpdate: YES];
[[[self currentSession] SCROLLVIEW] setNeedsDisplay: YES];
[tabBarControl update];
}
- (void)setWindowTitle
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal setWindowTitle]",
__FILE__, __LINE__);
#endif
NSString *title = [[self currentSession] windowTitle] ? [[self currentSession] windowTitle] : [self currentSessionName];
[self setWindowTitle: title];
}
- (void) setWindowTitle: (NSString *)title
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal setWindowTitle:%@]",
__FILE__, __LINE__, title);
#endif
NSString *temp = title ? title : @"Session";
[[self window] setTitle: [self sendInputToAllSessions] ? [NSString stringWithFormat:@">>%@<<", temp] : temp];
}
// increases or dcreases font size
- (void) changeFontSize: (BOOL) increase
{
float newFontSize;
float asciiFontSize = [[self font] pointSize];
if(increase == YES)
newFontSize = [self largerSizeForSize: asciiFontSize];
else
newFontSize = [self smallerSizeForSize: asciiFontSize];
NSFont *newAsciiFont = [NSFont fontWithName: [[self font] fontName] size: newFontSize];
float nonAsciiFontSize = [[self nafont] pointSize];
if(increase == YES)
newFontSize = [self largerSizeForSize: nonAsciiFontSize];
else
newFontSize = [self smallerSizeForSize: nonAsciiFontSize];
NSFont *newNonAsciiFont = [NSFont fontWithName: [[self nafont] fontName] size: newFontSize];
if(newAsciiFont != nil && newNonAsciiFont != nil)
{
[self setFont: newAsciiFont nafont: newNonAsciiFont];
// [self resizeWindow: [self width] height: [self height]];
NSRect frm = [[self window] frame];
float rh = frm.size.height - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.height;
float rw = frm.size.width - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.width;
HEIGHT=[self height]?[self height]:(([[[self window] screen] frame].size.height - rh)/charHeight + 0.5);
WIDTH=[self width]?[self width]:(([[[self window] screen] frame].size.width - rw - MARGIN*2)/charWidth + 0.5);
// resize the TABVIEW and TEXTVIEW
[self setWindowSize];
}
}
- (float) largerSizeForSize: (float) aSize
/*" Given a font size of aSize, return the next larger size. Uses the
same list of font sizes as presented in the font panel. "*/
{
if (aSize <= 8.0) return 9.0;
if (aSize <= 9.0) return 10.0;
if (aSize <= 10.0) return 11.0;
if (aSize <= 11.0) return 12.0;
if (aSize <= 12.0) return 13.0;
if (aSize <= 13.0) return 14.0;
if (aSize <= 14.0) return 18.0;
if (aSize <= 18.0) return 24.0;
if (aSize <= 24.0) return 36.0;
if (aSize <= 36.0) return 48.0;
if (aSize <= 48.0) return 64.0;
if (aSize <= 64.0) return 72.0;
if (aSize <= 72.0) return 96.0;
if (aSize <= 96.0) return 144.0;
// looks odd, but everything reasonable should have been covered above
return 288.0;
}
- (float) smallerSizeForSize: (float) aSize
/*" Given a font size of aSize, return the next smaller size. Uses
the same list of font sizes as presented in the font panel. "*/
{
if (aSize >= 288.0) return 144.0;
if (aSize >= 144.0) return 96.0;
if (aSize >= 96.0) return 72.0;
if (aSize >= 72.0) return 64.0;
if (aSize >= 64.0) return 48.0;
if (aSize >= 48.0) return 36.0;
if (aSize >= 36.0) return 24.0;
if (aSize >= 24.0) return 18.0;
if (aSize >= 18.0) return 14.0;
if (aSize >= 14.0) return 13.0;
if (aSize >= 13.0) return 12.0;
if (aSize >= 12.0) return 11.0;
if (aSize >= 11.0) return 10.0;
if (aSize >= 10.0) return 9.0;
// looks odd, but everything reasonable should have been covered above
return 8.0;
}
- (void) setCharacterSpacingHorizontal: (float) horizontal vertical: (float) vertical
{
charHorizontalSpacingMultiplier = horizontal;
charVerticalSpacingMultiplier = vertical;
[self setCharSizeUsingFont: FONT];
}
- (BOOL) antiAlias
{
return (antiAlias);
}
- (void) setAntiAlias: (BOOL) bAntiAlias
{
PTYSession *aSession;
int i, cnt = [TABVIEW numberOfTabViewItems];
antiAlias = bAntiAlias;
for(i=0; i<cnt; i++)
{
aSession = [[TABVIEW tabViewItemAtIndex: i] identifier];
[[aSession TEXTVIEW] setAntiAlias: antiAlias];
}
[[[self currentSession] TEXTVIEW] setNeedsDisplay: YES];
}
- (BOOL) blur
{
return (blur);
}
- (void) setBlur: (BOOL) flag
{
blur = flag;
if (blur)
[self enableBlur];
else
[self disableBlur];
}
- (void) enableBlur
{
id window = [self window];
if (!_fullScreen && nil != window && [window respondsToSelector:@selector(enableBlur)])
[window enableBlur];
}
- (void) disableBlur
{
id window = [self window];
if (!_fullScreen && nil != window && [window respondsToSelector:@selector(disableBlur)])
[window disableBlur];
}
- (void)setFont:(NSFont *)font nafont:(NSFont *)nafont
{
int i;
[FONT autorelease];
[font retain];
FONT=font;
[NAFONT autorelease];
[nafont retain];
NAFONT=nafont;
[self setCharSizeUsingFont: FONT];
for(i=0;i<[TABVIEW numberOfTabViewItems]; i++)
{
PTYSession* session = [[TABVIEW tabViewItemAtIndex: i] identifier];
[[session TEXTVIEW] setFont:FONT nafont:NAFONT];
}
[[self window] setResizeIncrements: NSMakeSize(charWidth, charHeight)];
}
- (NSFont *) font
{
return FONT;
}
- (NSFont *) nafont
{
return NAFONT;
}
- (NSFont *) oldFont
{
return oldFont;
}
- (NSFont *) oldNAFont
{
return oldNAFont;
}
- (void)reset:(id)sender
{
[[[self currentSession] TERMINAL] reset];
}
- (BOOL) useTransparency
{
return useTransparency;
}
- (void) setUseTransparency: (BOOL) flag
{
if (_fullScreen) return;
useTransparency = flag;
[[self window] setAlphaValue:flag?0.9999:1];
int n = [TABVIEW numberOfTabViewItems];
int i;
for(i=0;i<n;i++) {
[[[[TABVIEW tabViewItemAtIndex:i] identifier] TEXTVIEW] setUseTransparency:flag];
}
}
- (void)clearBuffer:(id)sender
{
[[self currentSession] clearBuffer];
}
- (void)clearScrollbackBuffer:(id)sender
{
[[self currentSession] clearScrollbackBuffer];
}
- (IBAction)logStart:(id)sender
{
if (![[self currentSession] logging]) [[self currentSession] logStart];
// send a notification
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermSessionBecameKey" object: [self currentSession]];
}
- (IBAction)logStop:(id)sender
{
if ([[self currentSession] logging]) [[self currentSession] logStop];
// send a notification
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermSessionBecameKey" object: [self currentSession]];
}
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
BOOL logging = [[self currentSession] logging];
BOOL result = YES;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal validateMenuItem:%@]",
__FILE__, __LINE__, item );
#endif
if ([item action] == @selector(logStart:)) {
result = logging == YES ? NO:YES;
}
else if ([item action] == @selector(logStop:)) {
result = logging == NO ? NO:YES;
}
return result;
}
- (void) sendInputToAllSessions: (NSData *) data
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal sendDataToAllSessions:]",
__FILE__, __LINE__);
#endif
PTYSession *aSession;
int i;
int n = [TABVIEW numberOfTabViewItems];
for (i=0; i<n; i++)
{
aSession = [[TABVIEW tabViewItemAtIndex: i] identifier];
if (![aSession exited]) [[aSession SHELL] writeTask:data];
//[[aSession TEXTVIEW] deselect];
}
}
- (BOOL) sendInputToAllSessions
{
return (sendInputToAllSessions);
}
- (void) setSendInputToAllSessions: (BOOL) flag
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s", __PRETTY_FUNCTION__);
#endif
sendInputToAllSessions = flag;
if(flag)
sendInputToAllSessions = (NSRunAlertPanel(NSLocalizedStringFromTableInBundle(@"Warning!",@"iTerm", [NSBundle bundleForClass: [self class]], @"Warning"),
NSLocalizedStringFromTableInBundle(@"Keyboard input will be sent to all sessions in this terminal.",@"iTerm", [NSBundle bundleForClass: [self class]], @"Keyboard Input"),
NSLocalizedStringFromTableInBundle(@"OK",@"iTerm", [NSBundle bundleForClass: [self class]], @"Profile"),
NSLocalizedStringFromTableInBundle(@"Cancel",@"iTerm", [NSBundle bundleForClass: [self class]], @"Cancel"), nil) == NSAlertDefaultReturn);
}
- (IBAction) toggleInputToAllSessions: (id) sender
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal toggleInputToAllSessions:%@]",
__FILE__, __LINE__, sender);
#endif
[self setSendInputToAllSessions: ![self sendInputToAllSessions]];
// Post a notification to reload menus
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermWindowBecameKey" object: self userInfo: nil];
[self setWindowTitle];
}
- (void) setFontSizeFollowWindowResize: (BOOL) flag
{
fontSizeFollowWindowResize = flag;
}
- (IBAction) toggleFontSizeFollowWindowResize: (id) sender
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal toggleFontSizeFollowWindowResize:%@]",
__FILE__, __LINE__, sender);
#endif
fontSizeFollowWindowResize = !fontSizeFollowWindowResize;
// cause reloading of menus
[[iTermController sharedInstance] setCurrentTerminal: self];
}
- (BOOL) fontSizeFollowWindowResize
{
return (fontSizeFollowWindowResize);
}
// NSWindow delegate methods
- (void)windowDidDeminiaturize:(NSNotification *)aNotification
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowDidDeminiaturize:%@]",
__FILE__, __LINE__, aNotification);
#endif
[self setBlur: blur];
}
- (BOOL)windowShouldClose:(NSNotification *)aNotification
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowShouldClose:%@]",
__FILE__, __LINE__, aNotification);
#endif
if ([[PreferencePanel sharedInstance] promptOnClose] && (![[PreferencePanel sharedInstance] onlyWhenMoreTabs] || [TABVIEW numberOfTabViewItems] > 1))
return [self showCloseWindow];
else
return (YES);
}
- (void)windowWillClose:(NSNotification *)aNotification
{
int i;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowWillClose:%@]",
__FILE__, __LINE__, aNotification);
#endif
// tabBarControl is holding on to us, so we have to tell it to let go
[tabBarControl setDelegate: nil];
// Release our window postion
for (i = 0; i < CACHED_WINDOW_POSITIONS; i++)
{
if(windowPositions[i] == (unsigned int) self)
{
windowPositions[i] = 0;
break;
}
}
EXIT = YES;
[self disableBlur];
if (_fullScreen) [NSMenu setMenuBarVisible: YES];
[[iTermController sharedInstance] terminalWillClose: self];
}
- (void)windowWillMiniaturize:(NSNotification *)aNotification
{
[self disableBlur];
}
- (void)windowDidBecomeKey:(NSNotification *)aNotification
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowDidBecomeKey:%@]",
__FILE__, __LINE__, aNotification);
#endif
//[self selectSessionAtIndex: [self currentSessionIndex]];
[[iTermController sharedInstance] setCurrentTerminal: self];
if (_fullScreen) [self hideMenuBar];
// update the cursor
[[[self currentSession] TEXTVIEW] setNeedsDisplay: YES];
if ([[self currentSession] timerMode] != FAST_MODE) {
[[self currentSession] setTimerMode: FAST_MODE];
}
}
- (void) windowDidResignKey: (NSNotification *)aNotification
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowDidResignKey:%@]",
__FILE__, __LINE__, aNotification);
#endif
//[self windowDidResignMain: aNotification];
if (_fullScreen) {
/*NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
if ([[iTermBookmarkController sharedInstance] window] == keyWindow ||
[[ITConfigPanelController singleInstance] window] == keyWindow ||
[[PreferencePanel sharedInstance] window] == keyWindow ||
![[keyWindow screen] isEqual:[[self window] screen]])
[[[self currentSession] TEXTVIEW] setNeedsDisplay: YES];
else
if (!_resizeInProgressFlag) [self toggleFullScreen: nil]; */
[NSMenu setMenuBarVisible: YES];
}
else {
// update the cursor
[[[self currentSession] TEXTVIEW] setNeedsDisplay: YES];
}
}
- (void)windowDidResignMain:(NSNotification *)aNotification
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowDidResignMain:%@]",
__FILE__, __LINE__, aNotification);
#endif
// if (_fullScreen) [self toggleFullScreen: nil];
}
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowWillResize: proposedFrameSize width = %f; height = %f]",
__FILE__, __LINE__, proposedFrameSize.width, proposedFrameSize.height);
#endif
if (sender!=[self window]) {
NSLog(@"Aha!");
return proposedFrameSize;
}
float nch = [sender frame].size.height - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.height;
float wch = [sender frame].size.width - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.width;
if (fontSizeFollowWindowResize) {
//scale = defaultFrame.size.height / [sender frame].size.height;
float scale = (proposedFrameSize.height - nch) / HEIGHT / charHeight;
NSFont *font = [[NSFontManager sharedFontManager] convertFont:FONT toSize:(int)(([FONT pointSize] * scale))];
font = [self _getMaxFont:font height:proposedFrameSize.height - nch lines:HEIGHT];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSSize sz;
[dic setObject:font forKey:NSFontAttributeName];
sz = [@"W" sizeWithAttributes:dic];
proposedFrameSize.height = [font defaultLineHeightForFont] * charVerticalSpacingMultiplier * HEIGHT + nch;
proposedFrameSize.width = sz.width * charHorizontalSpacingMultiplier * WIDTH + wch + MARGIN * 2;
}
else {
int new_height = (proposedFrameSize.height - nch) / charHeight + 0.5;
int new_width = (proposedFrameSize.width - wch - MARGIN*2) / charWidth + 0.5;
if (new_height<2) new_height = 2;
if (new_width<20) new_width = 20;
proposedFrameSize.height = charHeight * new_height + nch;
proposedFrameSize.width = charWidth * new_width + wch + MARGIN * 2;
//NSLog(@"actual height: %f",proposedFrameSize.height);
}
return (proposedFrameSize);
}
- (void)windowDidResize:(NSNotification *)aNotification
{
NSRect frame;
int w, h;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowDidResize: width = %f, height = %f]",
__FILE__, __LINE__, [[self window] frame].size.width, [[self window] frame].size.height);
#endif
// int tabBarHeight = [tabBarControl isHidden] ? 0 : [tabBarControl frame].size.height;
frame = [[[self currentSession] SCROLLVIEW] documentVisibleRect];
/* if (frame.size.height + tabBarHeight > [[[self window] contentView] frame].size.height) {
frame.size.height = [[[self window] contentView] frame].size.height - tabBarHeight;
} */
#if 0
NSLog(@"scrollview content size %.1f, %.1f, %.1f, %.1f",
frame.origin.x, frame.origin.y,
frame.size.width, frame.size.height);
#endif
if (fontSizeFollowWindowResize) {
float scale = (frame.size.height) / HEIGHT / charHeight;
NSFont *font = [[NSFontManager sharedFontManager] convertFont:FONT toSize:(int)(([FONT pointSize] * scale))];
font = [self _getMaxFont:font height:frame.size.height lines:HEIGHT];
float height = [font defaultLineHeightForFont] * charVerticalSpacingMultiplier;
if (height != charHeight) {
//NSLog(@"Old size: %f\t proposed New size:%f\tWindow Height: %f",[FONT pointSize], [font pointSize],frame.size.height);
NSFont *nafont = [[NSFontManager sharedFontManager] convertFont:FONT toSize:(int)(([NAFONT pointSize] * scale))];
nafont = [self _getMaxFont:nafont height:frame.size.height lines:HEIGHT];
[self setFont:font nafont:nafont];
NSString *aTitle = [NSString stringWithFormat:@"%@ (%.0f)", [[self currentSession] name], [font pointSize]];
[self setWindowTitle: aTitle];
}
WIDTH = (int)((frame.size.width - MARGIN * 2)/charWidth + 0.5);
HEIGHT = (int)((frame.size.height)/charHeight + 0.5);
[self setWindowSize];
}
else {
w = (int)((frame.size.width - MARGIN * 2)/charWidth);
h = (int)((frame.size.height)/charHeight);
if (w<20) w=20;
if (h<2) h=2;
if (w!=WIDTH || h!=HEIGHT) {
WIDTH = w;
HEIGHT = h;
// Display the new size in the window title.
NSString *aTitle = [NSString stringWithFormat:@"%@ (%d,%d)", [[self currentSession] name], WIDTH, HEIGHT];
[self setWindowTitle: aTitle];
[self setWindowSize];
}
}
// Post a notification
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermWindowDidResize" object: self userInfo: nil];
}
// PTYWindowDelegateProtocol
- (void) windowWillToggleToolbarVisibility: (id) sender
{
}
- (void) windowDidToggleToolbarVisibility: (id) sender
{
}
// Bookmarks
- (IBAction) toggleFullScreen: (id) sender
{
if (!_fullScreen) {
PseudoTerminal *fullScreenTerminal = [[PseudoTerminal alloc] initWithFullScreenWindowNibName:@"PseudoTerminal"];
if (fullScreenTerminal) {
PTYSession *currentSession = [self currentSession];
[fullScreenTerminal initWindowWithSettingsFrom: self];
[[[fullScreenTerminal window] contentView] lockFocus];
[[NSColor blackColor] set];
NSRectFill([[fullScreenTerminal window] frame]);
[[[fullScreenTerminal window] contentView] unlockFocus];
[[iTermController sharedInstance] addInTerminals: fullScreenTerminal];
[fullScreenTerminal release];
int n = [TABVIEW numberOfTabViewItems];
int i;
NSTabViewItem *aTabViewItem;
PTYSession *aSession;
fullScreenTerminal->_resizeInProgressFlag = YES;
for(i=0;i<n;i++) {
aTabViewItem = [[TABVIEW tabViewItemAtIndex:0] retain];
aSession = [aTabViewItem identifier];
// remove from our window
[TABVIEW removeTabViewItem: aTabViewItem];
// add the session to the new terminal
[fullScreenTerminal insertSession: aSession atIndex: i];
[[aSession TEXTVIEW] setFont:[fullScreenTerminal font] nafont:[fullScreenTerminal nafont]];
[[aSession TEXTVIEW] setCharWidth: [fullScreenTerminal charWidth]];
[[aSession TEXTVIEW] setLineHeight: [fullScreenTerminal charHeight]];
[[aSession TEXTVIEW] setLineWidth: [fullScreenTerminal width] * [fullScreenTerminal charWidth]];
[[aSession TEXTVIEW] setUseTransparency: NO];
// release the tabViewItem
[aTabViewItem release];
}
fullScreenTerminal->_resizeInProgressFlag = NO;
[[fullScreenTerminal tabView] selectTabViewItemWithIdentifier:currentSession];
[fullScreenTerminal setWindowSize];
[fullScreenTerminal setWindowTitle];
[[self window] close];
}
}
else
{
PseudoTerminal *normalScreenTerminal = [[PseudoTerminal alloc] initWithWindowNibName: @"PseudoTerminal"];
if ([[[PreferencePanel sharedInstance] window] isVisible]) [NSMenu setMenuBarVisible: YES];
if (normalScreenTerminal) {
PTYSession *currentSession = [self currentSession];
[normalScreenTerminal initWindowWithSettingsFrom: self];
[[iTermController sharedInstance] addInTerminals: normalScreenTerminal];
[normalScreenTerminal release];
int n = [TABVIEW numberOfTabViewItems];
int i;
NSTabViewItem *aTabViewItem;
PTYSession *aSession;
normalScreenTerminal->_resizeInProgressFlag = YES;
_resizeInProgressFlag = YES;
for(i=0;i<n;i++) {
aTabViewItem = [[TABVIEW tabViewItemAtIndex:0] retain];
aSession = [aTabViewItem identifier];
// remove from our window
[TABVIEW removeTabViewItem: aTabViewItem];
// add the session to the new terminal
[normalScreenTerminal insertSession: aSession atIndex: i];
[[aSession TEXTVIEW] setFont:[normalScreenTerminal font] nafont:[normalScreenTerminal nafont]];
[[aSession TEXTVIEW] setCharWidth: [normalScreenTerminal charWidth]];
[[aSession TEXTVIEW] setLineHeight: [normalScreenTerminal charHeight]];
[[aSession TEXTVIEW] setLineWidth: [normalScreenTerminal width] * [normalScreenTerminal charWidth]];
[[aSession TEXTVIEW] setUseTransparency: [self useTransparency]];
// release the tabViewItem
[aTabViewItem release];
}
normalScreenTerminal->_resizeInProgressFlag = NO;
[normalScreenTerminal setWindowSize];
[[normalScreenTerminal tabView] selectTabViewItemWithIdentifier:currentSession];
[[self window] close];
}
}
}
- (BOOL) fullScreen
{
return _fullScreen;
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal windowWillUseStandardFrame: defaultFramewidth = %f, height = %f]",
__FILE__, __LINE__, defaultFrame.size.width, defaultFrame.size.height);
#endif
float scale;
float nch = [sender frame].size.height - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.height;
float wch = [sender frame].size.width - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.width;
defaultFrame.origin.x = [sender frame].origin.x;
if (fontSizeFollowWindowResize) {
scale = (defaultFrame.size.height - nch) / HEIGHT / charHeight;
NSFont *font = [[NSFontManager sharedFontManager] convertFont:FONT toSize:(int)(([FONT pointSize] * scale))];
font = [self _getMaxFont:font height:defaultFrame.size.height - nch lines:HEIGHT];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSSize sz;
[dic setObject:font forKey:NSFontAttributeName];
sz = [@"W" sizeWithAttributes:dic];
defaultFrame.size.height = [font defaultLineHeightForFont] * charVerticalSpacingMultiplier * HEIGHT + nch;
defaultFrame.size.width = sz.width * charHorizontalSpacingMultiplier * WIDTH + MARGIN*2 + wch;
defaultFrame.origin.y = [sender frame].origin.y + [sender frame].size.height - defaultFrame.size.height;
// NSLog(@"actual height: %f\t (nch=%f) scale: %f\t new font:%f\told:%f",defaultFrame.size.height,nch,scale, [font pointSize], [FONT pointSize]);
}
else {
int new_height = (defaultFrame.size.height - nch) / charHeight;
int new_width = (defaultFrame.size.width - wch - MARGIN * 2) /charWidth;
defaultFrame.size.height = charHeight * new_height + nch;
defaultFrame.size.width = ([[PreferencePanel sharedInstance] maxVertically] ? [sender frame].size.width : new_width*charWidth+wch+MARGIN*2);
//NSLog(@"actual width: %f, height: %f",defaultFrame.size.width,defaultFrame.size.height);
}
return defaultFrame;
}
// Close Window
- (BOOL)showCloseWindow
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal showCloseWindow]", __FILE__, __LINE__);
#endif
return (NSRunAlertPanel(NSLocalizedStringFromTableInBundle(@"Close Window?",@"iTerm", [NSBundle bundleForClass: [self class]], @"Close window"),
NSLocalizedStringFromTableInBundle(@"All sessions will be closed",@"iTerm", [NSBundle bundleForClass: [self class]], @"Close window"),
NSLocalizedStringFromTableInBundle(@"OK",@"iTerm", [NSBundle bundleForClass: [self class]], @"OK"),
NSLocalizedStringFromTableInBundle(@"Cancel",@"iTerm", [NSBundle bundleForClass: [self class]], @"Cancel")
,nil)==NSAlertDefaultReturn);
}
- (IBAction)showConfigWindow:(id)sender;
{
if ([ITConfigPanelController onScreen])
[ITConfigPanelController close];
else
[ITConfigPanelController show];
}
- (void) resizeWindow:(int) w height:(int)h
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal resizeWindow:%d,%d]",
__FILE__, __LINE__, w, h);
#endif
// ignore resize request when we are in full screen mode.
if (_fullScreen) return;
NSRect frm = [[self window] frame];
float rh = frm.size.height - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.height;
float rw = frm.size.width - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.width;
HEIGHT=h?h:(([[[self window] screen] frame].size.height - rh)/charHeight + 0.5);
WIDTH=w?w:(([[[self window] screen] frame].size.width - rw - MARGIN*2)/charWidth + 0.5);
// resize the TABVIEW and TEXTVIEW
[self setWindowSize];
}
// Resize the window so that the text display area has pixel size of w*h
- (void) resizeWindowToPixelsWidth:(int)w height:(int)h
{
// ignore resize request when we are in full screen mode.
if (_fullScreen) return;
NSRect frm = [[self window] frame];
float rh = frm.size.height - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.height;
float rw = frm.size.width - [[[self currentSession] SCROLLVIEW] documentVisibleRect].size.width;
frm.origin.y += frm.size.height;
if (!h) h= [[[self window] screen] frame].size.height - rh;
int n = (h) / charHeight + 0.5;
frm.size.height = n*charHeight + rh;
if (!w) w= [[[self window] screen] frame].size.width - rw;
n = (w - MARGIN*2) / charWidth + 0.5;
frm.size.width = n*charWidth + rw + MARGIN*2;
frm.origin.y -= frm.size.height; //keep the top left point the same
[[self window] setFrame:frm display:NO];
[self windowDidResize:nil];
}
// Contextual menu
- (BOOL) suppressContextualMenu
{
return (suppressContextualMenu);
}
- (void) setSuppressContextualMenu: (BOOL) aBool
{
suppressContextualMenu = aBool;
}
- (void) menuForEvent:(NSEvent *)theEvent menu: (NSMenu *) theMenu
{
unsigned int modflag = 0;
int nextIndex;
NSMenuItem *aMenuItem;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal menuForEvent]", __FILE__, __LINE__);
#endif
if(theMenu == nil || suppressContextualMenu)
return;
modflag = [theEvent modifierFlags];
// Bookmarks
[theMenu insertItemWithTitle: NSLocalizedStringFromTableInBundle(@"New",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context menu") action:nil keyEquivalent:@"" atIndex: 0];
nextIndex = 1;
// Create a menu with a submenu to navigate between tabs if there are more than one
if([TABVIEW numberOfTabViewItems] > 1)
{
[theMenu insertItemWithTitle: NSLocalizedStringFromTableInBundle(@"Select",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context menu") action:nil keyEquivalent:@"" atIndex: nextIndex];
NSMenu *tabMenu = [[NSMenu alloc] initWithTitle:@""];
int i;
for (i = 0; i < [TABVIEW numberOfTabViewItems]; i++)
{
aMenuItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"%@ #%d", [[TABVIEW tabViewItemAtIndex: i] label], i+1]
action:@selector(selectTab:) keyEquivalent:@""];
[aMenuItem setRepresentedObject: [[TABVIEW tabViewItemAtIndex: i] identifier]];
[aMenuItem setTarget: TABVIEW];
[tabMenu addItem: aMenuItem];
[aMenuItem release];
}
[theMenu setSubmenu: tabMenu forItem: [theMenu itemAtIndex: nextIndex]];
[tabMenu release];
nextIndex++;
}
// Bookmarks
[theMenu insertItemWithTitle:
NSLocalizedStringFromTableInBundle(@"Bookmarks",@"iTerm", [NSBundle bundleForClass: [self class]], @"Bookmarks")
action:@selector(toggleBookmarksView:) keyEquivalent:@"" atIndex: nextIndex++];
// Separator
[theMenu insertItem:[NSMenuItem separatorItem] atIndex: nextIndex];
// Build the bookmarks menu
NSMenu *aMenu = [[[NSMenu alloc] init] autorelease];
[[iTermController sharedInstance] alternativeMenu: aMenu
forNode: [[ITAddressBookMgr sharedInstance] rootNode]
target: self
withShortcuts: NO];
[aMenu addItem: [NSMenuItem separatorItem]];
NSMenuItem *tip = [[[NSMenuItem alloc] initWithTitle: NSLocalizedStringFromTableInBundle(@"Press Option for New Window",@"iTerm", [NSBundle bundleForClass: [self class]], @"Toolbar Item: New") action:@selector(xyz) keyEquivalent: @""] autorelease];
[tip setKeyEquivalentModifierMask: NSCommandKeyMask];
[aMenu addItem: tip];
tip = [[tip copy] autorelease];
[tip setTitle:NSLocalizedStringFromTableInBundle(@"Open In New Window",@"iTerm", [NSBundle bundleForClass: [self class]], @"Toolbar Item: New")];
[tip setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
[tip setAlternate:YES];
[aMenu addItem: tip];
[theMenu setSubmenu: aMenu forItem: [theMenu itemAtIndex: 0]];
// Separator
[theMenu addItem:[NSMenuItem separatorItem]];
// Info
aMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"Info...",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context menu") action:@selector(showConfigWindow:) keyEquivalent:@""];
[aMenuItem setTarget: self];
[theMenu addItem: aMenuItem];
[aMenuItem release];
// Separator
[theMenu addItem:[NSMenuItem separatorItem]];
// Close current session
aMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"Close",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context menu") action:@selector(closeCurrentSession:) keyEquivalent:@""];
[aMenuItem setTarget: self];
[theMenu addItem: aMenuItem];
[aMenuItem release];
}
// NSTabView
- (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabView: willSelectTabViewItem]", __FILE__, __LINE__);
#endif
if (![[self currentSession] exited]) {
[[self currentSession] resetStatus];
[[[tabView selectedTabViewItem] identifier] setTimerMode: SLOW_MODE];
}
}
- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabView: didSelectTabViewItem]", __FILE__, __LINE__);
#endif
[[tabViewItem identifier] resetStatus];
[[[tabViewItem identifier] SCREEN] setDirty];
[[[tabViewItem identifier] TEXTVIEW] setNeedsDisplay: YES];
[[tabViewItem identifier] setTimerMode: FAST_MODE];
if (_fullScreen) {
[[[self window] contentView] lockFocus];
[[NSColor blackColor] set];
NSRectFill([[self window] frame]);
[[[self window] contentView] unlockFocus];
}
else {
[[tabViewItem identifier] setLabelAttribute];
[self setWindowTitle];
}
[[self window] makeFirstResponder:[[tabViewItem identifier] TEXTVIEW]];
// Post notifications
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermSessionBecameKey" object: [tabViewItem identifier]];
}
- (void)tabView:(NSTabView *)tabView willRemoveTabViewItem:(NSTabViewItem *)tabViewItem
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabView: willRemoveTabViewItem]", __FILE__, __LINE__);
#endif
}
- (void)tabView:(NSTabView *)tabView willAddTabViewItem:(NSTabViewItem *)tabViewItem
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabView: willAddTabViewItem]", __FILE__, __LINE__);
#endif
[self tabView: tabView willInsertTabViewItem: tabViewItem atIndex: [tabView numberOfTabViewItems]];
}
- (void)tabView:(NSTabView *)tabView willInsertTabViewItem:(NSTabViewItem *)tabViewItem atIndex: (int) index
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabView: willInsertTabViewItem: atIndex: %d]", __FILE__, __LINE__, index);
#endif
[[tabViewItem identifier] setParent: self];
}
- (BOOL)tabView:(NSTabView*)tabView shouldCloseTabViewItem:(NSTabViewItem *)tabViewItem
{
PTYSession *aSession = [tabViewItem identifier];
return [aSession exited] ||
![[PreferencePanel sharedInstance] promptOnClose] || [[PreferencePanel sharedInstance] onlyWhenMoreTabs] ||
(NSRunAlertPanel([NSString stringWithFormat:@"%@ #%d", [aSession name], [aSession realObjectCount]],
NSLocalizedStringFromTableInBundle(@"This session will be closed.",@"iTerm", [NSBundle bundleForClass: [self class]], @"Close Session"),
NSLocalizedStringFromTableInBundle(@"OK",@"iTerm", [NSBundle bundleForClass: [self class]], @"OK"),
NSLocalizedStringFromTableInBundle(@"Cancel",@"iTerm", [NSBundle bundleForClass: [self class]], @"Cancel")
,nil) == NSAlertDefaultReturn);
}
- (BOOL)tabView:(NSTabView*)aTabView shouldDragTabViewItem:(NSTabViewItem *)tabViewItem fromTabBar:(PSMTabBarControl *)tabBarControl
{
return YES;
}
- (BOOL)tabView:(NSTabView*)aTabView shouldDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl
{
//NSLog(@"shouldDropTabViewItem: %@ inTabBar: %@", [tabViewItem label], tabBarControl);
return YES;
}
- (void)tabView:(NSTabView*)aTabView didDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)aTabBarControl
{
//NSLog(@"didDropTabViewItem: %@ inTabBar: %@", [tabViewItem label], aTabBarControl);
PTYSession *aSession = [tabViewItem identifier];
PseudoTerminal *term = [aTabBarControl delegate];
[[aSession SCREEN] resizeWidth:[term width] height:[term height]];
[[aSession SHELL] setWidth:[term width] height:[term height]];
[[aSession TEXTVIEW] setFont:[term font] nafont:[term nafont]];
[[aSession TEXTVIEW] setCharWidth: [term charWidth]];
[[aSession TEXTVIEW] setLineHeight: [term charHeight]];
[[aSession TEXTVIEW] setUseTransparency: [term useTransparency]];
[[aSession TEXTVIEW] setLineWidth: [term width] * [term charWidth]];
if ([[term tabView] numberOfTabViewItems] == 1) [term setWindowSize];
int i;
for (i=0;i<[aTabView numberOfTabViewItems];i++)
{
PTYSession *aSession = [[aTabView tabViewItemAtIndex: i] identifier];
[aSession setObjectCount:i+1];
}
}
- (void)tabView:(NSTabView *)aTabView closeWindowForLastTabViewItem:(NSTabViewItem *)tabViewItem
{
//NSLog(@"closeWindowForLastTabViewItem: %@", [tabViewItem label]);
[[self window] close];
}
- (NSImage *)tabView:(NSTabView *)aTabView imageForTabViewItem:(NSTabViewItem *)tabViewItem offset:(NSSize *)offset styleMask:(unsigned int *)styleMask
{
NSImage *viewImage;
if (tabViewItem == [aTabView selectedTabViewItem]) {
NSView *textview = [tabViewItem view];
NSRect tabFrame = [tabBarControl frame];
int tabHeight = tabFrame.size.height;
NSRect contentFrame, viewRect;
contentFrame = viewRect = [textview frame];
contentFrame.size.height += tabHeight;
// grabs whole tabview image
viewImage = [[[NSImage alloc] initWithSize:contentFrame.size] autorelease];
NSImage *tabViewImage = [[[NSImage alloc] init] autorelease];
[textview lockFocus];
NSBitmapImageRep *tabviewRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:viewRect] autorelease];
[tabViewImage addRepresentation:tabviewRep];
[textview unlockFocus];
[viewImage lockFocus];
//viewRect.origin.x += 10;
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_BottomTab) {
viewRect.origin.y += tabHeight;
}
[tabViewImage compositeToPoint:viewRect.origin operation:NSCompositeSourceOver];
[viewImage unlockFocus];
//draw over where the tab bar would usually be
[viewImage lockFocus];
[[NSColor windowBackgroundColor] set];
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_TopTab) {
tabFrame.origin.y += viewRect.size.height;
}
NSRectFill(tabFrame);
//draw the background flipped, which is actually the right way up
NSAffineTransform *transform = [NSAffineTransform transform];
[transform scaleXBy:1.0 yBy:-1.0];
[transform concat];
tabFrame.origin.y = -tabFrame.origin.y - tabFrame.size.height;
[(id <PSMTabStyle>)[[aTabView delegate] style] drawBackgroundInRect:tabFrame];
[transform invert];
[transform concat];
[viewImage unlockFocus];
offset->width = [(id <PSMTabStyle>)[tabBarControl style] leftMarginForTabBarControl];
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_TopTab) {
offset->height = 22;
}
else {
offset->height = viewRect.size.height + 22;
}
*styleMask = NSBorderlessWindowMask;
}
else {
NSView *textview = [tabViewItem view];
NSRect tabFrame = [tabBarControl frame];
int tabHeight = tabFrame.size.height;
NSRect contentFrame, viewRect;
contentFrame = viewRect = [textview frame];
contentFrame.size.height += tabHeight;
// grabs whole tabview image
viewImage = [[[NSImage alloc] initWithSize:contentFrame.size] autorelease];
NSImage *textviewImage = [[[NSImage alloc] initWithSize:viewRect.size] autorelease];
[textviewImage setFlipped: YES];
[textviewImage lockFocus];
//draw the background flipped, which is actually the right way up
[[[tabViewItem identifier] TEXTVIEW] setForceUpdate: YES];
[[[tabViewItem identifier] TEXTVIEW] drawRect: viewRect];
[textviewImage unlockFocus];
[viewImage lockFocus];
//viewRect.origin.x += 10;
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_BottomTab) {
viewRect.origin.y += tabHeight;
}
[textviewImage compositeToPoint:viewRect.origin operation:NSCompositeSourceOver];
[viewImage unlockFocus];
//draw over where the tab bar would usually be
[viewImage lockFocus];
[[NSColor windowBackgroundColor] set];
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_TopTab) {
tabFrame.origin.y += viewRect.size.height;
}
NSRectFill(tabFrame);
//draw the background flipped, which is actually the right way up
NSAffineTransform *transform = [NSAffineTransform transform];
[transform scaleXBy:1.0 yBy:-1.0];
[transform concat];
tabFrame.origin.y = -tabFrame.origin.y - tabFrame.size.height;
[(id <PSMTabStyle>)[[aTabView delegate] style] drawBackgroundInRect:tabFrame];
[transform invert];
[transform concat];
[viewImage unlockFocus];
offset->width = [(id <PSMTabStyle>)[tabBarControl style] leftMarginForTabBarControl];
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_TopTab) {
offset->height = 22;
}
else {
offset->height = viewRect.size.height + 22;
}
*styleMask = NSBorderlessWindowMask;
}
return viewImage;
}
- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)tabView
{
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabViewDidChangeNumberOfTabViewItems]", __FILE__, __LINE__);
#endif
// check window size in case tabs have to be hidden or shown
if (([TABVIEW numberOfTabViewItems] == 1) || ([[PreferencePanel sharedInstance] hideTab] &&
([TABVIEW numberOfTabViewItems] > 1 && [tabBarControl isHidden])) )
{
[self setWindowSize];
}
int i;
for (i=0;i<[TABVIEW numberOfTabViewItems];i++)
{
PTYSession *aSession = [[TABVIEW tabViewItemAtIndex: i] identifier];
[aSession setObjectCount:i+1];
}
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermNumberOfSessionsDidChange" object: self userInfo: nil];
//[tabBarControl update];
}
- (NSMenu *)tabView:(NSTabView *)aTabView menuForTabViewItem:(NSTabViewItem *)tabViewItem
{
NSMenuItem *aMenuItem;
#if DEBUG_METHOD_TRACE
NSLog(@"%s(%d):-[PseudoTerminal tabViewContextualMenu]", __FILE__, __LINE__);
#endif
NSMenu *theMenu = [[[NSMenu alloc] init] autorelease];
// Create a menu with a submenu to navigate between tabs if there are more than one
if([TABVIEW numberOfTabViewItems] > 1)
{
int nextIndex = 0;
int i;
[theMenu insertItemWithTitle: NSLocalizedStringFromTableInBundle(@"Select",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context menu") action:nil keyEquivalent:@"" atIndex: nextIndex];
NSMenu *tabMenu = [[NSMenu alloc] initWithTitle:@""];
for (i = 0; i < [TABVIEW numberOfTabViewItems]; i++)
{
aMenuItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"%@ #%d", [[TABVIEW tabViewItemAtIndex: i] label], i+1]
action:@selector(selectTab:) keyEquivalent:@""];
[aMenuItem setRepresentedObject: [[TABVIEW tabViewItemAtIndex: i] identifier]];
[aMenuItem setTarget: TABVIEW];
[tabMenu addItem: aMenuItem];
[aMenuItem release];
}
[theMenu setSubmenu: tabMenu forItem: [theMenu itemAtIndex: nextIndex]];
[tabMenu release];
nextIndex++;
[theMenu addItem: [NSMenuItem separatorItem]];
}
// add tasks
aMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"Close Tab",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context Menu") action:@selector(closeTabContextualMenuAction:) keyEquivalent:@""];
[aMenuItem setRepresentedObject: tabViewItem];
[theMenu addItem: aMenuItem];
[aMenuItem release];
if([TABVIEW numberOfTabViewItems] > 1)
{
aMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"Move to new window",@"iTerm", [NSBundle bundleForClass: [self class]], @"Context Menu") action:@selector(moveTabToNewWindowContextualMenuAction:) keyEquivalent:@""];
[aMenuItem setRepresentedObject: tabViewItem];
[theMenu addItem: aMenuItem];
[aMenuItem release];
}
return theMenu;
}
- (PSMTabBarControl *)tabView:(NSTabView *)aTabView newTabBarForDraggedTabViewItem:(NSTabViewItem *)tabViewItem atPoint:(NSPoint)point
{
PseudoTerminal *term;
PTYSession *aSession = [tabViewItem identifier];
if(aSession == nil)
return nil;
// create a new terminal window
term = [[PseudoTerminal alloc] init];
if(term == nil)
return nil;
[term initWindowWithAddressbook: [aSession addressBookEntry]];
[[iTermController sharedInstance] addInTerminals: term];
[term release];
if ([[PreferencePanel sharedInstance] tabViewType] == PSMTab_TopTab) {
[[term window] setFrameTopLeftPoint:point];
}
else {
[[term window] setFrameOrigin:point];
}
return [term tabBarControl];
}
- (NSString *)tabView:(NSTabView *)aTabView toolTipForTabViewItem:(NSTabViewItem *)aTabViewItem
{
NSDictionary *ade = [[aTabViewItem identifier] addressBookEntry];
NSString *temp = [NSString stringWithFormat:NSLocalizedStringFromTableInBundle(@"Name: %@\nCommand: %@\nTerminal Profile: %@\nDisplay Profile: %@\nKeyboard Profile: %@",@"iTerm", [NSBundle bundleForClass: [self class]], @"Tab Tooltips"),
[ade objectForKey:KEY_NAME], [ade objectForKey:KEY_COMMAND], [ade objectForKey:KEY_TERMINAL_PROFILE],
[ade objectForKey:KEY_DISPLAY_PROFILE], [ade objectForKey:KEY_KEYBOARD_PROFILE]];
return temp;
}
- (void)tabView:(NSTabView *)tabView doubleClickTabViewItem:(NSTabViewItem *)tabViewItem
{
[tabView selectTabViewItem:tabViewItem];
[ITConfigPanelController show];
}
- (void)tabViewDoubleClickTabBar:(NSTabView *)tabView
{
[self addNewSession: [[ITAddressBookMgr sharedInstance] defaultBookmarkData]];
}
- (void) setLabelColor: (NSColor *) color forTabViewItem: tabViewItem
{
[tabBarControl setLabelColor: color forTabViewItem:tabViewItem];
}
- (PSMTabBarControl*) tabBarControl
{
return tabBarControl;
}
- (PTYTabView *) tabView
{
return TABVIEW;
}
// closes a tab
- (void) closeTabContextualMenuAction: (id) sender
{
[self closeSession: [[sender representedObject] identifier]];
}
- (void) closeTabWithIdentifier: (id) identifier
{
[self closeSession: identifier];
}
// moves a tab with its session to a new window
- (void) moveTabToNewWindowContextualMenuAction: (id) sender
{
PseudoTerminal *term;
NSTabViewItem *aTabViewItem = [sender representedObject];
PTYSession *aSession = [aTabViewItem identifier];
if(aSession == nil)
return;
// create a new terminal window
term = [[PseudoTerminal alloc] init];
if(term == nil)
return;
[term initWindowWithAddressbook: [aSession addressBookEntry]];
[[iTermController sharedInstance] addInTerminals: term];
[term release];
// temporarily retain the tabViewItem
[aTabViewItem retain];
// remove from our window
[TABVIEW removeTabViewItem: aTabViewItem];
// add the session to the new terminal
[term insertSession: aSession atIndex: 0];
[[aSession SCREEN] resizeWidth:[term width] height:[term height]];
[[aSession SHELL] setWidth:[term width] height:[term height]];
[[aSession TEXTVIEW] setFont:[term font] nafont:[term nafont]];
[[aSession TEXTVIEW] setCharWidth: [term charWidth]];
[[aSession TEXTVIEW] setLineHeight: [term charHeight]];
[[aSession TEXTVIEW] setLineWidth: [term width] * [term charWidth]];
[term setWindowSize];
// release the tabViewItem
[aTabViewItem release];
}
- (IBAction)closeWindow:(id)sender
{
[[self window] performClose:sender];
}
- (IBAction)sendCommand:(id)sender
{
NSString *command = [commandField stringValue];
if (command == nil || [[command stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""])
return;
NSRange range = [command rangeOfString:@"://"];
if (range.location != NSNotFound) {
range = [[command substringToIndex:range.location] rangeOfString:@" "];
if (range.location == NSNotFound) {
NSURL *url = [NSURL URLWithString: command];
NSString *urlType = [url scheme];
id bm = [[PreferencePanel sharedInstance] handlerBookmarkForURL: urlType];
//NSLog(@"Got the URL:%@\n%@", urlType, bm);
if (bm) [[iTermController sharedInstance] launchBookmark:[bm nodeData] inTerminal:[[iTermController sharedInstance] currentTerminal] withURL:command];
else [[NSWorkspace sharedWorkspace] openURL:url];
return;
}
}
[[self currentSession] sendCommand: command];
[commandField setStringValue:@""];
}
- (void) updateCurrentSessionProfiles
{
iTermDisplayProfileMgr *displayProfileMgr;
NSDictionary *aDict;
NSString *displayProfile;
PTYSession *current;
current = [self currentSession];
displayProfileMgr = [iTermDisplayProfileMgr singleInstance];
aDict = [current addressBookEntry];
displayProfile = [aDict objectForKey: KEY_DISPLAY_PROFILE];
if(displayProfile == nil)
displayProfile = [displayProfileMgr defaultProfileName];
[displayProfileMgr setTransparency: [current transparency] forProfile: displayProfile];
[displayProfileMgr setDisableBold: [current disableBold] forProfile: displayProfile];
[displayProfileMgr setBackgroundImage: [current backgroundImagePath] forProfile: displayProfile];
[displayProfileMgr setWindowColumns: [self columns] forProfile: displayProfile];
[displayProfileMgr setWindowRows: [self rows] forProfile: displayProfile];
[displayProfileMgr setWindowFont: [self font] forProfile: displayProfile];
[displayProfileMgr setWindowNAFont: [self nafont] forProfile: displayProfile];
[displayProfileMgr setWindowHorizontalCharSpacing: charHorizontalSpacingMultiplier forProfile: displayProfile];
[displayProfileMgr setWindowVerticalCharSpacing: charVerticalSpacingMultiplier forProfile: displayProfile];
[displayProfileMgr setWindowBlur: [self blur] forProfile: displayProfile];
[displayProfileMgr setWindowAntiAlias: [[current TEXTVIEW] antiAlias] forProfile: displayProfile];
[displayProfileMgr setColor: [current foregroundColor] forType: TYPE_FOREGROUND_COLOR forProfile: displayProfile];
[displayProfileMgr setColor: [current backgroundColor] forType: TYPE_BACKGROUND_COLOR forProfile: displayProfile];
[displayProfileMgr setColor: [current boldColor] forType: TYPE_BOLD_COLOR forProfile: displayProfile];
[displayProfileMgr setColor: [current selectionColor] forType: TYPE_SELECTION_COLOR forProfile: displayProfile];
[displayProfileMgr setColor: [current selectedTextColor] forType: TYPE_SELECTED_TEXT_COLOR forProfile: displayProfile];
[displayProfileMgr setColor: [current cursorColor] forType: TYPE_CURSOR_COLOR forProfile: displayProfile];
[displayProfileMgr setColor: [current cursorTextColor] forType: TYPE_CURSOR_TEXT_COLOR forProfile: displayProfile];
iTermTerminalProfileMgr *terminalProfileMgr;
NSString *terminalProfile;
terminalProfileMgr = [iTermTerminalProfileMgr singleInstance];
aDict = [current addressBookEntry];
terminalProfile = [aDict objectForKey: KEY_TERMINAL_PROFILE];
if(terminalProfile == nil)
terminalProfile = [terminalProfileMgr defaultProfileName];
[terminalProfileMgr setEncoding: [current encoding] forProfile: terminalProfile];
[terminalProfileMgr setSendIdleChar: [current antiIdle] forProfile: terminalProfile];
[terminalProfileMgr setIdleChar: [current antiCode] forProfile: terminalProfile];
id prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject: [[iTermDisplayProfileMgr singleInstance] profiles] forKey: @"Displays"];
[prefs setObject: [[iTermTerminalProfileMgr singleInstance] profiles] forKey: @"Terminals"];
[prefs synchronize];
NSRunInformationalAlertPanel(
[NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"%@'s display profile %@ and terminal profile %@ have been updated",@"iTerm", [NSBundle bundleForClass: [self class]], @"Profile"),
[[current addressBookEntry] objectForKey: @"Name"], displayProfile, terminalProfile],
NSLocalizedStringFromTableInBundle(@"All bookmarks associated with these profiles are affected",@"iTerm", [NSBundle bundleForClass: [self class]], @"Profile"),
NSLocalizedStringFromTableInBundle(@"OK",@"iTerm", [NSBundle bundleForClass: [self class]], @"Profile"), nil, nil);
}
// NSOutlineView delegate methods
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn
item:(id)item
{
return (NO);
}
// NSOutlineView doubleclick action
- (IBAction) doubleClickedOnBookmarksView: (id) sender
{
int selectedRow = [bookmarksView selectedRow];
TreeNode *selectedItem;
if(selectedRow < 0)
return;
selectedItem = [bookmarksView itemAtRow: selectedRow];
if(selectedItem != nil && [selectedItem isLeaf])
{
[[iTermController sharedInstance] launchBookmark: [selectedItem nodeData] inTerminal: self];
}
}
// Bookmarks
- (IBAction) toggleBookmarksView: (id) sender
{
if (_fullScreen) return;
[[(PTYWindow *)[self window] drawer] toggle: sender];
// Post a notification
[[NSNotificationCenter defaultCenter] postNotificationName: @"iTermWindowBecameKey" object: self userInfo: nil];
}
- (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize
{
// save the width to preferences
[[NSUserDefaults standardUserDefaults] setFloat: contentSize.width forKey: @"BookmarksDrawerWidth"];
return (contentSize);
}
- (IBAction) parameterPanelEnd: (id) sender
{
[NSApp stopModal];
}
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
{
int move = [[[aNotification userInfo] objectForKey:@"NSTextMovement"] intValue];
switch (move) {
case 16: // Return key
[self sendCommand: nil];
break;
case 17: // Tab key
[self addNewSession: [[ITAddressBookMgr sharedInstance] defaultBookmarkData] withCommand: [commandField stringValue]];
break;
default:
break;
}
}
@end
@implementation PseudoTerminal (Private)
- (void) _commonInit
{
charHorizontalSpacingMultiplier = charVerticalSpacingMultiplier = 1.0;
[self setUseTransparency: YES];
}
- (NSFont *) _getMaxFont:(NSFont* ) font
height:(float) height
lines:(float) lines
{
float newSize = [font pointSize], newHeight;
NSFont *newfont=nil;
do {
newfont = font;
font = [[NSFontManager sharedFontManager] convertFont:font toSize:newSize];
newSize++;
newHeight = [font defaultLineHeightForFont] * charVerticalSpacingMultiplier * lines;
} while (height >= newHeight);
return newfont;
}
- (void) _reloadAddressBook: (NSNotification *) aNotification
{
[bookmarksView reloadData];
}
- (void) _refreshTerminal: (NSNotification *) aNotification
{
[self setWindowSize];
}
- (NSString *) _getSessionParameters: (NSString *) command
{
NSMutableString *completeCommand = [[NSMutableString alloc] initWithString:command];
NSRange r1, r2, currentRange;
while (1)
{
currentRange = NSMakeRange(0,[completeCommand length]);
r1 = [completeCommand rangeOfString:@"$$" options:NSLiteralSearch range:currentRange];
if (r1.location == NSNotFound) break;
currentRange.location = r1.location + 2;
currentRange.length -= r1.location + 2;
r2 = [completeCommand rangeOfString:@"$$" options:NSLiteralSearch range:currentRange];
if (r2.location == NSNotFound) break;
[parameterName setStringValue: [completeCommand substringWithRange:NSMakeRange(r1.location+2, r2.location - r1.location-2)]];
[parameterValue setStringValue:@""];
[NSApp beginSheet: parameterPanel
modalForWindow: [self window]
modalDelegate: self
didEndSelector: nil
contextInfo: nil];
[NSApp runModalForWindow:parameterPanel];
[NSApp endSheet:parameterPanel];
[parameterPanel orderOut:self];
[completeCommand replaceOccurrencesOfString:[completeCommand substringWithRange:NSMakeRange(r1.location, r2.location - r1.location+2)] withString:[parameterValue stringValue] options:NSLiteralSearch range:NSMakeRange(0,[completeCommand length])];
}
return completeCommand;
}
- (void) hideMenuBar
{
NSScreen* menubarScreen = nil;
NSScreen* currentScreen = nil;
if([[NSScreen screens] count] == 0)
return;
menubarScreen = [[NSScreen screens] objectAtIndex:0];
currentScreen = [NSScreen mainScreen];
if(currentScreen == menubarScreen)
[NSMenu setMenuBarVisible: NO];
}
@end
@implementation PseudoTerminal (KeyValueCoding)
// accessors for attributes:
-(int)columns
{
// NSLog(@"PseudoTerminal: -columns");
return (WIDTH);
}
-(void)setColumns: (int)columns
{
// NSLog(@"PseudoTerminal: setColumns: %d", columns);
if(columns > 0)
{
WIDTH = columns;
if([TABVIEW numberOfTabViewItems] > 0) {
[self setWindowSize];
}
}
}
-(int)rows
{
// NSLog(@"PseudoTerminal: -rows");
return (HEIGHT);
}
-(void)setRows: (int)rows
{
// NSLog(@"PseudoTerminal: setRows: %d", rows);
if(rows > 0)
{
HEIGHT = rows;
if([TABVIEW numberOfTabViewItems] > 0) {
[self setWindowSize];
}
}
}
// accessors for to-many relationships:
// (See NSScriptKeyValueCoding.h)
-(id)valueInSessionsAtIndex:(unsigned)index
{
// NSLog(@"PseudoTerminal: -valueInSessionsAtIndex: %d", index);
return ([[TABVIEW tabViewItemAtIndex:index] identifier]);
}
-(NSArray*)sessions
{
int n = [TABVIEW numberOfTabViewItems];
NSMutableArray *sessions = [NSMutableArray arrayWithCapacity: n];
int i;
for (i= 0; i < n; i++)
{
[sessions addObject: [[TABVIEW tabViewItemAtIndex:i] identifier]];
}
return sessions;
}
-(void)setSessions: (NSArray*)sessions {}
-(id)valueWithName: (NSString *)uniqueName inPropertyWithKey: (NSString*)propertyKey
{
id result = nil;
int i;
if([propertyKey isEqualToString: sessionsKey] == YES)
{
PTYSession *aSession;
for (i= 0; i < [TABVIEW numberOfTabViewItems]; i++)
{
aSession = [[TABVIEW tabViewItemAtIndex:i] identifier];
if([[aSession name] isEqualToString: uniqueName] == YES)
return (aSession);
}
}
return result;
}
// The 'uniqueID' argument might be an NSString or an NSNumber.
-(id)valueWithID: (NSString *)uniqueID inPropertyWithKey: (NSString*)propertyKey
{
id result = nil;
int i;
if([propertyKey isEqualToString: sessionsKey] == YES)
{
PTYSession *aSession;
for (i= 0; i < [TABVIEW numberOfTabViewItems]; i++)
{
aSession = [[TABVIEW tabViewItemAtIndex:i] identifier];
if([[aSession tty] isEqualToString: uniqueID] == YES)
return (aSession);
}
}
return result;
}
-(void)addNewSession:(NSDictionary *) addressbookEntry
{
// NSLog(@"PseudoTerminal: -addInSessions: 0x%x", object);
PTYSession *aSession;
NSString *terminalProfile;
terminalProfile = [addressbookEntry objectForKey: KEY_TERMINAL_PROFILE];
if(terminalProfile == nil)
terminalProfile = [[iTermTerminalProfileMgr singleInstance] defaultProfileName];
// Initialize a new session
aSession = [[PTYSession alloc] init];
[[aSession SCREEN] setScrollback:[[iTermTerminalProfileMgr singleInstance] scrollbackLinesForProfile: [addressbookEntry objectForKey: KEY_TERMINAL_PROFILE]]];
// set our preferences
[aSession setAddressBookEntry: addressbookEntry];
// Add this session to our term and make it current
[self appendSession: aSession];
if ([aSession SCREEN]) {
NSString *cmd;
NSArray *arg;
NSString *pwd;
// Grab the addressbook command
cmd = [self _getSessionParameters: [addressbookEntry objectForKey: KEY_COMMAND]];
[PseudoTerminal breakDown:cmd cmdPath:&cmd cmdArgs:&arg];
pwd = [addressbookEntry objectForKey: KEY_WORKING_DIRECTORY];
if([pwd length] <= 0)
pwd = NSHomeDirectory();
NSDictionary *env=[NSDictionary dictionaryWithObject: pwd forKey:@"PWD"];
[self setCurrentSessionName:[addressbookEntry objectForKey: KEY_NAME]];
// Start the command
[self startProgram:cmd arguments:arg environment:env];
}
[aSession release];
}
-(void)addNewSession:(NSDictionary *) addressbookEntry withURL: (NSString *)url
{
// NSLog(@"PseudoTerminal: -addInSessions: 0x%x", object);
PTYSession *aSession;
NSString *terminalProfile;
terminalProfile = [addressbookEntry objectForKey: KEY_TERMINAL_PROFILE];
if(terminalProfile == nil)
terminalProfile = [[iTermTerminalProfileMgr singleInstance] defaultProfileName];
// Initialize a new session
aSession = [[PTYSession alloc] init];
[[aSession SCREEN] setScrollback:[[iTermTerminalProfileMgr singleInstance] scrollbackLinesForProfile: [addressbookEntry objectForKey: KEY_TERMINAL_PROFILE]]];
// set our preferences
[aSession setAddressBookEntry: addressbookEntry];
// Add this session to our term and make it current
[self appendSession: aSession];
if ([aSession SCREEN]) {
// We process the cmd to insert URL parts
NSMutableString *cmd = [[[NSMutableString alloc] initWithString:[addressbookEntry objectForKey: KEY_COMMAND]] autorelease];
NSURL *urlRep = [NSURL URLWithString: url];
// Grab the addressbook command
[cmd replaceOccurrencesOfString:@"$$URL$$" withString:url options:NSLiteralSearch range:NSMakeRange(0, [cmd length])];
[cmd replaceOccurrencesOfString:@"$$HOST$$" withString:[urlRep host]?[urlRep host]:@"" options:NSLiteralSearch range:NSMakeRange(0, [cmd length])];
[cmd replaceOccurrencesOfString:@"$$USER$$" withString:[urlRep user]?[urlRep user]:@"" options:NSLiteralSearch range:NSMakeRange(0, [cmd length])];
[cmd replaceOccurrencesOfString:@"$$PASSWORD$$" withString:[urlRep password]?[urlRep password]:@"" options:NSLiteralSearch range:NSMakeRange(0, [cmd length])];
[cmd replaceOccurrencesOfString:@"$$PORT$$" withString:[urlRep port]?[[urlRep port] stringValue]:@"" options:NSLiteralSearch range:NSMakeRange(0, [cmd length])];
[cmd replaceOccurrencesOfString:@"$$PATH$$" withString:[urlRep path]?[urlRep path]:@"" options:NSLiteralSearch range:NSMakeRange(0, [cmd length])];
NSArray *arg;
NSString *pwd;
[PseudoTerminal breakDown:cmd cmdPath:&cmd cmdArgs:&arg];
pwd = [addressbookEntry objectForKey: KEY_WORKING_DIRECTORY];
if([pwd length] <= 0)
pwd = NSHomeDirectory();
NSDictionary *env=[NSDictionary dictionaryWithObject: pwd forKey:@"PWD"];
[self setCurrentSessionName:[addressbookEntry objectForKey: KEY_NAME]];
// Start the command
[self startProgram:[self _getSessionParameters: cmd] arguments:arg environment:env];
}
[aSession release];
}
-(void)addNewSession:(NSDictionary *) addressbookEntry withCommand: (NSString *)command
{
// NSLog(@"PseudoTerminal: -addInSessions: 0x%x", object);
PTYSession *aSession;
NSString *terminalProfile;
terminalProfile = [addressbookEntry objectForKey: KEY_TERMINAL_PROFILE];
if(terminalProfile == nil)
terminalProfile = [[iTermTerminalProfileMgr singleInstance] defaultProfileName];
// Initialize a new session
aSession = [[PTYSession alloc] init];
[[aSession SCREEN] setScrollback:[[iTermTerminalProfileMgr singleInstance] scrollbackLinesForProfile: [addressbookEntry objectForKey: KEY_TERMINAL_PROFILE]]];
// set our preferences
[aSession setAddressBookEntry: addressbookEntry];
// Add this session to our term and make it current
[self appendSession: aSession];
if ([aSession SCREEN]) {
NSArray *arg;
NSString *pwd;
[PseudoTerminal breakDown:command cmdPath:&command cmdArgs:&arg];
pwd = [addressbookEntry objectForKey: KEY_WORKING_DIRECTORY];
if([pwd length] <= 0)
pwd = NSHomeDirectory();
NSDictionary *env=[NSDictionary dictionaryWithObject: pwd forKey:@"PWD"];
[self setCurrentSessionName:[addressbookEntry objectForKey: KEY_NAME]];
// Start the command
[self startProgram:[self _getSessionParameters: command] arguments:arg environment:env];
}
[aSession release];
}
-(void)appendSession:(PTYSession *)object
{
// NSLog(@"PseudoTerminal: -appendSession: 0x%x", object);
[self setupSession: object title: nil];
if ([object SCREEN]) // screen initialized ok
[self insertSession: object atIndex:[TABVIEW numberOfTabViewItems]];
else {
}
}
-(void)replaceInSessions:(PTYSession *)object atIndex:(unsigned)index
{
// NSLog(@"PseudoTerminal: -replaceInSessions: 0x%x atIndex: %d", object, index);
NSLog(@"Replace Sessions: not implemented.");
}
-(void)addInSessions:(PTYSession *)object
{
// NSLog(@"PseudoTerminal: -addInSessions: 0x%x", object);
[self insertInSessions: object];
}
-(void)insertInSessions:(PTYSession *)object
{
// NSLog(@"PseudoTerminal: -insertInSessions: 0x%x", object);
[self insertInSessions: object atIndex:[TABVIEW numberOfTabViewItems]];
}
-(void)insertInSessions:(PTYSession *)object atIndex:(unsigned)index
{
// NSLog(@"PseudoTerminal: -insertInSessions: 0x%x atIndex: %d", object, index);
[self setupSession: object title: nil];
if ([object SCREEN]) // screen initialized ok
[self insertSession: object atIndex: index];
else {
}
}
-(void)removeFromSessionsAtIndex:(unsigned)index
{
// NSLog(@"PseudoTerminal: -removeFromSessionsAtIndex: %d", index);
if(index < [TABVIEW numberOfTabViewItems])
{
PTYSession *aSession = [[TABVIEW tabViewItemAtIndex:index] identifier];
[self closeSession: aSession];
}
}
- (BOOL)windowInited
{
return (windowInited);
}
- (void) setWindowInited: (BOOL) flag
{
windowInited = flag;
}
// a class method to provide the keys for KVC:
+(NSArray*)kvcKeys
{
static NSArray *_kvcKeys = nil;
if( nil == _kvcKeys ){
_kvcKeys = [[NSArray alloc] initWithObjects:
columnsKey, rowsKey, sessionsKey, nil ];
}
return _kvcKeys;
}
@end
@implementation PseudoTerminal (ScriptingSupport)
// Object specifier
- (NSScriptObjectSpecifier *)objectSpecifier
{
unsigned index = 0;
id classDescription = nil;
NSScriptObjectSpecifier *containerRef;
NSArray *terminals = [[iTermController sharedInstance] terminals];
index = [terminals indexOfObjectIdenticalTo:self];
if (index != NSNotFound) {
containerRef = [NSApp objectSpecifier];
classDescription = [NSClassDescription classDescriptionForClass:[NSApp class]];
//create and return the specifier
return [[[NSIndexSpecifier allocWithZone:[self zone]]
initWithContainerClassDescription: classDescription
containerSpecifier: containerRef
key: @ "terminals"
index: index] autorelease];
}
else
return nil;
}
// Handlers for supported commands:
-(void)handleSelectScriptCommand: (NSScriptCommand *)command
{
[[iTermController sharedInstance] setCurrentTerminal: self];
}
-(void)handleLaunchScriptCommand: (NSScriptCommand *)command
{
// Get the command's arguments:
NSDictionary *args = [command evaluatedArguments];
NSString *session = [args objectForKey:@"session"];
NSDictionary *abEntry;
abEntry = [[ITAddressBookMgr sharedInstance] dataForBookmarkWithName: session];
if(abEntry == nil)
abEntry = [[ITAddressBookMgr sharedInstance] defaultBookmarkData];
// If we have not set up a window, do it now
if([self windowInited] == NO)
{
[self initWindowWithAddressbook:abEntry];
}
// launch the session!
[[iTermController sharedInstance] launchBookmark: abEntry inTerminal: self];
return;
}
@end