19105df34Sshatty/*
2b7d01200SAxel Dörfler * Copyright 2007-2015, Haiku, Inc. All rights reserved.
369adf535SStefano Ceccherini * Copyright (c) 2004 Daniel Furrer <assimil8or@users.sourceforge.net>
48002431bSDarkWyrm * Copyright (c) 2003-2004 Kian Duffy <myob@users.sourceforge.net>
57aed1511SAxel Dörfler * Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
69105df34Sshatty *
769adf535SStefano Ceccherini * Distributed under the terms of the MIT license.
85b41331fSSiarzhuk Zharski *
95b41331fSSiarzhuk Zharski * Authors:
105b41331fSSiarzhuk Zharski *		Kian Duffy, myob@users.sourceforge.net
115b41331fSSiarzhuk Zharski *		Daniel Furrer, assimil8or@users.sourceforge.net
1255067dfeSJohn Scipione *		John Scipione, jscipione@gmail.com
138840b3dbSSimon South *		Simon South, simon@simonsouth.net
145b41331fSSiarzhuk Zharski *		Siarzhuk Zharski, zharik@gmx.li
159105df34Sshatty */
16b10dd441SStefano Ceccherini
178e96ec34SAxel Dörfler
18b10dd441SStefano Ceccherini#include "TermWindow.h"
19b10dd441SStefano Ceccherini
208c6aa65eSStefano Ceccherini#include <new>
2152b1d543SIngo Weinhold#include <stdio.h>
22dc1456f6SJohn Scipione#include <stdlib.h>
233aeed660SJérôme Duval#include <strings.h>
2452b1d543SIngo Weinhold#include <time.h>
25b10dd441SStefano Ceccherini
269fe40077SJérôme Duval#include <Alert.h>
279fe40077SJérôme Duval#include <Application.h>
288989d8a5SStephan Aßmus#include <Catalog.h>
29f3782185SSiarzhuk Zharski#include <CharacterSet.h>
30f3782185SSiarzhuk Zharski#include <CharacterSetRoster.h>
3118f004ccSStefano Ceccherini#include <Clipboard.h>
3269adf535SStefano Ceccherini#include <Dragger.h>
33105093fdSIngo Weinhold#include <File.h>
34105093fdSIngo Weinhold#include <FindDirectory.h>
35354649f1SJohn Scipione#include <Keymap.h>
361ded93a4SIngo Weinhold#include <LayoutBuilder.h>
37135f173dSIngo Weinhold#include <LayoutUtils.h>
388989d8a5SStephan Aßmus#include <Locale.h>
399105df34Sshatty#include <Menu.h>
409105df34Sshatty#include <MenuBar.h>
419105df34Sshatty#include <MenuItem.h>
42354649f1SJohn Scipione#include <ObjectList.h>
439fe40077SJérôme Duval#include <Path.h>
44d365030eSIngo Weinhold#include <PopUpMenu.h>
459fe40077SJérôme Duval#include <PrintJob.h>
4655eb18efSJohn Scipione#include <Rect.h>
47bc96eab5SJérôme Duval#include <Roster.h>
48289ca930SFrançois Revol#include <Screen.h>
499105df34Sshatty#include <ScrollBar.h>
50678f903eSStefano Ceccherini#include <ScrollView.h>
51b1904124SStefano Ceccherini#include <String.h>
52354649f1SJohn Scipione#include <UnicodeChar.h>
53f3782185SSiarzhuk Zharski#include <UTF8.h>
54b1904124SStefano Ceccherini
55105093fdSIngo Weinhold#include <AutoLocker.h>
56105093fdSIngo Weinhold
5737322c4bSIngo Weinhold#include "ActiveProcessInfo.h"
5852b1d543SIngo Weinhold#include "Arguments.h"
59bf00b779SStefano Ceccherini#include "AppearPrefView.h"
6052b1d543SIngo Weinhold#include "FindWindow.h"
61a2ba3d65SStefano Ceccherini#include "Globals.h"
6252b1d543SIngo Weinhold#include "PrefWindow.h"
6352b1d543SIngo Weinhold#include "PrefHandler.h"
64135f173dSIngo Weinhold#include "SetTitleDialog.h"
6537322c4bSIngo Weinhold#include "ShellParameters.h"
6652b1d543SIngo Weinhold#include "TermConst.h"
6752b1d543SIngo Weinhold#include "TermScrollView.h"
6802ee32bbSIngo Weinhold#include "TitlePlaceholderMapper.h"
699105df34Sshatty
70b0307f5cSIngo Weinhold
7152b1d543SIngo Weinholdconst static int32 kTermViewOffset = 3;
7258cf7360SStefano Ceccherini
731eccdc25SJohn Scipioneconst static int32 kMinimumFontSize = 8;
741eccdc25SJohn Scipioneconst static int32 kMaximumFontSize = 36;
751eccdc25SJohn Scipione
7658cf7360SStefano Ceccherini// messages constants
77ad617d33SIngo Weinholdstatic const uint32 kNewTab = 'NTab';
78ad617d33SIngo Weinholdstatic const uint32 kCloseView = 'ClVw';
7947dbffcdSIngo Weinholdstatic const uint32 kCloseOtherViews = 'CloV';
80ad617d33SIngo Weinholdstatic const uint32 kIncreaseFontSize = 'InFs';
81ad617d33SIngo Weinholdstatic const uint32 kDecreaseFontSize = 'DcFs';
82ad617d33SIngo Weinholdstatic const uint32 kSetActiveTab = 'STab';
83ad617d33SIngo Weinholdstatic const uint32 kUpdateTitles = 'UPti';
84ad617d33SIngo Weinholdstatic const uint32 kEditTabTitle = 'ETti';
85ad617d33SIngo Weinholdstatic const uint32 kEditWindowTitle = 'EWti';
86ad617d33SIngo Weinholdstatic const uint32 kTabTitleChanged = 'TTch';
87ad617d33SIngo Weinholdstatic const uint32 kWindowTitleChanged = 'WTch';
88105093fdSIngo Weinholdstatic const uint32 kUpdateSwitchTerminalsMenuItem = 'Ustm';
8918f004ccSStefano Ceccherini
90f3782185SSiarzhuk Zharskiusing namespace BPrivate ; // BCharacterSet stuff
91b0307f5cSIngo Weinhold
92546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
93546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "Terminal TermWindow"
9418f004ccSStefano Ceccherini
95ca0d2711SFrançois Revol// actually an arrow
96ca0d2711SFrançois Revol#define UTF8_ENTER "\xe2\x86\xb5"
97ca0d2711SFrançois Revol
98b0307f5cSIngo Weinhold
99b1b68540SIngo Weinhold// #pragma mark - TermViewContainerView
100b1b68540SIngo Weinhold
101b1b68540SIngo Weinhold
10252b1d543SIngo Weinholdclass TermViewContainerView : public BView {
10352b1d543SIngo Weinholdpublic:
10452b1d543SIngo Weinhold	TermViewContainerView(TermView* termView)
1057aed1511SAxel Dörfler		:
10652b1d543SIngo Weinhold		BView(BRect(), "term view container", B_FOLLOW_ALL, 0),
10752b1d543SIngo Weinhold		fTermView(termView)
10852b1d543SIngo Weinhold	{
10952b1d543SIngo Weinhold		termView->MoveTo(kTermViewOffset, kTermViewOffset);
11052b1d543SIngo Weinhold		BRect frame(termView->Frame());
11152b1d543SIngo Weinhold		ResizeTo(frame.right + kTermViewOffset, frame.bottom + kTermViewOffset);
11252b1d543SIngo Weinhold		AddChild(termView);
11352b1d543SIngo Weinhold	}
11452b1d543SIngo Weinhold
11552b1d543SIngo Weinhold	TermView* GetTermView() const	{ return fTermView; }
11652b1d543SIngo Weinhold
11752b1d543SIngo Weinhold	virtual void GetPreferredSize(float* _width, float* _height)
11852b1d543SIngo Weinhold	{
11952b1d543SIngo Weinhold		float width, height;
12052b1d543SIngo Weinhold		fTermView->GetPreferredSize(&width, &height);
12152b1d543SIngo Weinhold		*_width = width + 2 * kTermViewOffset;
12252b1d543SIngo Weinhold		*_height = height + 2 * kTermViewOffset;
12352b1d543SIngo Weinhold	}
12452b1d543SIngo Weinhold
12552b1d543SIngo Weinholdprivate:
12652b1d543SIngo Weinhold	TermView*	fTermView;
12752b1d543SIngo Weinhold};
12852b1d543SIngo Weinhold
12952b1d543SIngo Weinhold
130b1b68540SIngo Weinhold// #pragma mark - SessionID
131b1b68540SIngo Weinhold
132b1b68540SIngo Weinhold
133b1b68540SIngo WeinholdTermWindow::SessionID::SessionID(int32 id)
134b1b68540SIngo Weinhold	:
135b1b68540SIngo Weinhold	fID(id)
136b1b68540SIngo Weinhold{
137b1b68540SIngo Weinhold}
138b1b68540SIngo Weinhold
139b1b68540SIngo Weinhold
140b1b68540SIngo WeinholdTermWindow::SessionID::SessionID(const BMessage& message, const char* field)
141b1b68540SIngo Weinhold{
1425feeb234SIngo Weinhold	if (message.FindInt32(field, &fID) != B_OK)
1435feeb234SIngo Weinhold		fID = -1;
144b1b68540SIngo Weinhold}
145b1b68540SIngo Weinhold
146b1b68540SIngo Weinhold
147b1b68540SIngo Weinholdstatus_t
148b1b68540SIngo WeinholdTermWindow::SessionID::AddToMessage(BMessage& message, const char* field) const
149b1b68540SIngo Weinhold{
150b1b68540SIngo Weinhold	return message.AddInt32(field, fID);
151b1b68540SIngo Weinhold}
152b1b68540SIngo Weinhold
153b1b68540SIngo Weinhold
154b1b68540SIngo Weinhold// #pragma mark - Session
155b1b68540SIngo Weinhold
156b1b68540SIngo Weinhold
157799a9a34SIngo Weinholdstruct TermWindow::Session {
158b1b68540SIngo Weinhold	SessionID				id;
159b1b68540SIngo Weinhold	int32					index;
16002ee32bbSIngo Weinhold	Title					title;
161799a9a34SIngo Weinhold	TermViewContainerView*	containerView;
162799a9a34SIngo Weinhold
163b1b68540SIngo Weinhold	Session(SessionID id, int32 index, TermViewContainerView* containerView)
164799a9a34SIngo Weinhold		:
165799a9a34SIngo Weinhold		id(id),
166b1b68540SIngo Weinhold		index(index),
167799a9a34SIngo Weinhold		containerView(containerView)
168799a9a34SIngo Weinhold	{
16902ee32bbSIngo Weinhold		title.title = B_TRANSLATE("Shell ");
170b1b68540SIngo Weinhold		title.title << index;
17102ee32bbSIngo Weinhold		title.patternUserDefined = false;
172799a9a34SIngo Weinhold	}
173799a9a34SIngo Weinhold};
174799a9a34SIngo Weinhold
175799a9a34SIngo Weinhold
176b1b68540SIngo Weinhold// #pragma mark - TermWindow
177b1b68540SIngo Weinhold
178b1b68540SIngo Weinhold
179105093fdSIngo WeinholdTermWindow::TermWindow(const BString& title, Arguments* args)
1806df054eeSIngo Weinhold	:
181105093fdSIngo Weinhold	BWindow(BRect(0, 0, 0, 0), title, B_DOCUMENT_WINDOW,
182105093fdSIngo Weinhold		B_CURRENT_WORKSPACE | B_QUIT_ON_WINDOW_CLOSE),
18302ee32bbSIngo Weinhold	fTitleUpdateRunner(this, BMessage(kUpdateTitles), 1000000),
184b1b68540SIngo Weinhold	fNextSessionID(0),
18569adf535SStefano Ceccherini	fTabView(NULL),
1868a6bf08dSIngo Weinhold	fMenuBar(NULL),
187b216f407SIngo Weinhold	fSwitchTerminalsMenuItem(NULL),
1888a6bf08dSIngo Weinhold	fEncodingMenu(NULL),
18969adf535SStefano Ceccherini	fPrintSettings(NULL),
19069adf535SStefano Ceccherini	fPrefWindow(NULL),
19169adf535SStefano Ceccherini	fFindPanel(NULL),
19269adf535SStefano Ceccherini	fSavedFrame(0, 0, -1, -1),
193486cd821SIngo Weinhold	fSetWindowTitleDialog(NULL),
194135f173dSIngo Weinhold	fSetTabTitleDialog(NULL),
19569adf535SStefano Ceccherini	fFindString(""),
1964aa87c04SIngo Weinhold	fFindNextMenuItem(NULL),
1974aa87c04SIngo Weinhold	fFindPreviousMenuItem(NULL),
19869adf535SStefano Ceccherini	fFindSelection(false),
19969adf535SStefano Ceccherini	fForwardSearch(false),
20069adf535SStefano Ceccherini	fMatchCase(false),
201ffcedfaaSPhilippe Saint-Pierre	fMatchWord(false),
202ffcedfaaSPhilippe Saint-Pierre	fFullScreen(false)
203702e4be8SStefano Ceccherini{
204105093fdSIngo Weinhold	// register this terminal
205105093fdSIngo Weinhold	fTerminalRoster.Register(Team(), this);
206105093fdSIngo Weinhold	fTerminalRoster.SetListener(this);
207105093fdSIngo Weinhold	int32 id = fTerminalRoster.ID();
208105093fdSIngo Weinhold
2098840b3dbSSimon South	// fetch the current keymap
2108840b3dbSSimon South	get_key_map(&fKeymap, &fKeymapChars);
2118840b3dbSSimon South
21202ee32bbSIngo Weinhold	// apply the title settings
21302ee32bbSIngo Weinhold	fTitle.pattern = title;
214105093fdSIngo Weinhold	if (fTitle.pattern.Length() == 0) {
215560ff447SJonas Sundström		fTitle.pattern = B_TRANSLATE_SYSTEM_NAME("Terminal");
216105093fdSIngo Weinhold
217105093fdSIngo Weinhold		if (id >= 0)
218105093fdSIngo Weinhold			fTitle.pattern << " " << id + 1;
219105093fdSIngo Weinhold
220105093fdSIngo Weinhold		fTitle.patternUserDefined = false;
221105093fdSIngo Weinhold	} else
222105093fdSIngo Weinhold		fTitle.patternUserDefined = true;
223105093fdSIngo Weinhold
224105093fdSIngo Weinhold	fTitle.title = fTitle.pattern;
225105093fdSIngo Weinhold	fTitle.pattern = title;
226105093fdSIngo Weinhold
22702ee32bbSIngo Weinhold	_TitleSettingsChanged();
22802ee32bbSIngo Weinhold
229105093fdSIngo Weinhold	// get the saved window position and workspaces
230105093fdSIngo Weinhold	BRect frame;
231105093fdSIngo Weinhold	uint32 workspaces;
232105093fdSIngo Weinhold	if (_LoadWindowPosition(&frame, &workspaces) == B_OK) {
233a95a728cSAdrien Destugues		// make sure the window is still on screen
234a95a728cSAdrien Destugues		// (for example if there was a resolution change)
23552e43a20SAxel Dörfler		BRect screenFrame = BScreen(this).Frame();
23652e43a20SAxel Dörfler		if (frame.Width() <= screenFrame.Width()
23752e43a20SAxel Dörfler			&& frame.Height() <= screenFrame.Height())
238a95a728cSAdrien Destugues			ResizeTo(frame.Width(), frame.Height());
23952e43a20SAxel Dörfler
24052e43a20SAxel Dörfler		MoveTo(frame.LeftTop());
2418e96ec34SAxel Dörfler		MoveOnScreen(B_MOVE_IF_PARTIALLY_OFFSCREEN);
242a95a728cSAdrien Destugues
243105093fdSIngo Weinhold		SetWorkspaces(workspaces);
244105093fdSIngo Weinhold	} else {
245105093fdSIngo Weinhold		// use computed defaults
246fa89878aSAxel Dörfler		int row = id / 16;
247fa89878aSAxel Dörfler		int column = id % 16;
248fa89878aSAxel Dörfler		int x = (column * 16) + (row * 64) + 50;
249fa89878aSAxel Dörfler		int y = (column * 16) + 50;
250b216f407SIngo Weinhold
251fa89878aSAxel Dörfler		MoveTo(x, y);
252105093fdSIngo Weinhold	}
253b216f407SIngo Weinhold
254105093fdSIngo Weinhold	// init the GUI and add a tab
255105093fdSIngo Weinhold	_InitWindow();
256105093fdSIngo Weinhold	_AddTab(args);
25765b57677SIngo Weinhold
25865b57677SIngo Weinhold	// Announce our window as no longer minimized. That's not true, since it's
25965b57677SIngo Weinhold	// still hidden at this point, but it will be shown very soon.
26065b57677SIngo Weinhold	fTerminalRoster.SetWindowInfo(false, Workspaces());
261702e4be8SStefano Ceccherini}
262f14a8c58SStefano Ceccherini
26371922d19SAxel Dörfler
2649105df34SshattyTermWindow::~TermWindow()
2659105df34Sshatty{
266105093fdSIngo Weinhold	fTerminalRoster.Unregister();
267b216f407SIngo Weinhold
268135f173dSIngo Weinhold	_FinishTitleDialog();
269135f173dSIngo Weinhold
2707aed1511SAxel Dörfler	if (fPrefWindow)
2713fa02e15SIngo Weinhold		fPrefWindow->PostMessage(B_QUIT_REQUESTED);
2723fa02e15SIngo Weinhold
27396d6092eSStefano Ceccherini	if (fFindPanel && fFindPanel->Lock()) {
27496d6092eSStefano Ceccherini		fFindPanel->Quit();
27596d6092eSStefano Ceccherini		fFindPanel = NULL;
27696d6092eSStefano Ceccherini	}
277d76009fdSIngo Weinhold
278dc25fe81SStefano Ceccherini	PrefHandler::DeleteDefault();
279799a9a34SIngo Weinhold
280713b2a78SIngo Weinhold	for (int32 i = 0; Session* session = _SessionAt(i); i++)
281799a9a34SIngo Weinhold		delete session;
2828840b3dbSSimon South
2838840b3dbSSimon South	delete fKeymap;
2848840b3dbSSimon South	delete[] fKeymapChars;
2859105df34Sshatty}
2869105df34Sshatty
28711516ceeSAxel Dörfler
2886df054eeSIngo Weinholdvoid
2896df054eeSIngo WeinholdTermWindow::SessionChanged()
2906df054eeSIngo Weinhold{
29102ee32bbSIngo Weinhold	_UpdateSessionTitle(fTabView->Selection());
2926df054eeSIngo Weinhold}
2936df054eeSIngo Weinhold
2946df054eeSIngo Weinhold
2959105df34Sshattyvoid
296bb4632f1SStefano CeccheriniTermWindow::_InitWindow()
2979105df34Sshatty{
29811516ceeSAxel Dörfler	// make menu bar
2996fbf283fSStefano Ceccherini	_SetupMenu();
3009105df34Sshatty
30140bbe4ecSIngo Weinhold	// shortcuts to switch tabs
30240bbe4ecSIngo Weinhold	for (int32 i = 0; i < 9; i++) {
30340bbe4ecSIngo Weinhold		BMessage* message = new BMessage(kSetActiveTab);
30440bbe4ecSIngo Weinhold		message->AddInt32("index", i);
30540bbe4ecSIngo Weinhold		AddShortcut('1' + i, B_COMMAND_KEY, message);
30640bbe4ecSIngo Weinhold	}
307d76009fdSIngo Weinhold
30838d5ce62SIngo Weinhold	AddShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
30938d5ce62SIngo Weinhold		new BMessage(MSG_MOVE_TAB_LEFT));
31038d5ce62SIngo Weinhold	AddShortcut(B_RIGHT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
31138d5ce62SIngo Weinhold		new BMessage(MSG_MOVE_TAB_RIGHT));
31238d5ce62SIngo Weinhold
313678f903eSStefano Ceccherini	BRect textFrame = Bounds();
3148a6bf08dSIngo Weinhold	textFrame.top = fMenuBar->Bounds().bottom + 1.0;
3159105df34Sshatty
3169e47d4f7SAdrien Destugues	fTabView = new SmartTabView(textFrame, "tab view", B_WIDTH_FROM_LABEL);
317d365030eSIngo Weinhold	fTabView->SetListener(this);
318678f903eSStefano Ceccherini	AddChild(fTabView);
319272f87d6SIngo Weinhold
320272f87d6SIngo Weinhold	// Make the scroll view one pixel wider than the tab view container view, so
321272f87d6SIngo Weinhold	// the scroll bar will look good.
322272f87d6SIngo Weinhold	fTabView->SetInsets(0, 0, -1, 0);
3239105df34Sshatty}
32411516ceeSAxel Dörfler
32511516ceeSAxel Dörfler
326d9fdb4f6SStefano Ceccherinibool
327190806e6SStefano CeccheriniTermWindow::_CanClose(int32 index)
328d9fdb4f6SStefano Ceccherini{
3296491fb59SStefano Ceccherini	bool warnOnExit = PrefHandler::Default()->getBool(PREF_WARN_ON_EXIT);
3306491fb59SStefano Ceccherini
3316491fb59SStefano Ceccherini	if (!warnOnExit)
332190806e6SStefano Ceccherini		return true;
3336491fb59SStefano Ceccherini
33453c32667SIngo Weinhold	uint32 busyProcessCount = 0;
33553c32667SIngo Weinhold	BString busyProcessNames;
33653c32667SIngo Weinhold		// all names, separated by "\n\t"
33753c32667SIngo Weinhold
33853c32667SIngo Weinhold	if (index != -1) {
339ca598670SIngo Weinhold		ShellInfo shellInfo;
34053c32667SIngo Weinhold		ActiveProcessInfo info;
341ca598670SIngo Weinhold		TermView* termView = _TermViewAt(index);
342ca598670SIngo Weinhold		if (termView->GetShellInfo(shellInfo)
343ca598670SIngo Weinhold			&& termView->GetActiveProcessInfo(info)
344ca598670SIngo Weinhold			&& (info.ID() != shellInfo.ProcessID()
345ca598670SIngo Weinhold				|| !shellInfo.IsDefaultShell())) {
34653c32667SIngo Weinhold			busyProcessCount++;
34753c32667SIngo Weinhold			busyProcessNames = info.Name();
34853c32667SIngo Weinhold		}
34953c32667SIngo Weinhold	} else {
350190806e6SStefano Ceccherini		for (int32 i = 0; i < fSessions.CountItems(); i++) {
351ca598670SIngo Weinhold			ShellInfo shellInfo;
35253c32667SIngo Weinhold			ActiveProcessInfo info;
353ca598670SIngo Weinhold			TermView* termView = _TermViewAt(i);
354ca598670SIngo Weinhold			if (termView->GetShellInfo(shellInfo)
355ca598670SIngo Weinhold				&& termView->GetActiveProcessInfo(info)
356ca598670SIngo Weinhold				&& (info.ID() != shellInfo.ProcessID()
357ca598670SIngo Weinhold					|| !shellInfo.IsDefaultShell())) {
35853c32667SIngo Weinhold				if (++busyProcessCount > 1)
35953c32667SIngo Weinhold					busyProcessNames << "\n\t";
36053c32667SIngo Weinhold				busyProcessNames << info.Name();
361190806e6SStefano Ceccherini			}
3626491fb59SStefano Ceccherini		}
3636491fb59SStefano Ceccherini	}
3646491fb59SStefano Ceccherini
36553c32667SIngo Weinhold	if (busyProcessCount == 0)
36653c32667SIngo Weinhold		return true;
36753c32667SIngo Weinhold
36853c32667SIngo Weinhold	BString alertMessage;
36953c32667SIngo Weinhold	if (busyProcessCount == 1) {
37053c32667SIngo Weinhold		// Only one pending process. Select the alert text depending on whether
37153c32667SIngo Weinhold		// the terminal will be closed.
37253c32667SIngo Weinhold		alertMessage = index == -1 || fSessions.CountItems() == 1
37353c32667SIngo Weinhold			? B_TRANSLATE("The process \"%1\" is still running.\n"
37453cd28e9SIngo Weinhold				"If you close the Terminal, the process will be killed.")
37553c32667SIngo Weinhold			: B_TRANSLATE("The process \"%1\" is still running.\n"
37653cd28e9SIngo Weinhold				"If you close the tab, the process will be killed.");
37753c32667SIngo Weinhold	} else {
37853c32667SIngo Weinhold		// multiple pending processes
37953c32667SIngo Weinhold		alertMessage = B_TRANSLATE(
38053c32667SIngo Weinhold			"The following processes are still running:\n\n"
38153c32667SIngo Weinhold			"\t%1\n\n"
38236cdd7a2SIngo Weinhold			"If you close the Terminal, the processes will be killed.");
3836491fb59SStefano Ceccherini	}
3846491fb59SStefano Ceccherini
38553c32667SIngo Weinhold	alertMessage.ReplaceFirst("%1", busyProcessNames);
38653c32667SIngo Weinhold
38753c32667SIngo Weinhold	BAlert* alert = new BAlert(B_TRANSLATE("Really close?"),
38853c32667SIngo Weinhold		alertMessage, B_TRANSLATE("Close"), B_TRANSLATE("Cancel"), NULL,
38953c32667SIngo Weinhold		B_WIDTH_AS_USUAL, B_WARNING_ALERT);
39053c32667SIngo Weinhold	alert->SetShortcut(1, B_ESCAPE);
39153c32667SIngo Weinhold	return alert->Go() == 0;
392190806e6SStefano Ceccherini}
393190806e6SStefano Ceccherini
394190806e6SStefano Ceccherini
395190806e6SStefano Ceccherinibool
396190806e6SStefano CeccheriniTermWindow::QuitRequested()
397190806e6SStefano Ceccherini{
398135f173dSIngo Weinhold	_FinishTitleDialog();
399135f173dSIngo Weinhold
400190806e6SStefano Ceccherini	if (!_CanClose(-1))
401190806e6SStefano Ceccherini		return false;
402190806e6SStefano Ceccherini
403105093fdSIngo Weinhold	_SaveWindowPosition();
404d18fc399SAdrien Destugues
405d9fdb4f6SStefano Ceccherini	return BWindow::QuitRequested();
406d9fdb4f6SStefano Ceccherini}
407d9fdb4f6SStefano Ceccherini
408d9fdb4f6SStefano Ceccherini
4099105df34Sshattyvoid
4100d32d905SStefano CeccheriniTermWindow::MenusBeginning()
4119105df34Sshatty{
412ed47eeecSStefano Ceccherini	TermView* view = _ActiveTermView();
4135b41331fSSiarzhuk Zharski
41411516ceeSAxel Dörfler	// Syncronize Encode Menu Pop-up menu and Preference.
415f3782185SSiarzhuk Zharski	const BCharacterSet* charset
416f3782185SSiarzhuk Zharski		= BCharacterSetRoster::GetCharacterSetByConversionID(view->Encoding());
417f3782185SSiarzhuk Zharski	if (charset != NULL) {
418f3782185SSiarzhuk Zharski		BString name(charset->GetPrintName());
419f3782185SSiarzhuk Zharski		const char* mime = charset->GetMIMEName();
420f3782185SSiarzhuk Zharski		if (mime)
421f3782185SSiarzhuk Zharski			name << " (" << mime << ")";
422f3782185SSiarzhuk Zharski
423f3782185SSiarzhuk Zharski		BMenuItem* item = fEncodingMenu->FindItem(name);
424f3782185SSiarzhuk Zharski		if (item != NULL)
425f3782185SSiarzhuk Zharski			item->SetMarked(true);
426f3782185SSiarzhuk Zharski	}
427b61e1f74SPhilippe Saint-Pierre
428b61e1f74SPhilippe Saint-Pierre	BFont font;
429b61e1f74SPhilippe Saint-Pierre	view->GetTermFont(&font);
430b61e1f74SPhilippe Saint-Pierre
431b61e1f74SPhilippe Saint-Pierre	float size = font.Size();
432b61e1f74SPhilippe Saint-Pierre
4331eccdc25