void TermWindow::_NewTab() { ActiveProcessInfo info; if (_ActiveTermView()->GetActiveProcessInfo(info)) _AddTab(NULL, info.CurrentDirectory()); else _AddTab(NULL); }
void TermView::HyperLinkState::Entered() { ActiveProcessInfo activeProcessInfo; if (fView->GetActiveProcessInfo(activeProcessInfo)) fCurrentDirectory = activeProcessInfo.CurrentDirectory(); else fCurrentDirectory.Truncate(0); _UpdateHighlight(); }
void TermWindow::_NewTab() { if (fTabView->CountTabs() < kMaxTabs) { ActiveProcessInfo info; if (_ActiveTermView()->GetActiveProcessInfo(info)) _AddTab(NULL, info.CurrentDirectory()); else _AddTab(NULL); } }
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; }
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; } }
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; }