1#include "Mime.h"
2#include "TypeConstants.h"
3#include "Application.h"
4#include "InterfaceDefs.h"
5#include "TranslationUtils.h"
6#include "Button.h"
7#include "Errors.h"
8#include "Window.h"
9#include "Alert.h"
10#include "TextControl.h"
11#include "FindDirectory.h"
12#include "Directory.h"
13#include "Roster.h"
14#include "Bitmap.h"
15#include "OS.h"
16#include "PrintJob.h"
17
18// POSIX includes
19#include "errno.h"
20#include "malloc.h"
21#include "signal.h"
22
23#include "InstallPrinter.h"
24
25#define PRT_SERVER_SIGNATURE	"application/x-vnd.Be-PSRV"
26
27#define PRT_ATTR_MIMETYPE		"application/x-vnd.Be.printer\0"
28#define PRT_ATTR_STATE			"free\0"
29#define PRT_ATTR_TRANSPORT		"beserved\0"
30#define PRT_ATTR_TRANSPORTADDR	"local\0"
31#define PRT_ATTR_CONNECTION		"local\0"
32#define PRT_ATTR_COMMENTS		"\0"
33
34char *printerTypes[] = { "HP PCL3 LaserJet Compatible\0" };
35
36
37// ----- InstallPrinterView -----------------------------------------------------
38
39InstallPrinterView::InstallPrinterView(BRect rect, char *host, char *printer)
40	: BView(rect, "InstallPrinterView", B_FOLLOW_ALL, B_WILL_DRAW)
41{
42	strcpy(this->host, host);
43	strcpy(this->printer, printer);
44
45	rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
46	SetViewColor(gray);
47
48	BRect bmpRect(0.0, 0.0, 31.0, 31.0);
49	icon = new BBitmap(bmpRect, B_CMAP8);
50	BMimeType mime("application/x-vnd.Be.printer");
51	mime.GetIcon(icon, B_LARGE_ICON);
52
53	BRect r(55, 50, 250, 65);
54	chkDefault = new BCheckBox(r, "Default", "Make this my default printer", NULL);
55	chkDefault->SetValue(B_CONTROL_ON);
56	AddChild(chkDefault);
57
58	r.top = 70;
59	r.bottom = r.top + 20;
60	chkTestPage = new BCheckBox(r, "TestPage", "Print a test page", NULL);
61	chkTestPage->SetValue(B_CONTROL_OFF);
62	chkTestPage->SetEnabled(false);
63	AddChild(chkTestPage);
64
65	r.Set(140, 105, 260, 125);
66	BButton *okBtn = new BButton(r, "OkayBtn", "Configure Printer", new BMessage(MSG_INSTALL_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
67	okBtn->MakeDefault(true);
68	AddChild(okBtn);
69
70	r.Set(270, 105, 340, 125);
71	AddChild(new BButton(r, "CancelBtn", "Cancel", new BMessage(MSG_INSTALL_CANCEL), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM));
72}
73
74InstallPrinterView::~InstallPrinterView()
75{
76}
77
78void InstallPrinterView::Draw(BRect rect)
79{
80	BRect r = Bounds();
81	BRect iconRect(13.0, 5.0, 45.0, 37.0);
82	rgb_color black = { 0, 0, 0, 255 };
83	rgb_color gray = ui_color(B_PANEL_BACKGROUND_COLOR);
84	char msg[512];
85
86	SetViewColor(gray);
87	SetLowColor(gray);
88	FillRect(r, B_SOLID_LOW);
89
90	SetHighColor(black);
91	SetFont(be_bold_font);
92	SetFontSize(11);
93	MovePenTo(55, 15);
94	DrawString("Configure this Printer?");
95
96	sprintf(msg, "'%s' on computer '%s?'", printer, host);
97	SetFont(be_plain_font);
98	SetFontSize(10);
99	MovePenTo(55, 28);
100	DrawString("Would you like to configure your computer to print to printer");
101	MovePenTo(55, 40);
102	DrawString(msg);
103
104	SetDrawingMode(B_OP_ALPHA);
105	SetHighColor(0, 0, 0, 180);
106	SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
107	DrawBitmap(icon, iconRect);
108}
109
110
111// ----- InstallPrinterPanel ----------------------------------------------------------------------
112
113InstallPrinterPanel::InstallPrinterPanel(BRect frame, char *host, char *printer)
114	: BWindow(frame, "New Printer", B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
115{
116	cancelled = false;
117
118	BRect r = Bounds();
119	installView = new InstallPrinterView(r, host, printer);
120	AddChild(installView);
121
122	Show();
123}
124
125InstallPrinterPanel::~InstallPrinterPanel()
126{
127}
128
129// MessageReceived()
130//
131void InstallPrinterPanel::MessageReceived(BMessage *msg)
132{
133	switch (msg->what)
134	{
135		case MSG_INSTALL_OK:
136			cancelled = false;
137			defaultPrinter = installView->isDefault();
138			sendTestPage = installView->printTestPage();
139			BWindow::Quit();
140			break;
141
142		case MSG_INSTALL_CANCEL:
143			cancelled = true;
144			BWindow::Quit();
145			break;
146
147		default:
148			BWindow::MessageReceived(msg);
149			break;
150	}
151}
152
153// CreatePrinter()
154//
155bool InstallPrinterPanel::CreatePrinter(char *printer, char *host, int type, char *user, char *password)
156{
157	char path[B_PATH_NAME_LENGTH], msg[B_PATH_NAME_LENGTH + 256];
158
159	// Create the printer spooling folder.  If it cannot be created, we'll have to abort.
160	find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, sizeof(path));
161	strcat(path, "/printers/");
162	strcat(path, printer);
163	if (create_directory(path, S_IRWXU | S_IRWXG | S_IRWXO) != B_OK)
164	{
165		sprintf(msg, "A printer spooling folder, %s, could not be created.", path);
166		BAlert *alert = new BAlert("", msg, "OK");
167		alert->Go();
168		return false;
169	}
170
171	// Now set the necessary attributes for the printing system to work.  This includes
172	// standard BeOS attributes, such as BEOS:TYPE and Driver Name, but also includes those
173	// specific to BeServed, such as "server," which identifies the remote host.
174	int file = open(path, O_RDONLY);
175	if (file >= 0)
176	{
177		fs_write_attr(file, "BEOS:TYPE", B_STRING_TYPE, 0, PRT_ATTR_MIMETYPE, strlen(PRT_ATTR_MIMETYPE) + 1);
178		fs_write_attr(file, "Driver Name", B_STRING_TYPE, 0, printerTypes[type], strlen(printerTypes[type]) + 1);
179		fs_write_attr(file, "Printer Name", B_STRING_TYPE, 0, printer, strlen(printer) + 1);
180		fs_write_attr(file, "state", B_STRING_TYPE, 0, PRT_ATTR_STATE, strlen(PRT_ATTR_STATE) + 1);
181		fs_write_attr(file, "transport", B_STRING_TYPE, 0, PRT_ATTR_TRANSPORT, strlen(PRT_ATTR_TRANSPORT) + 1);
182		fs_write_attr(file, "transport_address", B_STRING_TYPE, 0, PRT_ATTR_TRANSPORTADDR, strlen(PRT_ATTR_TRANSPORTADDR) + 1);
183		fs_write_attr(file, "connection", B_STRING_TYPE, 0, PRT_ATTR_CONNECTION, strlen(PRT_ATTR_CONNECTION) + 1);
184		fs_write_attr(file, "Comments", B_STRING_TYPE, 0, PRT_ATTR_COMMENTS, strlen(PRT_ATTR_COMMENTS) + 1);
185		fs_write_attr(file, "server", B_STRING_TYPE, 0, host, strlen(host) + 1);
186		fs_write_attr(file, "user", B_STRING_TYPE, 0, user, strlen(user) + 1);
187		fs_write_attr(file, "password", B_STRING_TYPE, 0, password, BT_AUTH_TOKEN_LENGTH + 1);
188		close(file);
189	}
190
191//	if (!NotifyPrintServer(printer, type))
192		RestartPrintServer();
193
194	return true;
195}
196
197void InstallPrinterPanel::RestartPrintServer()
198{
199	app_info appInfo;
200
201	if (be_roster->GetAppInfo(PRT_SERVER_SIGNATURE, &appInfo) == B_OK)
202	{
203		int retries = 0;
204		kill(appInfo.thread, SIGTERM);
205		while (be_roster->IsRunning(PRT_SERVER_SIGNATURE) && retries++ < 5)
206			sleep(1);
207	}
208
209	be_roster->Launch(PRT_SERVER_SIGNATURE);
210}
211
212void InstallPrinterPanel::SetDefaultPrinter(char *printer)
213{
214	FILE *fp;
215	char path[B_PATH_NAME_LENGTH];
216	int i;
217
218	// Create the printer spooling folder.  If it cannot be created, we'll have to abort.
219	find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, sizeof(path));
220	strcat(path, "/printer_data");
221
222	fp = fopen(path, "wb");
223	if (fp)
224	{
225		fputs(printer, fp);
226		for (i = strlen(printer); i < 256; i++)
227			fputc('\0', fp);
228
229		fclose(fp);
230	}
231}
232
233bool InstallPrinterPanel::NotifyPrintServer(char *printer, int type)
234{
235	BMessage msg('selp');
236	BMessenger msgr;
237
238	if (!GetPrintServerMessenger(msgr))
239		return false;
240
241	msg.AddString("driver", printerTypes[type]);
242	msg.AddString("transport", PRT_ATTR_TRANSPORT);
243	msg.AddString("transport path", PRT_ATTR_TRANSPORTADDR);
244	msg.AddString("printer name", printer);
245	msg.AddString("connection", PRT_ATTR_CONNECTION);
246	msgr.SendMessage(&msg);
247	return true;
248}
249
250bool InstallPrinterPanel::GetPrintServerMessenger(BMessenger &msgr)
251{
252	if (!be_roster->IsRunning(PRT_SERVER_SIGNATURE))
253		be_roster->Launch(PRT_SERVER_SIGNATURE);
254
255	msgr = BMessenger(PRT_SERVER_SIGNATURE);
256	return msgr.IsValid();
257}
258
259
260void InstallPrinterPanel::TestPrinter(char *printer)
261{
262	char *jobName = new char [strlen(printer) + 20];
263	if (!jobName)
264		return;
265
266	sprintf(jobName, "%s Test Page", printer);
267	BPrintJob job(jobName);
268
269	if (job.ConfigPage() == B_OK)
270		if (job.ConfigJob() == B_OK)
271		{
272			BRect printableRect = job.PrintableRect();
273			BPoint startPoint(printableRect.left, printableRect.top);
274			TestPrintView *testView = new TestPrintView(printableRect);
275
276			job.BeginJob();
277			job.DrawView(testView, printableRect, startPoint);
278			job.SpoolPage();
279			job.CommitJob();
280
281			delete testView;
282		}
283
284	delete jobName;
285}
286
287// ----- TestPrintView ------------------------------------------------------------------------
288
289TestPrintView::TestPrintView(BRect rect)
290	: BView(rect, "TestPrintView", B_FOLLOW_ALL, B_WILL_DRAW)
291{
292	BMessage archive;
293	size_t size;
294	char *bits;
295
296	rgb_color white = { 255, 255, 255, 255 };
297	SetViewColor(white);
298
299//	bits = (char *) be_app->AppResources()->LoadResource(type_code('BBMP'), BMP_TESTPAGE_LOGO, &size);
300//	if (bits)
301//		if (archive.Unflatten(bits) == B_OK)
302//			beServedIcon = new BBitmap(&archive);
303}
304
305TestPrintView::~TestPrintView()
306{
307}
308
309void TestPrintView::Draw(BRect rect)
310{
311	BRect iconRect(13.0, 5.0, 45.0, 37.0);
312	rgb_color black = { 0, 0, 0, 255 };
313	rgb_color white = { 255, 255, 255, 255 };
314
315	SetViewColor(white);
316	SetLowColor(white);
317
318	SetHighColor(black);
319	SetFont(be_bold_font);
320	SetFontSize(11);
321	MovePenTo(55, 15);
322	DrawString("");
323
324	SetFont(be_plain_font);
325	SetFontSize(10);
326	MovePenTo(55, 28);
327	DrawString("This test page has been sent to your printer by request.  By reading this information, you are confirming");
328	MovePenTo(55, 40);
329	DrawString("that this printer is communicating correctly with the computer from which this test was sent.");
330
331	SetDrawingMode(B_OP_ALPHA);
332	SetHighColor(0, 0, 0, 180);
333	SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
334	DrawBitmap(beServedIcon, iconRect);
335}
336