1/*
2 * Copyright 2001-2006, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ithamar R. Adema
7 */
8
9
10#include "PrintServerApp.h"
11
12#include <stdio.h>
13
14#include <Catalog.h>
15#include <Locale.h>
16#include <PropertyInfo.h>
17
18#include "Transport.h"
19#include "Printer.h"
20
21
22#undef B_TRANSLATION_CONTEXT
23#define B_TRANSLATION_CONTEXT "PrintServerApp Scripting"
24
25
26static property_info prop_list[] = {
27	{ "ActivePrinter", { B_GET_PROPERTY, B_SET_PROPERTY },
28		{ B_DIRECT_SPECIFIER },
29		B_TRANSLATE_MARK("Retrieve or select the active printer") },
30	{ "Printer", { B_GET_PROPERTY }, { B_INDEX_SPECIFIER, B_NAME_SPECIFIER,
31		B_REVERSE_INDEX_SPECIFIER },
32		B_TRANSLATE_MARK("Retrieve a specific printer") },
33	{ "Printer", { B_CREATE_PROPERTY }, { B_DIRECT_SPECIFIER },
34		B_TRANSLATE_MARK("Create a new printer") },
35	{ "Printer", { B_DELETE_PROPERTY }, { B_INDEX_SPECIFIER, B_NAME_SPECIFIER,
36		B_REVERSE_INDEX_SPECIFIER },
37		B_TRANSLATE_MARK("Delete a specific printer") },
38	{ "Printers", { B_COUNT_PROPERTIES }, { B_DIRECT_SPECIFIER },
39		B_TRANSLATE_MARK("Return the number of available printers") },
40	{ "Transport", { B_GET_PROPERTY }, { B_INDEX_SPECIFIER, B_NAME_SPECIFIER,
41		B_REVERSE_INDEX_SPECIFIER },
42		B_TRANSLATE_MARK("Retrieve a specific transport") },
43	{ "Transports", { B_COUNT_PROPERTIES }, { B_DIRECT_SPECIFIER },
44		B_TRANSLATE_MARK("Return the number of available transports") },
45	{ "UseConfigWindow", { B_GET_PROPERTY, B_SET_PROPERTY },
46		{ B_DIRECT_SPECIFIER },
47		B_TRANSLATE_MARK("Show configuration window") },
48
49	{ 0 } // terminate list
50};
51
52
53void
54PrintServerApp::HandleScriptingCommand(BMessage* msg)
55{
56	BString propName;
57	BMessage spec;
58	int32 idx;
59
60	if (msg->GetCurrentSpecifier(&idx,&spec) == B_OK &&
61		spec.FindString("property",&propName) == B_OK) {
62		switch(msg->what) {
63			case B_GET_PROPERTY:
64				if (propName == "ActivePrinter") {
65					BMessage reply(B_REPLY);
66					reply.AddString("result", fDefaultPrinter
67						? fDefaultPrinter->Name() : "");
68					reply.AddInt32("error", B_OK);
69					msg->SendReply(&reply);
70				} else if (propName == "UseConfigWindow") {
71					BMessage reply(B_REPLY);
72					reply.AddString("result", fUseConfigWindow
73						? "true" : "false");
74					reply.AddInt32("error", B_OK);
75					msg->SendReply(&reply);
76				}
77				break;
78
79			case B_SET_PROPERTY:
80				if (propName == "ActivePrinter") {
81					BString newActivePrinter;
82					if (msg->FindString("data", &newActivePrinter) == B_OK) {
83						BMessage reply(B_REPLY);
84						reply.AddInt32("error",
85							SelectPrinter(newActivePrinter.String()));
86						msg->SendReply(&reply);
87					}
88				} else if (propName == "UseConfigWindow") {
89					bool useConfigWindow;
90					if (msg->FindBool("data", &useConfigWindow) == B_OK) {
91						fUseConfigWindow = useConfigWindow;
92						BMessage reply(B_REPLY);
93						reply.AddInt32("error", fUseConfigWindow);
94						msg->SendReply(&reply);
95					}
96				}
97				break;
98
99			case B_CREATE_PROPERTY:
100				if (propName == "Printer") {
101					BString name, driver, transport, config;
102
103					if (msg->FindString("name", &name) == B_OK
104						&& msg->FindString("driver", &driver) == B_OK
105						&& msg->FindString("transport", &transport) == B_OK
106						&& msg->FindString("config", &config) == B_OK) {
107						BMessage reply(B_REPLY);
108						reply.AddInt32("error", CreatePrinter(name.String(),
109							driver.String(), "Local", transport.String(),
110							config.String()));
111						msg->SendReply(&reply);
112					}
113				}
114				break;
115
116			case B_DELETE_PROPERTY: {
117					Printer* printer = GetPrinterFromSpecifier(&spec);
118					status_t rc = B_BAD_VALUE;
119
120					if (printer != NULL)
121						rc=printer->Remove();
122
123					BMessage reply(B_REPLY);
124					reply.AddInt32("error", rc);
125					msg->SendReply(&reply);
126				}
127				break;
128
129			case B_COUNT_PROPERTIES:
130				if (propName == "Printers") {
131					BMessage reply(B_REPLY);
132					reply.AddInt32("result", Printer::CountPrinters());
133					reply.AddInt32("error", B_OK);
134					msg->SendReply(&reply);
135				} else if (propName == "Transports") {
136					BMessage reply(B_REPLY);
137					reply.AddInt32("result", Transport::CountTransports());
138					reply.AddInt32("error", B_OK);
139					msg->SendReply(&reply);
140				}
141				break;
142		}
143	}
144}
145
146
147Printer*
148PrintServerApp::GetPrinterFromSpecifier(BMessage* msg)
149{
150	switch(msg->what) {
151		case B_NAME_SPECIFIER:
152		{
153			BString name;
154			if (msg->FindString("name", &name) == B_OK)
155				return Printer::Find(name.String());
156			break;
157		}
158
159		case B_INDEX_SPECIFIER:
160		{
161			int32 idx;
162			if (msg->FindInt32("index", &idx) == B_OK)
163				return Printer::At(idx);
164			break;
165		}
166
167		case B_REVERSE_INDEX_SPECIFIER:
168		{
169			int32 idx;
170			if (msg->FindInt32("index", &idx) == B_OK)
171				return Printer::At(Printer::CountPrinters() - idx);
172			break;
173		}
174	}
175
176	return NULL;
177}
178
179
180Transport*
181PrintServerApp::GetTransportFromSpecifier(BMessage* msg)
182{
183	switch(msg->what) {
184		case B_NAME_SPECIFIER:
185		{
186			BString name;
187			if (msg->FindString("name", &name) == B_OK)
188				return Transport::Find(name);
189			break;
190		}
191
192		case B_INDEX_SPECIFIER:
193		{
194			int32 idx;
195			if (msg->FindInt32("index", &idx) == B_OK)
196				return Transport::At(idx);
197			break;
198		}
199
200		case B_REVERSE_INDEX_SPECIFIER:
201		{
202			int32 idx;
203			if (msg->FindInt32("index", &idx) == B_OK)
204				return Transport::At(Transport::CountTransports() - idx);
205			break;
206		}
207	}
208
209	return NULL;
210}
211
212
213BHandler*
214PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
215								int32 form, const char* prop)
216{
217	BPropertyInfo prop_info(prop_list);
218	BHandler* rc = NULL;
219
220	int32 idx;
221	switch( idx=prop_info.FindMatch(msg,0,spec,form,prop) ) {
222		case B_ERROR:
223			rc = Inherited::ResolveSpecifier(msg,index,spec,form,prop);
224			break;
225
226		case 1:
227			// GET Printer [arg]
228			if ((rc=GetPrinterFromSpecifier(spec)) == NULL) {
229				BMessage reply(B_REPLY);
230				reply.AddInt32("error", B_BAD_INDEX);
231				msg->SendReply(&reply);
232			}
233			else
234				msg->PopSpecifier();
235			break;
236
237		case 5:
238			// GET Transport [arg]
239			if ((rc=GetTransportFromSpecifier(spec)) == NULL) {
240				BMessage reply(B_REPLY);
241				reply.AddInt32("error", B_BAD_INDEX);
242				msg->SendReply(&reply);
243			}
244			else
245				msg->PopSpecifier();
246			break;
247
248		default:
249			rc = this;
250	}
251
252	return rc;
253}
254
255
256status_t
257PrintServerApp::GetSupportedSuites(BMessage* msg)
258{
259	msg->AddString("suites", "suite/vnd.OpenBeOS-printserver");
260
261	static bool localized = false;
262	if (!localized) {
263		localized = true;
264		for (int i = 0; prop_list[i].name != NULL; i ++)
265			prop_list[i].usage = B_TRANSLATE_NOCOLLECT(prop_list[i].usage);
266	}
267
268	BPropertyInfo prop_info(prop_list);
269	msg->AddFlat("messages", &prop_info);
270
271	return Inherited::GetSupportedSuites(msg);
272}
273