1/*
2 * Copyright 2002-2006, Haiku Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Mathew Hounsell
7 *		Vasilis Kaoutsis, kaoutsis@sch.gr
8 */
9
10
11#include <Alert.h>
12#include <Application.h>
13
14#include <stdio.h>
15#include <string.h>
16
17
18const char* kSignature = "application/x-vnd.Haiku.cmd-alert";
19
20const char* kButtonDefault = "OK";
21
22const int32 kErrorInitFail = 127;
23const int32 kErrorArgumentsFail = 126;
24
25
26class AlertApplication : public BApplication {
27	public:
28		AlertApplication();
29		virtual ~AlertApplication() { }
30
31		virtual void ReadyToRun();
32		virtual void ArgvReceived(int32 argc, char** argv);
33
34		bool GoodArguments() const { return fOk; }
35		int32 ChoiceNumber() const { return fChoiceNumber; }
36		char const* ChoiceText() const { return fChoiceText; }
37
38	private:
39		void _SetChoice(int32 buttonIndex);
40		void _Usage() const;
41
42	private:
43		bool fOk;
44		bool fModal;
45		alert_type fIcon;
46		char* fArgumentText;
47		char* fArgumentButton0;
48		char* fArgumentButton1;
49		char* fArgumentButton2;
50		char* fChoiceText;
51		int32 fChoiceNumber;
52};
53
54
55AlertApplication::AlertApplication()
56	: BApplication(kSignature),
57	fOk(false),
58	fModal(false),
59	fIcon(B_INFO_ALERT),
60	fArgumentText(NULL),
61	fArgumentButton0(NULL),
62	fArgumentButton1(NULL),
63	fArgumentButton2(NULL),
64	fChoiceText(NULL),
65	fChoiceNumber(0)
66{
67}
68
69
70/*!
71	Invoked when the application receives a B_ARGV_RECEIVED message.
72	The message is sent when command line arguments are used in launching the
73	app from the shell. The function isn't called if there were no command
74	line arguments.
75*/
76void
77AlertApplication::ArgvReceived(int32 argc, char** argv)
78{
79	// Now there is at least one
80	// command line argument option.
81
82	const uint32 kArgCount = argc - 1;
83	uint32 index = 1;
84	bool iconFlag = false;
85
86	// Look for valid '--' options.
87	for (; index <= kArgCount; ++index) {
88		if (argv[index][0] == '-' && argv[index][1] == '-') {
89			const char* option = argv[index] + 2;
90
91			if (!strcmp(option, "modal"))
92				fModal = true;
93			else if (!strcmp(option, "empty") && !iconFlag) {
94				fIcon = B_EMPTY_ALERT;
95				iconFlag = true;
96			} else if (!strcmp(option, "info") && !iconFlag) {
97				fIcon = B_INFO_ALERT;
98				iconFlag = true;
99			} else if (!strcmp(option, "idea") && !iconFlag) {
100				fIcon = B_IDEA_ALERT;
101				iconFlag = true;
102			} else if (!strcmp(option, "warning") && !iconFlag) {
103				fIcon = B_WARNING_ALERT;
104				iconFlag = true;
105			} else if (!strcmp(option, "stop") && !iconFlag) {
106				fIcon = B_STOP_ALERT;
107				iconFlag = true;
108			} else {
109				// Unrecognized '--' opition.
110				fprintf(stdout, "Unrecognized option %s\n", argv[index]);
111				return;
112			}
113		} else {
114			// Option doesn't start with '--'
115			break;
116		}
117
118		if (index == kArgCount) {
119			// User provides arguments that all begins with '--',
120			// so none can be considered as text argument.
121			fprintf(stdout, "Missing the text argument!\n");
122			return;
123		}
124	}
125
126	fArgumentText = strdup(argv[index]);
127		// First argument that start without --,
128		// so grub it as the text argument.
129
130	if (index == kArgCount) {
131		// No more text argument. Give Button0
132		// the default label.
133		fArgumentButton0 = strdup(kButtonDefault);
134		fOk = true;
135		return;
136	}
137
138	if (index < kArgCount) {
139		// There is another argument,
140		// so let that be the Button0 label.
141		fArgumentButton0 = strdup(argv[++index]);
142	}
143
144	if (index < kArgCount) {
145		// There is another argument,
146		// so let that be the Button1 label.
147		fArgumentButton1 = strdup(argv[++index]);
148	}
149
150	if (index < kArgCount) {
151		// There is another argument,
152		// so let that be the Button2 label.
153		fArgumentButton2 = strdup(argv[++index]);
154	}
155
156	// Ignore all other arguments if they exist,
157	// since they are useless.
158
159	fOk = true;
160}
161
162
163void
164AlertApplication::_SetChoice(int32 buttonIndex)
165{
166	fChoiceNumber = buttonIndex;
167	switch (fChoiceNumber) {
168		case 0:
169			fChoiceText = fArgumentButton0;
170			break;
171
172		case 1:
173			fChoiceText = fArgumentButton1;
174			break;
175
176		case 2:
177			fChoiceText = fArgumentButton2;
178			break;
179	}
180}
181
182
183void
184AlertApplication::_Usage() const
185{
186	fprintf(stderr,
187		"usage: alert [ <type> ] [ --modal ] [ --help ] text [ button1 [ button2 [ button3 ]]]\n"
188		"<type> is --empty | --info | --idea | --warning | --stop\n"
189		"--modal makes the alert system modal and shows it in all workspaces.\n"
190		"If any button argument is given, exit status is button number (starting with 0)\n"
191		"and 'alert' will print the title of the button pressed to stdout.\n");
192}
193
194
195/*!
196	Is called when the app receives a B_READY_TO_RUN message. The message
197	is sent automatically during the Run() function, and is sent after the
198	initial B_REFS_RECEIVED and B_ARGV_RECEIVED messages (if any) have been
199	handled.
200*/
201void
202AlertApplication::ReadyToRun()
203{
204	if (GoodArguments()) {
205		BAlert* alert = new BAlert("alert", fArgumentText,
206			fArgumentButton0, fArgumentButton1, fArgumentButton2,
207			B_WIDTH_AS_USUAL, fIcon);
208
209		if (fModal)
210			alert->SetFeel(B_MODAL_ALL_WINDOW_FEEL);
211
212		_SetChoice(alert->Go());
213	} else
214		_Usage();
215
216	Quit();
217}
218
219
220//	#pragma mark -
221
222
223int
224main(int argc, char** argv)
225{
226	AlertApplication app;
227	if (app.InitCheck() != B_OK)
228		return kErrorInitFail;
229
230	app.Run();
231	if (!app.GoodArguments())
232		return kErrorArgumentsFail;
233
234	fprintf(stdout, "%s\n", app.ChoiceText());
235	return app.ChoiceNumber();
236}
237