Beispiel #1
0
void
TermWindow::_NewTab()
{
	ActiveProcessInfo info;
	if (_ActiveTermView()->GetActiveProcessInfo(info))
		_AddTab(NULL, info.CurrentDirectory());
	else
		_AddTab(NULL);
}
Beispiel #2
0
void
TermView::HyperLinkState::Entered()
{
	ActiveProcessInfo activeProcessInfo;
	if (fView->GetActiveProcessInfo(activeProcessInfo))
		fCurrentDirectory = activeProcessInfo.CurrentDirectory();
	else
		fCurrentDirectory.Truncate(0);

	_UpdateHighlight();
}
Beispiel #3
0
void
TermWindow::_NewTab()
{
	if (fTabView->CountTabs() < kMaxTabs) {
		ActiveProcessInfo info;
		if (_ActiveTermView()->GetActiveProcessInfo(info))
			_AddTab(NULL, info.CurrentDirectory());
		else
			_AddTab(NULL);
	}
}
Beispiel #4
0
bool
Shell::GetActiveProcessInfo(ActiveProcessInfo& _info) const
{
	_info.Unset();

	// get the foreground process group
	pid_t process = tcgetpgrp(fFd);
	if (process < 0)
		return false;

	// get more info on the process group leader
	KMessage info;
	status_t error = get_extended_team_info(process, B_TEAM_INFO_BASIC, info);
	if (error != B_OK)
		return false;

	// fetch the name and the current directory from the info
	const char* name;
	int32 cwdDevice;
	int64 cwdDirectory;
	if (info.FindString("name", &name) != B_OK
		|| info.FindInt32("cwd device", &cwdDevice) != B_OK
		|| info.FindInt64("cwd directory", &cwdDirectory) != B_OK) {
		return false;
	}

	// convert the node ref into a path
	entry_ref cwdRef(cwdDevice, cwdDirectory, ".");
	BPath cwdPath;
	if (cwdPath.SetTo(&cwdRef) != B_OK)
		return false;

	// set the result
	_info.SetTo(process, name, cwdPath.Path());

	return true;
}
Beispiel #5
0
void
TermWindow::MessageReceived(BMessage *message)
{
	int32 encodingId;
	bool findresult;

	switch (message->what) {
		case B_COPY:
			_ActiveTermView()->Copy(be_clipboard);
			break;

		case B_PASTE:
			_ActiveTermView()->Paste(be_clipboard);
			break;

#ifdef USE_DEBUG_SNAPSHOTS
		case SHORTCUT_DEBUG_SNAPSHOTS:
			_ActiveTermView()->MakeDebugSnapshots();
			break;

		case SHORTCUT_DEBUG_CAPTURE:
			_ActiveTermView()->StartStopDebugCapture();
			break;
#endif

		case B_SELECT_ALL:
			_ActiveTermView()->SelectAll();
			break;

		case MENU_CLEAR_ALL:
			_ActiveTermView()->Clear();
			break;

		case MENU_SWITCH_TERM:
			_SwitchTerminal();
			break;

		case MENU_NEW_TERM:
		{
			// Set our current working directory to that of the active tab, so
			// that the new terminal and its shell inherit it.
			// Note: That's a bit lame. We should rather fork() and change the
			// CWD in the child, but since ATM there aren't any side effects of
			// changing our CWD, we save ourselves the trouble.
			ActiveProcessInfo activeProcessInfo;
			if (_ActiveTermView()->GetActiveProcessInfo(activeProcessInfo))
				chdir(activeProcessInfo.CurrentDirectory());

			app_info info;
			be_app->GetAppInfo(&info);

			// try launching two different ways to work around possible problems
			if (be_roster->Launch(&info.ref) != B_OK)
				be_roster->Launch(TERM_SIGNATURE);
			break;
		}

		case MENU_PREF_OPEN:
			if (!fPrefWindow) {
				fPrefWindow = new PrefWindow(this);
			} else
				fPrefWindow->Activate();
			break;

		case MSG_PREF_CLOSED:
			fPrefWindow = NULL;
			break;

		case MSG_WINDOW_TITLE_SETTING_CHANGED:
		case MSG_TAB_TITLE_SETTING_CHANGED:
			_TitleSettingsChanged();
			break;

		case MENU_FIND_STRING:
			if (fFindPanel == NULL) {
				fFindPanel = new FindWindow(this, fFindString, fFindSelection,
					fMatchWord, fMatchCase, fForwardSearch);

				fFindPanel->CenterIn(Frame());
				_MoveWindowInScreen(fFindPanel);
				fFindPanel->Show();
			} else
				fFindPanel->Activate();
			break;

		case MSG_FIND:
		{
			fFindPanel->PostMessage(B_QUIT_REQUESTED);
			message->FindBool("findselection", &fFindSelection);
			if (!fFindSelection)
				message->FindString("findstring", &fFindString);
			else
				_ActiveTermView()->GetSelection(fFindString);

			if (fFindString.Length() == 0) {
				const char* errorMsg = !fFindSelection
					? B_TRANSLATE("No search string was entered.")
					: B_TRANSLATE("Nothing is selected.");
				BAlert* alert = new BAlert(B_TRANSLATE("Find failed"),
					errorMsg, B_TRANSLATE("OK"), NULL, NULL,
					B_WIDTH_AS_USUAL, B_WARNING_ALERT);
				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);

				alert->Go();
				fFindPreviousMenuItem->SetEnabled(false);
				fFindNextMenuItem->SetEnabled(false);
				break;
			}

			message->FindBool("forwardsearch", &fForwardSearch);
			message->FindBool("matchcase", &fMatchCase);
			message->FindBool("matchword", &fMatchWord);
			findresult = _ActiveTermView()->Find(fFindString, fForwardSearch,
				fMatchCase, fMatchWord);

			if (!findresult) {
				BAlert* alert = new BAlert(B_TRANSLATE("Find failed"),
					B_TRANSLATE("Text not found."),
					B_TRANSLATE("OK"), NULL, NULL,
					B_WIDTH_AS_USUAL, B_WARNING_ALERT);
				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
				alert->Go();
				fFindPreviousMenuItem->SetEnabled(false);
				fFindNextMenuItem->SetEnabled(false);
				break;
			}

			// Enable the menu items Find Next and Find Previous
			fFindPreviousMenuItem->SetEnabled(true);
			fFindNextMenuItem->SetEnabled(true);
			break;
		}

		case MENU_FIND_NEXT:
		case MENU_FIND_PREVIOUS:
			findresult = _ActiveTermView()->Find(fFindString,
				(message->what == MENU_FIND_NEXT) == fForwardSearch,
				fMatchCase, fMatchWord);
			if (!findresult) {
				BAlert* alert = new BAlert(B_TRANSLATE("Find failed"),
					B_TRANSLATE("Not found."), B_TRANSLATE("OK"),
					NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
				alert->Go();
			}
			break;

		case MSG_FIND_CLOSED:
			fFindPanel = NULL;
			break;

		case MENU_ENCODING:
			if (message->FindInt32("op", &encodingId) == B_OK)
				_ActiveTermView()->SetEncoding(encodingId);
			break;

		case MSG_COLS_CHANGED:
		{
			int32 columns, rows;
			if (message->FindInt32("columns", &columns) != B_OK
				|| message->FindInt32("rows", &rows) != B_OK) {
				break;
			}

			for (int32 i = 0; i < fTabView->CountTabs(); i++) {
				TermView* view = _TermViewAt(i);
				view->SetTermSize(rows, columns, true);
				_ResizeView(view);
			}
			break;
		}

		case MSG_HALF_FONT_CHANGED:
		case MSG_FULL_FONT_CHANGED:
		{
			BFont font;
			_GetPreferredFont(font);
			for (int32 i = 0; i < fTabView->CountTabs(); i++) {
				TermView* view = _TermViewAt(i);
				view->SetTermFont(&font);
				_ResizeView(view);
			}
			break;
		}

		case MSG_HALF_SIZE_CHANGED:
		case MSG_FULL_SIZE_CHANGED:
		{
			const char* size = NULL;
			if (message->FindString("font_size", &size) != B_OK)
				break;

			// mark the font size menu item
			for (int32 i = 0; i < fFontSizeMenu->CountItems(); i++) {
				BMenuItem* item = fFontSizeMenu->ItemAt(i);
				if (item == NULL)
					continue;

				item->SetMarked(false);
				if (strcmp(item->Label(), size) == 0)
					item->SetMarked(true);
			}

			BFont font;
			_ActiveTermView()->GetTermFont(&font);
			font.SetSize(atoi(size));
			PrefHandler::Default()->setInt32(PREF_HALF_FONT_SIZE,
				(int32)atoi(size));
			for (int32 i = 0; i < fTabView->CountTabs(); i++) {
				TermView* view = _TermViewAt(i);
				_TermViewAt(i)->SetTermFont(&font);
				_ResizeView(view);
			}
			break;
		}

		case FULLSCREEN:
			if (!fSavedFrame.IsValid()) { // go fullscreen
				_ActiveTermView()->DisableResizeView();
				float mbHeight = fMenuBar->Bounds().Height() + 1;
				fSavedFrame = Frame();
				BScreen screen(this);

				for (int32 i = fTabView->CountTabs() - 1; i >= 0 ; i--)
					_TermViewAt(i)->ScrollBar()->ResizeBy(0,
						(B_H_SCROLL_BAR_HEIGHT - 1));

				fMenuBar->Hide();
				fTabView->ResizeBy(0, mbHeight);
				fTabView->MoveBy(0, -mbHeight);
				fSavedLook = Look();
				// done before ResizeTo to work around a Dano bug
				// (not erasing the decor)
				SetLook(B_NO_BORDER_WINDOW_LOOK);
				ResizeTo(screen.Frame().Width() + 1, screen.Frame().Height() + 1);
				MoveTo(screen.Frame().left, screen.Frame().top);
				SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE));
				fFullScreen = true;
			} else { // exit fullscreen
				_ActiveTermView()->DisableResizeView();
				float mbHeight = fMenuBar->Bounds().Height() + 1;
				fMenuBar->Show();

				for (int32 i = fTabView->CountTabs() - 1; i >= 0 ; i--)
					_TermViewAt(i)->ScrollBar()->ResizeBy(0,
						-(B_H_SCROLL_BAR_HEIGHT - 1));

				ResizeTo(fSavedFrame.Width(), fSavedFrame.Height());
				MoveTo(fSavedFrame.left, fSavedFrame.top);
				fTabView->ResizeBy(0, -mbHeight);
				fTabView->MoveBy(0, mbHeight);
				SetLook(fSavedLook);
				fSavedFrame = BRect(0, 0, -1, -1);
				SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
				fFullScreen = false;
			}
			break;

		case MSG_FONT_CHANGED:
			PostMessage(MSG_HALF_FONT_CHANGED);
			break;

		case MSG_COLOR_CHANGED:
		case MSG_COLOR_SCHEME_CHANGED:
		{
			_SetTermColors(_ActiveTermViewContainerView());
			_ActiveTermViewContainerView()->Invalidate();
			_ActiveTermView()->Invalidate();
			break;
		}

		case SAVE_AS_DEFAULT:
		{
			BPath path;
			if (PrefHandler::GetDefaultPath(path) == B_OK)
				PrefHandler::Default()->SaveAsText(path.Path(),
					PREFFILE_MIMETYPE);
			break;
		}
		case MENU_PAGE_SETUP:
			_DoPageSetup();
			break;

		case MENU_PRINT:
			_DoPrint();
			break;

		case MSG_CHECK_CHILDREN:
			_CheckChildren();
			break;

		case MSG_MOVE_TAB_LEFT:
		case MSG_MOVE_TAB_RIGHT:
			_NavigateTab(_IndexOfTermView(_ActiveTermView()),
				message->what == MSG_MOVE_TAB_LEFT ? -1 : 1, true);
			break;

		case kTabTitleChanged:
		{
			// tab title changed message from SetTitleDialog
			SessionID sessionID(*message, "session");
			if (Session* session = _SessionForID(sessionID)) {
				BString title;
				if (message->FindString("title", &title) == B_OK) {
					session->title.pattern = title;
					session->title.patternUserDefined = true;
				} else {
					session->title.pattern.Truncate(0);
					session->title.patternUserDefined = false;
				}
				_UpdateSessionTitle(_IndexOfSession(session));
			}
			break;
		}

		case kWindowTitleChanged:
		{
			// window title changed message from SetTitleDialog
			BString title;
			if (message->FindString("title", &title) == B_OK) {
				fTitle.pattern = title;
				fTitle.patternUserDefined = true;
			} else {
				fTitle.pattern
					= PrefHandler::Default()->getString(PREF_WINDOW_TITLE);
				fTitle.patternUserDefined = false;
			}

			_UpdateSessionTitle(fTabView->Selection());
				// updates the window title as a side effect

			break;
		}

		case kSetActiveTab:
		{
			int32 index;
			if (message->FindInt32("index", &index) == B_OK
					&& index >= 0 && index < fSessions.CountItems()) {
				fTabView->Select(index);
			}
			break;
		}

		case kNewTab:
			_NewTab();
			break;

		case kCloseView:
		{
			int32 index = -1;
			SessionID sessionID(*message, "session");
			if (sessionID.IsValid()) {
				if (Session* session = _SessionForID(sessionID))
					index = _IndexOfSession(session);
			} else
				index = _IndexOfTermView(_ActiveTermView());

			if (index >= 0)
				_RemoveTab(index);

			break;
		}

		case kCloseOtherViews:
		{
			Session* session = _SessionForID(SessionID(*message, "session"));
			if (session == NULL)
				break;

			int32 count = fSessions.CountItems();
			for (int32 i = count - 1; i >= 0; i--) {
				if (_SessionAt(i) != session)
					_RemoveTab(i);
			}

			break;
		}

		case kIncreaseFontSize:
		case kDecreaseFontSize:
		{
			BFont font;
			_ActiveTermView()->GetTermFont(&font);
			float size = font.Size();

			if (message->what == kIncreaseFontSize) {
				if (size < 12)
					size += 1;
				else if (size < 24)
					size += 2;
				else
					size += 4;
			} else {
				if (size <= 12)
					size -= 1;
				else if (size <= 24)
					size -= 2;
				else
					size -= 4;
			}

			// constrain the font size
			if (size < kMinimumFontSize)
				size = kMinimumFontSize;
			if (size > kMaximumFontSize)
				size = kMaximumFontSize;

			// mark the font size menu item
			for (int32 i = 0; i < fFontSizeMenu->CountItems(); i++) {
				BMenuItem* item = fFontSizeMenu->ItemAt(i);
				if (item == NULL)
					continue;

				item->SetMarked(false);
				if (atoi(item->Label()) == size)
					item->SetMarked(true);
			}

			font.SetSize(size);
			PrefHandler::Default()->setInt32(PREF_HALF_FONT_SIZE, (int32)size);
			for (int32 i = 0; i < fTabView->CountTabs(); i++) {
				TermView* view = _TermViewAt(i);
				_TermViewAt(i)->SetTermFont(&font);
				_ResizeView(view);
			}
			break;
		}

		case kUpdateTitles:
			_UpdateTitles();
			break;

		case kEditTabTitle:
		{
			SessionID sessionID(*message, "session");
			if (Session* session = _SessionForID(sessionID))
				_OpenSetTabTitleDialog(_IndexOfSession(session));
			break;
		}

		case kEditWindowTitle:
			_OpenSetWindowTitleDialog();
			break;

		case kUpdateSwitchTerminalsMenuItem:
			_UpdateSwitchTerminalsMenuItem();
			break;

		default:
			BWindow::MessageReceived(message);
			break;
	}
}
Beispiel #6
0
bool
TermWindow::_CanClose(int32 index)
{
	bool warnOnExit = PrefHandler::Default()->getBool(PREF_WARN_ON_EXIT);

	if (!warnOnExit)
		return true;

	uint32 busyProcessCount = 0;
	BString busyProcessNames;
		// all names, separated by "\n\t"

	if (index != -1) {
		ShellInfo shellInfo;
		ActiveProcessInfo info;
		TermView* termView = _TermViewAt(index);
		if (termView->GetShellInfo(shellInfo)
			&& termView->GetActiveProcessInfo(info)
			&& (info.ID() != shellInfo.ProcessID()
				|| !shellInfo.IsDefaultShell())) {
			busyProcessCount++;
			busyProcessNames = info.Name();
		}
	} else {
		for (int32 i = 0; i < fSessions.CountItems(); i++) {
			ShellInfo shellInfo;
			ActiveProcessInfo info;
			TermView* termView = _TermViewAt(i);
			if (termView->GetShellInfo(shellInfo)
				&& termView->GetActiveProcessInfo(info)
				&& (info.ID() != shellInfo.ProcessID()
					|| !shellInfo.IsDefaultShell())) {
				if (++busyProcessCount > 1)
					busyProcessNames << "\n\t";
				busyProcessNames << info.Name();
			}
		}
	}

	if (busyProcessCount == 0)
		return true;

	BString alertMessage;
	if (busyProcessCount == 1) {
		// Only one pending process. Select the alert text depending on whether
		// the terminal will be closed.
		alertMessage = index == -1 || fSessions.CountItems() == 1
			? B_TRANSLATE("The process \"%1\" is still running.\n"
				"If you close the Terminal, the process will be killed.")
			: B_TRANSLATE("The process \"%1\" is still running.\n"
				"If you close the tab, the process will be killed.");
	} else {
		// multiple pending processes
		alertMessage = B_TRANSLATE(
			"The following processes are still running:\n\n"
			"\t%1\n\n"
			"If you close the Terminal, the processes will be killed.");
	}

	alertMessage.ReplaceFirst("%1", busyProcessNames);

	BAlert* alert = new BAlert(B_TRANSLATE("Really close?"),
		alertMessage, B_TRANSLATE("Close"), B_TRANSLATE("Cancel"), NULL,
		B_WIDTH_AS_USUAL, B_WARNING_ALERT);
	alert->SetShortcut(1, B_ESCAPE);
	return alert->Go() == 0;
}