1/*
2 * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include "Arguments.h"
11
12extern const char *__progname;
13
14// usage
15static const char *kUsage =
16	"%s <options> [ <program> ... ]\n"
17	"Starts a terminal with a shell running in it. If <program> is given\n"
18	"and is an absolute or relative path to an executable, it is run instead\n"
19	"of the shell. The command line arguments for the program just follow the\n"
20	"path of the program.\n"
21	"\n"
22	"Options:\n"
23	"  -h, --help           - print this info text\n"
24	"  -l <x> <y>           - open the terminal window at location (<x>, <y>)\n"
25	"  -s <width> <height>  - open the terminal window with width <width> and\n"
26	"                         height <height>)\n"
27	"  -t <title>           - set the terminal window title to <title>\n";
28
29// application name
30const char *kAppName = __progname;
31
32static void
33print_usage(bool error)
34{
35	fprintf(error ? stderr : stdout, kUsage, kAppName);
36}
37
38static void
39print_usage_and_exit(bool error)
40{
41	print_usage(error);
42	exit(error ? 0 : 1);
43}
44
45Arguments::Arguments()
46	: fBounds(50, 50, 630, 435),
47	  fStandardShell(true),
48	  fShellArgumentCount(0),
49	  fShellArguments(NULL),
50	  fTitle("MiniTerminal")
51{
52	const char *argv[] = { "/bin/sh", "--login" };
53
54	_SetShellArguments(2, argv);
55}
56
57
58Arguments::~Arguments()
59{
60	_SetShellArguments(0, NULL);
61}
62
63
64void
65Arguments::Parse(int argc, const char *const *argv)
66{
67	int argi = 1;
68	while (argi < argc) {
69		const char *arg = argv[argi++];
70
71		if (*arg == '-') {
72			if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
73				print_usage_and_exit(false);
74
75			} else if (strcmp(arg, "-l") == 0) {
76				// location
77				float x, y;
78				if (argi + 1 >= argc
79					|| sscanf(argv[argi++], "%f", &x) != 1
80					|| sscanf(argv[argi++], "%f", &y) != 1) {
81					print_usage_and_exit(true);
82				}
83
84				fBounds.OffsetTo(x, y);
85
86			} else if (strcmp(arg, "-s") == 0) {
87				// size
88				float width, height;
89				if (argi + 1 >= argc
90					|| sscanf(argv[argi++], "%f", &width) != 1
91					|| sscanf(argv[argi++], "%f", &height) != 1) {
92					print_usage_and_exit(true);
93				}
94
95				fBounds.right = fBounds.left + width;
96				fBounds.bottom = fBounds.top + height;
97
98			} else if (strcmp(arg, "-t") == 0) {
99				// title
100				if (argi >= argc)
101					print_usage_and_exit(true);
102
103				fTitle = argv[argi++];
104
105			} else {
106				// illegal option
107				fprintf(stderr, "Unrecognized option \"%s\"\n", arg);
108				print_usage_and_exit(true);
109			}
110
111		} else {
112			// no option, so the remainder is the shell program with arguments
113			_SetShellArguments(argc - argi + 1, argv + argi - 1);
114			argi = argc;
115			fStandardShell = false;
116		}
117	}
118}
119
120
121void
122Arguments::GetShellArguments(int &argc, const char *const *&argv) const
123{
124	argc = fShellArgumentCount;
125	argv = fShellArguments;
126}
127
128
129void
130Arguments::_SetShellArguments(int argc, const char *const *argv)
131{
132	// delete old arguments
133	delete[] fShellArguments;
134	fShellArguments = NULL;
135	fShellArgumentCount = 0;
136
137	// copy new ones
138	if (argc > 0 && argv) {
139		fShellArguments = new const char*[argc + 1];
140		for (int i = 0; i < argc; i++)
141			fShellArguments[i] = argv[i];
142
143		fShellArguments[argc] = NULL;
144		fShellArgumentCount = argc;
145	}
146}
147
148