3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / apps / terminal / TermApp.cpp
blobbb016af6e9f29b34bb4732689b62d2780cb78165
1 /*
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.
8 * Authors:
9 * Kian Duffy, myob@users.sourceforge.net
10 * Siarzhuk Zharski, zharik@gmx.li
14 #include "TermApp.h"
16 #include <errno.h>
17 #include <signal.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
22 #include <Alert.h>
23 #include <Catalog.h>
24 #include <Clipboard.h>
25 #include <Catalog.h>
26 #include <InterfaceDefs.h>
27 #include <Locale.h>
28 #include <NodeInfo.h>
29 #include <Path.h>
30 #include <Roster.h>
31 #include <Screen.h>
32 #include <String.h>
34 #include "Arguments.h"
35 #include "Globals.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];
46 int
47 main()
49 TermApp app;
50 app.Run();
52 return 0;
55 #undef B_TRANSLATION_CONTEXT
56 #define B_TRANSLATION_CONTEXT "Terminal TermApp"
58 TermApp::TermApp()
60 BApplication(TERM_SIGNATURE),
61 fChildCleanupThread(-1),
62 fTerminating(false),
63 fStartFullscreen(false),
64 fTermWindow(NULL),
65 fArgs(NULL)
67 fArgs = new Arguments(0, NULL);
69 _InitDefaultPalette();
73 TermApp::~TermApp()
75 delete fArgs;
79 void
80 TermApp::ReadyToRun()
82 // Prevent opeing window when option -h is given.
83 if (sUsageRequested)
84 return;
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
89 // cleanup thread.
90 struct sigaction action;
91 action.sa_handler = (__sighandler_t)_SigChildHandler;
92 sigemptyset(&action.sa_mask);
93 action.sa_flags = 0;
94 if (sigaction(SIGCHLD, &action, NULL) < 0) {
95 fprintf(stderr, "sigaction() failed: %s\n", strerror(errno));
96 // continue anyway
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);
107 if (error != 0)
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);
115 } else {
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.
127 if (status < B_OK) {
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,
131 B_INFO_ALERT);
132 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
133 alert->Go(NULL);
134 PostMessage(B_QUIT_REQUESTED);
135 return;
138 // using BScreen::Frame isn't enough
139 if (fStartFullscreen)
140 BMessenger(fTermWindow).SendMessage(FULLSCREEN);
144 bool
145 TermApp::QuitRequested()
147 // check whether the system is shutting down
148 BMessage* message = CurrentMessage();
149 bool shutdown;
150 if (message != NULL && message->FindBool("_shutdown_", &shutdown) == B_OK
151 && shutdown) {
152 // The system is shutting down. Quit the window synchronously. This
153 // skips the checks for running processes and the "Are you sure..."
154 // alert.
155 if (fTermWindow->Lock())
156 fTermWindow->Quit();
159 return BApplication::QuitRequested();
163 void
164 TermApp::Quit()
166 fTerminating = true;
168 if (fChildCleanupThread >= 0) {
169 send_signal(fChildCleanupThread, SIGUSR1);
170 wait_for_thread(fChildCleanupThread, NULL);
173 BApplication::Quit();
177 void
178 TermApp::MessageReceived(BMessage* message)
180 switch (message->what) {
181 case MSG_ACTIVATE_TERM:
182 fTermWindow->Activate();
183 break;
185 default:
186 BApplication::MessageReceived(message);
187 break;
192 void
193 TermApp::ArgvReceived(int32 argc, char **argv)
195 fArgs->Parse(argc, argv);
197 if (fArgs->UsageRequested()) {
198 _Usage(argv[0]);
199 sUsageRequested = true;
200 PostMessage(B_QUIT_REQUESTED);
201 return;
204 if (fArgs->Title() != NULL)
205 fWindowTitle = fArgs->Title();
207 fStartFullscreen = fArgs->FullScreen();
211 void
212 TermApp::RefsReceived(BMessage* message)
214 // Works Only Launced by Double-Click file, or Drags file to App.
215 if (!IsLaunching())
216 return;
218 entry_ref ref;
219 if (message->FindRef("refs", 0, &ref) != B_OK)
220 return;
222 BFile file;
223 if (file.SetTo(&ref, B_READ_WRITE) != B_OK)
224 return;
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) {
233 BEntry ent(&ref);
234 BPath path(&ent);
235 PrefHandler::Default()->OpenText(path.Path());
236 return;
239 // if App opened by Shell Script
240 if (strcmp(mimetype, "text/x-haiku-shscript") == 0) {
241 // Not implemented.
242 // beep();
243 return;
248 status_t
249 TermApp::_MakeTermWindow()
251 try {
252 fTermWindow = new TermWindow(fWindowTitle, fArgs);
253 } catch (int error) {
254 return (status_t)error;
255 } catch (...) {
256 return B_ERROR;
259 fTermWindow->Show();
261 return B_OK;
265 //#ifndef B_NETPOSITIVE_APP_SIGNATURE
266 //#define B_NETPOSITIVE_APP_SIGNATURE "application/x-vnd.Be-NPOS"
267 //#endif
269 //void
270 //TermApp::ShowHTML(BMessage *msg)
272 // const char *url;
273 // msg->FindString("Url", &url);
274 // BMessage message;
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)))
281 // snooze(10000);
283 // // Activate net+
284 // be_roster->ActivateApp(be_roster->TeamFor(B_NETPOSITIVE_APP_SIGNATURE));
288 /*static*/ void
289 TermApp::_SigChildHandler(int signal, void* data)
291 fprintf(stderr, "Terminal: _SigChildHandler() called! That should never "
292 "happen!\n");
296 /*static*/ status_t
297 TermApp::_ChildCleanupThreadEntry(void* data)
299 return ((TermApp*)data)->_ChildCleanupThread();
303 status_t
304 TermApp::_ChildCleanupThread()
306 sigset_t waitForSignals;
307 sigemptyset(&waitForSignals);
308 sigaddset(&waitForSignals, SIGCHLD);
309 sigaddset(&waitForSignals, SIGUSR1);
311 for (;;) {
312 int signal;
313 int error = sigwait(&waitForSignals, &signal);
315 if (fTerminating)
316 break;
318 if (error == 0 && signal == SIGCHLD)
319 fTermWindow->PostMessage(MSG_CHECK_CHILDREN);
322 return B_OK;
326 void
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"
332 "\n"
333 "Usage: %s [OPTION] [SHELL]\n"), name);
335 fprintf(stderr,
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"
346 void
347 TermApp::_InitDefaultPalette()
349 // 0 - 15 are system ANSI colors
350 const char * keys[kANSIColorCount] = {
351 PREF_ANSI_BLACK_COLOR,
352 PREF_ANSI_RED_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);