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	{ 0 } // terminate list
49};
50
51
52void
53PrintServerApp::HandleScriptingCommand(BMessage* msg)
54{
55	BString propName;
56	BMessage spec;
57	int32 idx;
58
59	if (msg->GetCurrentSpecifier(&idx,&spec) == B_OK &&
60		spec.FindString("property",&propName) == B_OK) {
61		switch(msg->what) {
62			case B_GET_PROPERTY:
63				if (propName == "ActivePrinter") {
64					BMessage reply(B_REPLY);
65					reply.AddString("result", fDefaultPrinter
66						? fDefaultPrinter->Name() : "");
67					reply.AddInt32("error", B_OK);
68					msg->SendReply(&reply);
69				} else if (propName == "UseConfigWindow") {
70					BMessage reply(B_REPLY);
71					reply.AddString("result", fUseConfigWindow
72						? "true" : "false");
73					reply.AddInt32("error", B_OK);
74					msg->SendReply(&reply);
75				}
76				break;
77
78			case B_SET_PROPERTY:
79				if (propName == "ActivePrinter") {
80					BString newActivePrinter;
81					if (msg->FindString("data", &newActivePrinter) == B_OK) {
82						BMessage reply(B_REPLY);
83						reply.AddInt32("error",
84							SelectPrinter(newActivePrinter.String()));
85						msg->SendReply(&reply);
86					}
87				} else if (propName == "UseConfigWindow") {
88					bool useConfigWindow;
89					if (msg->FindBool("data", &useConfigWindow) == B_OK) {
90						fUseConfigWindow = useConfigWindow;
91						BMessage reply(B_REPLY);
92						reply.AddInt32("error", fUseConfigWindow);
93						msg->SendReply(&reply);
94					}
95				}
96				break;
97
98			case B_CREATE_PROPERTY:
99				if (propName == "Printer") {
100					BString name, driver, transport, config;
101
102					if (msg->FindString("name", &name) == B_OK
103						&& msg->FindString("driver", &driver) == B_OK
104						&& msg->FindString("transport", &transport) == B_OK
105						&& msg->FindString("config", &config) == B_OK) {
106						BMessage reply(B_REPLY);
107						reply.AddInt32("error", CreatePrinter(name.String(),
108							driver.String(), "Local", transport.String(),
109							config.String()));
110						msg->SendReply(&reply);
111					}
112				}
113				break;
114
115			case B_DELETE_PROPERTY: {
116					Printer* printer = GetPrinterFromSpecifier(&spec);
117					status_t rc = B_BAD_VALUE;
118
119					if (printer != NULL)
120						rc=printer->Remove();
121
122					BMessage reply(B_REPLY);
123					reply.AddInt32("error", rc);
124					msg->SendReply(&reply);
125				}
126				break;
127
128			case B_COUNT_PROPERTIES:
129				if (propName == "Printers") {
130					BMessage reply(B_REPLY);
131					reply.AddInt32("result", Printer::CountPrinters());
132					reply.AddInt32("error", B_OK);
133					msg->SendReply(&reply);
134				} else if (propName == "Transports") {
135					BMessage reply(B_REPLY);
136					reply.AddInt32("result", Transport::CountTransports());
137					reply.AddInt32("error", B_OK);
138					msg->SendReply(&reply);
139				}
140				break;
141		}
142	}
143}
144
145
146Printer*
147PrintServerApp::GetPrinterFromSpecifier(BMessage* msg)
148{
149	switch(msg->what) {
150		case B_NAME_SPECIFIER:
151		{
152			BString name;
153			if (msg->FindString("name", &name) == B_OK)
154				return Printer::Find(name.String());
155			break;
156		}
157
158		case B_INDEX_SPECIFIER:
159		{
160			int32 idx;
161			if (msg->FindInt32("index", &idx) == B_OK)
162				return Printer::At(idx);
163			break;
164		}
165
166		case B_REVERSE_INDEX_SPECIFIER:
167		{
168			int32 idx;
169			if (msg->FindInt32("index", &idx) == B_OK)
170				return Printer::At(Printer::CountPrinters() - idx);
171			break;
172		}
173	}
174
175	return NULL;
176}
177
178
179Transport*
180PrintServerApp::GetTransportFromSpecifier(BMessage* msg)
181{
182	switch(msg->what) {
183		case B_NAME_SPECIFIER:
184		{
185			BString name;
186			if (msg->FindString("name", &name) == B_OK)
187				return Transport::Find(name);
188			break;
189		}
190
191		case B_INDEX_SPECIFIER:
192		{
193			int32 idx;
194			if (msg->FindInt32("index", &idx) == B_OK)
195				return Transport::At(idx);
196			break;
197		}
198
199		case B_REVERSE_INDEX_SPECIFIER:
200		{
201			int32 idx;
202			if (msg->FindInt32("index", &idx) == B_OK)
203				return Transport::At(Transport::CountTransports() - idx);
204			break;
205		}
206	}
207
208	return NULL;
209}
210
211
212BHandler*
213PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
214								int32 form, const char* prop)
215{
216	BPropertyInfo prop_info(prop_list);
217	BHandler* rc = NULL;
218
219	int32 idx;
220	switch( idx=prop_info.FindMatch(msg,0,spec,form,prop) ) {
221		case B_ERROR:
222			rc = Inherited::ResolveSpecifier(msg,index,spec,form,prop);
223
224		case 1:
225			// GET Printer [arg]
226			if ((rc=GetPrinterFromSpecifier(spec)) == NULL) {
227				BMessage reply(B_REPLY);
228				reply.AddInt32("error", B_BAD_INDEX);
229				msg->SendReply(&reply);
230			}
231			else
232				msg->PopSpecifier();
233			break;
234
235		case 5:
236			// GET Transport [arg]
237			if ((rc=GetTransportFromSpecifier(spec)) == NULL) {
238				BMessage reply(B_REPLY);
239				reply.AddInt32("error", B_BAD_INDEX);
240				msg->SendReply(&reply);
241			}
242			else
243				msg->PopSpecifier();
244			break;
245
246		default:
247			rc = this;
248	}
249
250	return rc;
251}
252
253
254status_t
255PrintServerApp::GetSupportedSuites(BMessage* msg)
256{
257	msg->AddString("suites", "suite/vnd.OpenBeOS-printserver");
258
259	static bool localized = false;
260	if (!localized) {
261		localized = true;
262		for (int i = 0; prop_list[i].name != NULL; i ++)
263			prop_list[i].usage = B_TRANSLATE_NOCOLLECT(prop_list[i].usage);
264	}
265
266	BPropertyInfo prop_info(prop_list);
267	msg->AddFlat("messages", &prop_info);
268
269	return Inherited::GetSupportedSuites(msg);
270}
271