2 * Copyright 2001-2013, Haiku, Inc. All rights reserved.
3 * Copyright (c) 2003-2004 Kian Duffy <myob@users.sourceforge.net>
4 * Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
6 * Distributed unter the terms of the MIT license.
9 * Kian Duffy, myob@users.sourceforge.net
10 * Siarzhuk Zharski, zharik@gmx.li
24 #include <Clipboard.h>
26 #include <InterfaceDefs.h>
34 #include "Arguments.h"
36 #include "PrefHandler.h"
37 #include "TermConst.h"
38 #include "TermWindow.h"
41 static bool sUsageRequested
= false;
42 //static bool sGeometryRequested = false;
44 rgb_color
TermApp::fDefaultPalette
[kTermColorCount
];
55 #undef B_TRANSLATION_CONTEXT
56 #define B_TRANSLATION_CONTEXT "Terminal TermApp"
60 BApplication(TERM_SIGNATURE
),
61 fChildCleanupThread(-1),
63 fStartFullscreen(false),
67 fArgs
= new Arguments(0, NULL
);
69 _InitDefaultPalette();
82 // Prevent opeing window when option -h is given.
86 // Install a SIGCHLD signal handler, so that we will be notified, when
87 // a shell exits. The handler itself will never be executed, since we block
88 // the signal in all threads and handle it with sigwaitinfo() in the child
90 struct sigaction action
;
91 action
.sa_handler
= (__sighandler_t
)_SigChildHandler
;
92 sigemptyset(&action
.sa_mask
);
94 if (sigaction(SIGCHLD
, &action
, NULL
) < 0) {
95 fprintf(stderr
, "sigaction() failed: %s\n", strerror(errno
));
99 // block SIGCHLD and SIGUSR1 -- we send the latter to wake up the child
100 // cleanup thread when quitting.
101 sigset_t blockedSignals
;
102 sigemptyset(&blockedSignals
);
103 sigaddset(&blockedSignals
, SIGCHLD
);
104 sigaddset(&blockedSignals
, SIGUSR1
);
106 int error
= pthread_sigmask(SIG_BLOCK
, &blockedSignals
, NULL
);
108 fprintf(stderr
, "pthread_sigmask() failed: %s\n", strerror(errno
));
110 // spawn the child cleanup thread
111 fChildCleanupThread
= spawn_thread(_ChildCleanupThreadEntry
,
112 "child cleanup", B_NORMAL_PRIORITY
, this);
113 if (fChildCleanupThread
>= 0) {
114 resume_thread(fChildCleanupThread
);
116 fprintf(stderr
, "Failed to start child cleanup thread: %s\n",
117 strerror(fChildCleanupThread
));
120 // init the mouse copy'n'paste clipboard
121 gMouseClipboard
= new BClipboard(MOUSE_CLIPBOARD_NAME
, true);
123 status_t status
= _MakeTermWindow();
125 // failed spawn, print stdout and open alert panel
126 // TODO: This alert does never show up.
128 BAlert
* alert
= new BAlert("alert",
129 B_TRANSLATE("Terminal couldn't start the shell. Sorry."),
130 B_TRANSLATE("OK"), NULL
, NULL
, B_WIDTH_FROM_LABEL
,
132 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
134 PostMessage(B_QUIT_REQUESTED
);
138 // using BScreen::Frame isn't enough
139 if (fStartFullscreen
)
140 BMessenger(fTermWindow
).SendMessage(FULLSCREEN
);
145 TermApp::QuitRequested()
147 // check whether the system is shutting down
148 BMessage
* message
= CurrentMessage();
150 if (message
!= NULL
&& message
->FindBool("_shutdown_", &shutdown
) == B_OK
152 // The system is shutting down. Quit the window synchronously. This
153 // skips the checks for running processes and the "Are you sure..."
155 if (fTermWindow
->Lock())
159 return BApplication::QuitRequested();
168 if (fChildCleanupThread
>= 0) {
169 send_signal(fChildCleanupThread
, SIGUSR1
);
170 wait_for_thread(fChildCleanupThread
, NULL
);
173 BApplication::Quit();
178 TermApp::MessageReceived(BMessage
* message
)
180 switch (message
->what
) {
181 case MSG_ACTIVATE_TERM
:
182 fTermWindow
->Activate();
186 BApplication::MessageReceived(message
);
193 TermApp::ArgvReceived(int32 argc
, char **argv
)
195 fArgs
->Parse(argc
, argv
);
197 if (fArgs
->UsageRequested()) {
199 sUsageRequested
= true;
200 PostMessage(B_QUIT_REQUESTED
);
204 if (fArgs
->Title() != NULL
)
205 fWindowTitle
= fArgs
->Title();
207 fStartFullscreen
= fArgs
->FullScreen();
212 TermApp::RefsReceived(BMessage
* message
)
214 // Works Only Launced by Double-Click file, or Drags file to App.
219 if (message
->FindRef("refs", 0, &ref
) != B_OK
)
223 if (file
.SetTo(&ref
, B_READ_WRITE
) != B_OK
)
226 BNodeInfo
info(&file
);
227 char mimetype
[B_MIME_TYPE_LENGTH
];
228 info
.GetType(mimetype
);
230 // if App opened by Pref file
231 if (strcmp(mimetype
, PREFFILE_MIMETYPE
) == 0) {
235 PrefHandler::Default()->OpenText(path
.Path());
239 // if App opened by Shell Script
240 if (strcmp(mimetype
, "text/x-haiku-shscript") == 0) {
249 TermApp::_MakeTermWindow()
252 fTermWindow
= new TermWindow(fWindowTitle
, fArgs
);
253 } catch (int error
) {
254 return (status_t
)error
;
265 //#ifndef B_NETPOSITIVE_APP_SIGNATURE
266 //#define B_NETPOSITIVE_APP_SIGNATURE "application/x-vnd.Be-NPOS"
270 //TermApp::ShowHTML(BMessage *msg)
273 // msg->FindString("Url", &url);
276 // message.what = B_NETPOSITIVE_OPEN_URL;
277 // message.AddString("be:url", url);
279 // be_roster->Launch(B_NETPOSITIVE_APP_SIGNATURE, &message);
280 // while(!(be_roster->IsRunning(B_NETPOSITIVE_APP_SIGNATURE)))
284 // be_roster->ActivateApp(be_roster->TeamFor(B_NETPOSITIVE_APP_SIGNATURE));
289 TermApp::_SigChildHandler(int signal
, void* data
)
291 fprintf(stderr
, "Terminal: _SigChildHandler() called! That should never "
297 TermApp::_ChildCleanupThreadEntry(void* data
)
299 return ((TermApp
*)data
)->_ChildCleanupThread();
304 TermApp::_ChildCleanupThread()
306 sigset_t waitForSignals
;
307 sigemptyset(&waitForSignals
);
308 sigaddset(&waitForSignals
, SIGCHLD
);
309 sigaddset(&waitForSignals
, SIGUSR1
);
313 int error
= sigwait(&waitForSignals
, &signal
);
318 if (error
== 0 && signal
== SIGCHLD
)
319 fTermWindow
->PostMessage(MSG_CHECK_CHILDREN
);
327 TermApp::_Usage(char *name
)
329 fprintf(stderr
, B_TRANSLATE("Haiku Terminal\n"
330 "Copyright 2001-2009 Haiku, Inc.\n"
331 "Copyright(C) 1999 Kazuho Okui and Takashi Murai.\n"
333 "Usage: %s [OPTION] [SHELL]\n"), name
);
336 B_TRANSLATE(" -h, --help print this help\n"
337 //" -p, --preference load preference file\n"
338 " -t, --title set window title\n"
339 " -f, --fullscreen start fullscreen\n")
340 //" -geom, --geometry set window geometry\n"
341 //" An example of geometry is \"80x25+100+100\"\n"
347 TermApp::_InitDefaultPalette()
349 // 0 - 15 are system ANSI colors
350 const char * keys
[kANSIColorCount
] = {
351 PREF_ANSI_BLACK_COLOR
,
353 PREF_ANSI_GREEN_COLOR
,
354 PREF_ANSI_YELLOW_COLOR
,
355 PREF_ANSI_BLUE_COLOR
,
356 PREF_ANSI_MAGENTA_COLOR
,
357 PREF_ANSI_CYAN_COLOR
,
358 PREF_ANSI_WHITE_COLOR
,
359 PREF_ANSI_BLACK_HCOLOR
,
360 PREF_ANSI_RED_HCOLOR
,
361 PREF_ANSI_GREEN_HCOLOR
,
362 PREF_ANSI_YELLOW_HCOLOR
,
363 PREF_ANSI_BLUE_HCOLOR
,
364 PREF_ANSI_MAGENTA_HCOLOR
,
365 PREF_ANSI_CYAN_HCOLOR
,
366 PREF_ANSI_WHITE_HCOLOR
369 rgb_color
* color
= fDefaultPalette
;
370 PrefHandler
* handler
= PrefHandler::Default();
371 for (uint i
= 0; i
< kANSIColorCount
; i
++)
372 *color
++ = handler
->getRGB(keys
[i
]);
374 // 16 - 231 are 6x6x6 color "cubes" in xterm color model
375 for (uint red
= 0; red
< 256; red
+= (red
== 0) ? 95 : 40)
376 for (uint green
= 0; green
< 256; green
+= (green
== 0) ? 95 : 40)
377 for (uint blue
= 0; blue
< 256; blue
+= (blue
== 0) ? 95 : 40)
378 (*color
++).set_to(red
, green
, blue
);
380 // 232 - 255 are grayscale ramp in xterm color model
381 for (uint gray
= 8; gray
< 240; gray
+= 10)
382 (*color
++).set_to(gray
, gray
, gray
);