xref: /haiku/src/apps/terminal/TermWindow.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
1 /*
2  * Copyright (c) 2003-2004 Kian Duffy <myob@users.sourceforge.net>
3  * Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
4  * Copyright (c) 2004 Daniel Furrer <assimil8or@users.sourceforge.net>
5  *
6  * Distributed unter the terms of the MIT license.
7  */
8 #include <Alert.h>
9 #include <Application.h>
10 #include <Menu.h>
11 #include <MenuBar.h>
12 #include <MenuItem.h>
13 #include <Path.h>
14 #include <PrintJob.h>
15 #include <PropertyInfo.h>
16 #include <Roster.h>
17 #include <Screen.h>
18 #include <ScrollBar.h>
19 #include <String.h>
20 #include <TextControl.h>
21 #include <WindowScreen.h>
22 
23 #include <float.h>
24 #include <stdio.h>
25 #include <string>
26 #include <sys/time.h>
27 #include <unistd.h>
28 
29 #include "CodeConv.h"
30 #include "ColorWindow.h"
31 #include "MenuUtil.h"
32 #include "FindDlg.h"
33 #include "PrefDlg.h"
34 #include "PrefView.h"
35 #include "PrefHandler.h"
36 #include "TermApp.h"
37 #include "TermBaseView.h"
38 #include "TermBuffer.h"
39 #include "TermParse.h"
40 #include "TermView.h"
41 #include "TermWindow.h"
42 #include "TermConst.h"
43 #include "spawn.h"
44 
45 
46 // Global Preference Handler
47 extern PrefHandler *gTermPref;
48 //
49 // help and GPL URL
50 //
51 //#define URL_PREFIX  "file:///boot/home/config/settings/MuTerminal/help/"
52 //#define INDEX_FILE  "/index.html"
53 //#define GPL_FILE  "/gpl.html"
54 //#define CHLP_FILE   "file:///boot/beos/documentation/Shell%20Tools/index.html"
55 
56 extern int gNowCoding;  /* defined TermParce.cpp */
57 
58 void SetCoding(int);
59 
60 
61 TermWindow::TermWindow(BRect frame, const char* title, int fd)
62 	: BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE),
63 	fPfd(fd)
64 {
65 	InitWindow();
66 
67 	fPrintSettings = NULL;
68 	fPrefWindow = NULL;
69 	fFindPanel = NULL;
70 }
71 
72 
73 TermWindow::~TermWindow()
74 {
75 	close(fPfd);
76 	delete fTermParse;
77 	delete fCodeConv;
78 	if (fPrefWindow)
79 		fPrefWindow->PostMessage(B_QUIT_REQUESTED);
80 
81 	if (fFindPanel && fFindPanel->Lock()) {
82 		fFindPanel->Quit();
83 		fFindPanel = NULL;
84 	}
85 
86 	delete fWindowUpdate;
87 }
88 
89 
90 //	#pragma mark - public methods
91 
92 
93 /** Initialize Window object. */
94 
95 void
96 TermWindow::InitWindow(void)
97 {
98 	// make menu bar
99 	SetupMenu();
100 
101 	// Setup font.
102 
103 	const char *family = gTermPref->getString(PREF_HALF_FONT_FAMILY);
104 
105 	BFont halfFont;
106 	halfFont.SetFamilyAndStyle(family, NULL);
107 	float size = gTermPref->getFloat(PREF_HALF_FONT_SIZE);
108 	if (size < 6.0f)
109 		size = 6.0f;
110 	halfFont.SetSize(size);
111 	halfFont.SetSpacing(B_FIXED_SPACING);
112 
113 	family = gTermPref->getString(PREF_FULL_FONT_FAMILY);
114 
115 	BFont fullFont;
116 	fullFont.SetFamilyAndStyle(family, NULL);
117 	size = gTermPref->getFloat(PREF_FULL_FONT_SIZE);
118 	if (size < 6.0f)
119 		size = 6.0f;
120 	fullFont.SetSize(size);
121 	fullFont.SetSpacing(B_FIXED_SPACING);
122 
123 	// Make Terminal text view.
124 
125 	BRect textframe = Bounds();
126 	textframe.top = fMenubar->Bounds().bottom + 1.0;
127 
128 	fCodeConv = new CodeConv();
129 	fTermView = new TermView(Bounds(), fCodeConv, fPfd);
130 
131 	/*
132 	 * MuTerm has two views. BaseView is window base view.
133 	 * TermView is character Terminal view on BaseView. It has paste
134 	 * on BaseView shift as VIEW_OFFSET.
135 	 */
136 	fBaseView = new TermBaseView(textframe, fTermView);
137 
138 	// Initialize TermView. (font, size and color)
139 
140 	fTermView->SetTermFont(&halfFont, &fullFont);
141 
142 	BRect rect = fTermView->SetTermSize(gTermPref->getInt32(PREF_ROWS),
143 		gTermPref->getInt32(PREF_COLS), 1);
144 
145 	int width, height;
146 	fTermView->GetFontSize(&width, &height);
147 	SetSizeLimits(MIN_COLS * width, MAX_COLS * width,
148 		MIN_COLS * height, MAX_COLS * height);
149 
150 	fTermView->SetTermColor();
151 	fBaseView->SetViewColor(gTermPref->getRGB(PREF_TEXT_BACK_COLOR));
152 
153 	// Add offset to baseview.
154 	rect.InsetBy(-VIEW_OFFSET, -VIEW_OFFSET);
155 
156 	// Resize Window
157 
158 	ResizeTo(rect.Width()+ B_V_SCROLL_BAR_WIDTH,
159 		rect.Height() + fMenubar->Bounds().Height());
160 
161 	fBaseView->ResizeTo(rect.Width(), rect.Height());
162 	fBaseView->AddChild(fTermView);
163 	fTermView->MoveBy(VIEW_OFFSET, VIEW_OFFSET);
164 
165 	// Make Scroll Bar.
166 
167 	BRect scrollRect(0, 0, B_V_SCROLL_BAR_WIDTH,
168 		rect.Height() - B_H_SCROLL_BAR_HEIGHT + 1);
169 
170 	scrollRect.OffsetBy(rect.Width() + 1, fMenubar->Bounds().Height());
171 
172 	BScrollBar *scrollBar = new BScrollBar(scrollRect, "scrollbar",
173 		fTermView, 0, 0, B_VERTICAL);
174 	fTermView->SetScrollBar(scrollBar);
175 
176 	AddChild(scrollBar);
177 	AddChild(fBaseView);
178 
179 	// Set fEditmenu's target to fTermView. (Oh!...)
180 	fEditmenu->SetTargetForItems(fTermView);
181 
182 	// Initialize TermParse
183 	gNowCoding = longname2op(gTermPref->getString(PREF_TEXT_ENCODING));
184 	fTermParse = new TermParse(fPfd, this, fTermView, fCodeConv);
185 	if (fTermParse->StartThreads() < B_OK)
186 		return;
187 
188 	// Set Coding.
189 
190 	// Init find parameters
191 	fMatchCase = false;
192 	fMatchWord = false;
193 	fFindSelection = false;
194 	fForwardSearch = false;
195 
196 	// Initialize MessageRunner.
197 	fWindowUpdate = new BMessageRunner(BMessenger(this),
198 		new BMessage (MSGRUN_WINDOW), 500000);
199 }
200 
201 
202 void
203 TermWindow::MenusBeginning(void)
204 {
205 	// Syncronize Encode Menu Pop-up menu and Preference.
206 	(fEncodingmenu->FindItem(op2longname(gNowCoding)))->SetMarked(true);
207 	BWindow::MenusBeginning();
208 }
209 
210 
211 void
212 TermWindow::SetupMenu(void)
213 {
214 	PrefHandler menuText;
215 
216 	LoadLocaleFile (&menuText);
217 
218 	// Menu bar object.
219 	fMenubar = new BMenuBar(Bounds(), "mbar");
220 
221 	// Make File Menu.
222 	fFilemenu = new BMenu("Terminal");
223 	fFilemenu->AddItem(new BMenuItem("Switch Terminals", new BMessage(MENU_SWITCH_TERM),'G'));
224 	fFilemenu->AddItem(new BMenuItem("Start New Terminal", new BMessage(MENU_NEW_TERM), 'N'));
225 	fFilemenu->AddSeparatorItem();
226 	fFilemenu->AddItem(new BMenuItem("Page Setup...", new BMessage(MENU_PAGE_SETUP)));
227 	fFilemenu->AddItem(new BMenuItem("Print", new BMessage(MENU_PRINT),'P'));
228 	fFilemenu->AddSeparatorItem();
229 	fFilemenu->AddItem(new BMenuItem("About Terminal...", new BMessage(B_ABOUT_REQUESTED)));
230 	fFilemenu->AddSeparatorItem();
231 	fFilemenu->AddItem(new BMenuItem("Quit", new BMessage(MENU_FILE_QUIT), 'Q'));
232 	fMenubar->AddItem(fFilemenu);
233 
234 	// Make Edit Menu.
235 	fEditmenu = new BMenu ("Edit");
236 	fEditmenu->AddItem (new BMenuItem ("Copy", new BMessage (B_COPY),'C'));
237 	fEditmenu->AddItem (new BMenuItem ("Paste", new BMessage (B_PASTE),'V'));
238 	fEditmenu->AddSeparatorItem ();
239 	fEditmenu->AddItem (new BMenuItem ("Select All", new BMessage (B_SELECT_ALL), 'A'));
240 	fEditmenu->AddItem (new BMenuItem ("Clear All", new BMessage (MENU_CLEAR_ALL), 'L'));
241 	fEditmenu->AddSeparatorItem ();
242 	fEditmenu->AddItem (new BMenuItem ("Find", new BMessage (MENU_FIND_STRING),'F'));
243 	fFindBackwardMenuItem = new BMenuItem ("Find Backward", new BMessage (MENU_FIND_BACKWARD), '[');
244 	fEditmenu->AddItem (fFindBackwardMenuItem);
245 	fFindBackwardMenuItem->SetEnabled(false);
246 	fFindForwardMenuItem = new BMenuItem ("Find Forward", new BMessage (MENU_FIND_FORWARD), ']');
247 	fEditmenu->AddItem (fFindForwardMenuItem);
248 	fFindForwardMenuItem->SetEnabled(false);
249 
250 
251 	fMenubar->AddItem (fEditmenu);
252 
253 	// Make Help Menu.
254 	fHelpmenu = new BMenu("Settings");
255 	fWindowSizeMenu = new BMenu("Window Size");
256 	fWindowSizeMenu->AddItem(new BMenuItem("80x24", new BMessage(EIGHTYTWENTYFOUR)));
257 	fWindowSizeMenu->AddItem(new BMenuItem("80x25", new BMessage(EIGHTYTWENTYFIVE)));
258 	fWindowSizeMenu->AddItem(new BMenuItem("80x40", new BMessage(EIGHTYFORTY)));
259 	fWindowSizeMenu->AddItem(new BMenuItem("132x24", new BMessage(ONETHREETWOTWENTYFOUR)));
260 	fWindowSizeMenu->AddItem(new BMenuItem("132x25", new BMessage(ONETHREETWOTWENTYFIVE)));
261 	fWindowSizeMenu->AddItem(new BMenuItem("Fullscreen", new BMessage(FULLSCREEN), B_ENTER));
262 
263  	// Considering we have this in the preferences window, this menu is not
264  	// needed and should not be shown if we are to not confuse the user
265 /*  fNewFontMenu = new BMenu("Font");
266 	fNewFontMenu->SetRadioMode(true);
267 		int32 numFamilies1 = count_font_families();
268 		for ( int32 i = 0; i < numFamilies1; i++ ) {
269 			font_family family;
270 			uint32 flags;
271 			if ( get_font_family(i, &family, &flags) == B_OK ) {
272 				fNewFontMenu->AddItem(item = new BMenuItem(family, new BMessage(MSG_FONT_CHANGED)));
273 			//	if (0 ==i) item->SetMarked(true);
274 			}
275 		}
276   fNewFontMenu->FindItem (gTermPref->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true);
277 */
278 
279 	fEncodingmenu = new BMenu("Font Encoding");
280 	fEncodingmenu->SetRadioMode(true);
281 	MakeEncodingMenu(fEncodingmenu, gNowCoding, true);
282 	fHelpmenu->AddItem(fWindowSizeMenu);
283 	fHelpmenu->AddItem(fEncodingmenu);
284 //  fHelpmenu->AddItem(fNewFontMenu);
285 	fHelpmenu->AddSeparatorItem();
286 	fHelpmenu->AddItem(new BMenuItem("Preferences", new BMessage(MENU_PREF_OPEN)));
287 	fHelpmenu->AddSeparatorItem();
288 	fHelpmenu->AddItem(new BMenuItem("Save as default", new BMessage(SAVE_AS_DEFAULT)));
289 	fMenubar->AddItem(fHelpmenu);
290 
291 	AddChild(fMenubar);
292 }
293 
294 
295 void
296 TermWindow::MessageReceived(BMessage *message)
297 {
298 	int32 coding_id;
299 	BRect r;
300 	BFont halfFont;
301 	BFont fullFont;
302 	bool findresult;
303 
304 	switch (message->what) {
305 		case MENU_SWITCH_TERM: {
306 			be_app->PostMessage(MENU_SWITCH_TERM);
307 			break;
308 		}
309 		case MENU_NEW_TERM: {
310 			app_info info;
311 			be_app->GetAppInfo(&info);
312 
313 			// try launching two different ways to work around possible problems
314 			if (be_roster->Launch(&info.ref)!=B_OK)
315 			be_roster->Launch(TERM_SIGNATURE);
316 			break;
317 		}
318 		case MENU_PREF_OPEN: {
319 			if (!fPrefWindow)
320 				fPrefWindow = new PrefDlg(this);
321 			else
322 				fPrefWindow->Activate();
323 			break;
324 		}
325 		case MSG_PREF_CLOSED: {
326 			fPrefWindow = NULL;
327 			break;
328 		}
329 		case MENU_FIND_STRING: {
330 			if (!fFindPanel) {
331 				BRect r = Frame();
332 				r.left += 20;
333 				r.top += 20;
334 				r.right = r.left + 260;
335 				r.bottom = r.top + 190;
336 				fFindPanel = new FindDlg(r, this, fFindString, fFindSelection, fMatchWord, fMatchCase, fForwardSearch);
337 			}
338 			else
339 				fFindPanel->Activate();
340 			break;
341 		}
342 		case MSG_FIND: {
343 			fFindPanel->PostMessage(B_QUIT_REQUESTED);
344 			message->FindBool("findselection", &fFindSelection);
345 			if (!fFindSelection)
346 				message->FindString("findstring", &fFindString);
347 			else
348 				fTermView->GetSelection(fFindString);
349 
350 			if (fFindString.Length() == 0) {
351 				BAlert *alert = new BAlert("find failed", "No search string.", "Okay", NULL,
352 					NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
353 				alert->Go();
354 				fFindBackwardMenuItem->SetEnabled(false);
355 				fFindForwardMenuItem->SetEnabled(false);
356 				break;
357 			}
358 
359 			message->FindBool("forwardsearch", &fForwardSearch);
360 			message->FindBool("matchcase", &fMatchCase);
361 			message->FindBool("matchword", &fMatchWord);
362 			findresult = fTermView->Find(fFindString, fForwardSearch, fMatchCase, fMatchWord);
363 
364 			if (!findresult) {
365 				BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL,
366 					NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
367 				alert->Go();
368 				fFindBackwardMenuItem->SetEnabled(false);
369 				fFindForwardMenuItem->SetEnabled(false);
370 				break;
371 			}
372 
373 			//Enable the menu items Find Forward and Find Backward
374 			fFindBackwardMenuItem->SetEnabled(true);
375 			fFindForwardMenuItem->SetEnabled(true);
376 			break;
377 		}
378 		case MENU_FIND_FORWARD: {
379 			findresult = fTermView->Find(fFindString, true, fMatchCase, fMatchWord);
380 			if (!findresult) {
381 				BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL,
382 					NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
383 				alert->Go();
384 			}
385 			break;
386 		}
387 		case MENU_FIND_BACKWARD: {
388 			findresult = fTermView->Find(fFindString, false, fMatchCase, fMatchWord);
389 			if (!findresult) {
390 				BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL,
391 					NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
392 				alert->Go();
393 			}
394 			break;
395 		}
396 		case MSG_FIND_CLOSED: {
397 			fFindPanel = NULL;
398 			break;
399 		}
400 		case MENU_FILE_QUIT: {
401 			be_app->PostMessage(B_QUIT_REQUESTED);
402 			break;
403 		}
404 		case MENU_ENCODING: {
405 			message->FindInt32 ("op", &coding_id);
406 			gNowCoding = coding_id;
407 			SetCoding(coding_id);
408 			break;
409 		}
410 		// Extended B_SET_PROPERTY. Dispatch this message,
411 		// Set coding ID.
412 		case B_SET_PROPERTY: {
413 			int32 i;
414 			BMessage spe;
415 			message->GetCurrentSpecifier(&i, &spe);
416 			if (!strcmp("encode", spe.FindString("property", i))){
417 				message->FindInt32 ("data",  &coding_id);
418 				gNowCoding = coding_id;
419 				SetCoding (coding_id);
420 
421 				message->SendReply(B_REPLY);
422 			} else {
423 				BWindow::MessageReceived(message);
424 			}
425 			break;
426 		}
427 
428 		// Extended B_GET_PROPERTY. Dispatch this message, reply now coding ID.
429 		case B_GET_PROPERTY: {
430 			int32 i;
431 			BMessage spe;
432 			message->GetCurrentSpecifier(&i, &spe);
433 			if (!strcmp("encode", spe.FindString("property", i))){
434 				BMessage reply(B_REPLY);
435 				reply.AddInt32("result", gNowCoding);
436 				message->SendReply(&reply);
437 			}
438 			else if (!strcmp("tty", spe.FindString("property", i))) {
439 				BMessage reply(B_REPLY);
440 				reply.AddString("result", ttyname(fPfd));
441 				message->SendReply(&reply);
442 			} else {
443 				BWindow::MessageReceived(message);
444 			}
445 			break;
446 		}
447 
448 		// Message from Preference panel.
449 		case MSG_ROWS_CHANGED:
450 		case MSG_COLS_CHANGED: {
451 			r = fTermView->SetTermSize (gTermPref->getInt32 (PREF_ROWS),
452 										gTermPref->getInt32 (PREF_COLS), 0);
453 
454 			ResizeTo (r.Width()+ B_V_SCROLL_BAR_WIDTH + VIEW_OFFSET * 2,
455 			r.Height()+fMenubar->Bounds().Height() + VIEW_OFFSET *2);
456 
457 			BPath path;
458 			if (PrefHandler::GetDefaultPath(path) == B_OK)
459 				gTermPref->SaveAsText(path.Path(), PREFFILE_MIMETYPE);
460 			break;
461 		}
462 		case MSG_HALF_FONT_CHANGED:
463 		case MSG_FULL_FONT_CHANGED:
464 		case MSG_HALF_SIZE_CHANGED:
465 		case MSG_FULL_SIZE_CHANGED: {
466 
467 			halfFont.SetFamilyAndStyle (gTermPref->getString(PREF_HALF_FONT_FAMILY),NULL);
468 			halfFont.SetSize (gTermPref->getFloat(PREF_HALF_FONT_SIZE));
469 			halfFont.SetSpacing (B_FIXED_SPACING);
470 
471 			fullFont.SetFamilyAndStyle (gTermPref->getString(PREF_FULL_FONT_FAMILY),NULL);
472 			fullFont.SetSize (gTermPref->getFloat(PREF_FULL_FONT_SIZE));
473 			fullFont.SetSpacing (B_FIXED_SPACING);
474 
475 			fTermView->SetTermFont (&halfFont, &fullFont);
476 			r = fTermView->SetTermSize (0, 0, 0);
477 
478 			int width, height;
479 
480 			fTermView->GetFontSize (&width, &height);
481 
482 			SetSizeLimits (MIN_COLS * width, MAX_COLS * width,
483 							MIN_COLS * height, MAX_COLS * height);
484 
485 			ResizeTo (r.Width()+ B_V_SCROLL_BAR_WIDTH + VIEW_OFFSET * 2,
486 			r.Height()+fMenubar->Bounds().Height() + VIEW_OFFSET * 2);
487 
488 			fTermView->Invalidate();
489 		    break;
490 		}
491 		case EIGHTYTWENTYFOUR: {
492 			gTermPref->setString(PREF_COLS, "80");
493 			gTermPref->setString(PREF_ROWS, "24");
494 		   	this->PostMessage (MSG_ROWS_CHANGED);
495 			this->PostMessage (MSG_COLS_CHANGED);
496 			break;
497 		}
498 		case EIGHTYTWENTYFIVE: {
499 			gTermPref->setString(PREF_COLS, "80");
500 			gTermPref->setString(PREF_ROWS, "25");
501 		   	this->PostMessage (MSG_ROWS_CHANGED);
502 		   	this->PostMessage (MSG_COLS_CHANGED);
503 			break;
504 		}
505 		case EIGHTYFORTY: {
506 			gTermPref->setString(PREF_COLS, "80");
507 			gTermPref->setString(PREF_ROWS, "40");
508 		   	this->PostMessage (MSG_ROWS_CHANGED);
509 		   	this->PostMessage (MSG_COLS_CHANGED);
510 			break;
511 		}
512 		case ONETHREETWOTWENTYFOUR: {
513 			gTermPref->setString(PREF_COLS, "132");
514 			gTermPref->setString(PREF_ROWS, "24");
515 		   	this->PostMessage (MSG_ROWS_CHANGED);
516 		   	this->PostMessage (MSG_COLS_CHANGED);
517 			break;
518 		}
519 		case ONETHREETWOTWENTYFIVE: {
520 			gTermPref->setString(PREF_COLS, "132");
521 			gTermPref->setString(PREF_ROWS, "25");
522 		   	this->PostMessage (MSG_ROWS_CHANGED);
523 		   	this->PostMessage (MSG_COLS_CHANGED);
524 			break;
525 		}
526 		case FULLSCREEN: {
527 			if (!fSavedFrame.IsValid()) { // go fullscreen
528 				float mbHeight = fMenubar->Bounds().Height() + 1;
529 				fSavedFrame = Frame();
530 				BScreen screen(this);
531 				fTermView->ScrollBar()->Hide();
532 				fMenubar->Hide();
533 				fBaseView->MoveTo(0,0);
534 				fBaseView->ResizeBy(B_V_SCROLL_BAR_WIDTH, mbHeight);
535 				fSavedLook = Look();
536 				// done before ResizeTo to work around a Dano bug (not erasing the decor)
537 				SetLook(B_NO_BORDER_WINDOW_LOOK);
538 				ResizeTo(screen.Frame().Width()+1, screen.Frame().Height()+1);
539 				MoveTo(screen.Frame().left, screen.Frame().top);
540 			} else { // exit fullscreen
541 				float mbHeight = fMenubar->Bounds().Height() + 1;
542 				fMenubar->Show();
543 				fTermView->ScrollBar()->Show();
544 				ResizeTo(fSavedFrame.Width(), fSavedFrame.Height());
545 				MoveTo(fSavedFrame.left, fSavedFrame.top);
546 				fBaseView->ResizeBy(-B_V_SCROLL_BAR_WIDTH, -mbHeight);
547 				fBaseView->MoveTo(0,mbHeight);
548 				SetLook(fSavedLook);
549 				fSavedFrame = BRect(0,0,-1,-1);
550 			}
551 			break;
552 		}
553 		case MSG_FONT_CHANGED: {
554 	    	gTermPref->setString (PREF_HALF_FONT_FAMILY, fNewFontMenu->FindMarked()->Label());
555 	    	this->PostMessage (MSG_HALF_FONT_CHANGED);
556 		    break;
557 		}
558 		case MSG_COLOR_CHANGED: {
559 			fBaseView->SetViewColor (gTermPref->getRGB (PREF_TEXT_BACK_COLOR));
560 			fTermView->SetTermColor ();
561 			fBaseView->Invalidate();
562 			fTermView->Invalidate();
563 			break;
564 		}
565 		case SAVE_AS_DEFAULT: {
566 			BPath path;
567 			if (PrefHandler::GetDefaultPath(path) == B_OK)
568 				gTermPref->SaveAsText(path.Path(), PREFFILE_MIMETYPE);
569 			break;
570 		}
571 		case MENU_PAGE_SETUP: {
572 			DoPageSetup ();
573 			break;
574 		}
575 		case MENU_PRINT: {
576 			DoPrint ();
577 			break;
578 		}
579 		case MSGRUN_WINDOW: {
580 			fTermView->UpdateSIGWINCH ();
581 			break;
582 		}
583 		case B_ABOUT_REQUESTED: {
584 			be_app->PostMessage(B_ABOUT_REQUESTED);
585 			break;
586 		}
587 		default: {
588 			BWindow::MessageReceived(message);
589 			break;
590 		}
591 	}
592 }
593 ////////////////////////////////////////////////////////////////////////////
594 // WindowActivated (bool)
595 //  Dispatch Mesasge.
596 ////////////////////////////////////////////////////////////////////////////
597 void
598 TermWindow::WindowActivated (bool )
599 {
600 
601 }
602 
603 ////////////////////////////////////////////////////////////////////////////
604 // Quit (void)
605 //  Quit Application.
606 ////////////////////////////////////////////////////////////////////////////
607 //void
608 //TermWindow::colRequested() {
609 //	colWindow *colW=new colWindow("Colours for Terminal");
610 //	colW->Show();
611 //	}
612 
613 
614 void
615 TermWindow::Quit()
616 {
617 	BWindow::Quit();
618 }
619 
620 
621 bool
622 TermWindow::QuitRequested(void)
623 {
624 	return BWindow::QuitRequested();
625 }
626 
627 
628 ////////////////////////////////////////////////////////////////////////////
629 // int GetTimeZone (void)
630 //  Get Machine Timezone.
631 ////////////////////////////////////////////////////////////////////////////
632 int
633 TermWindow::GetTimeZone()
634 {
635 	struct timeval tv;
636 	struct timezone tm;
637 
638 	gettimeofday (&tv, &tm);
639 
640 	return -tm.tz_minuteswest / 60;
641 }
642 
643 
644 void
645 TermWindow::TermWinActivate()
646 {
647 	Activate();
648 
649 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
650 	if (focus_follows_mouse()) {
651 		BPoint aMouseLoc = Frame().LeftTop();
652 		set_mouse_position(int32(aMouseLoc.x + 16), int32(aMouseLoc.y + 2));
653 		be_app->SetCursor(B_HAND_CURSOR);
654 	}
655 #endif
656 }
657 
658 
659 status_t
660 TermWindow::GetSupportedSuites(BMessage *msg)
661 {
662   static property_info prop_list[] = {
663      { "encode",
664        {B_GET_PROPERTY, 0},
665        {B_DIRECT_SPECIFIER, 0},
666        "get muterminal encode"},
667      { "encode",
668        {B_SET_PROPERTY, 0},
669        {B_DIRECT_SPECIFIER, 0},
670        "set muterminal encode"},
671      { "tty",
672        {B_GET_PROPERTY, 0},
673        {B_DIRECT_SPECIFIER, 0},
674        "get tty_name."},
675      { 0  }
676 
677   };
678   msg->AddString("suites", "suite/vnd.naan-termwindow");
679   BPropertyInfo prop_info(prop_list);
680   msg->AddFlat("messages", &prop_info);
681   return BWindow::GetSupportedSuites(msg);
682 }
683 ////////////////////////////////////////////////////////////////////////////
684 // ResolveSpecifier
685 //
686 ////////////////////////////////////////////////////////////////////////////
687 BHandler*
688 TermWindow::ResolveSpecifier(BMessage *msg, int32 index,
689            BMessage *specifier, int32 form,
690            const char *property)
691 {
692   if ( (strcmp(property, "encode") == 0)
693     && ((msg->what == B_SET_PROPERTY) || (msg->what == B_GET_PROPERTY) ))
694       return this;
695   else if ( (strcmp(property, "tty") == 0)
696     &&  (msg->what == B_GET_PROPERTY) )
697       return this;
698 
699   return BWindow::ResolveSpecifier(msg, index, specifier, form, property);
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////
703 // SetCoding
704 //  Set coding utility functions.
705 ////////////////////////////////////////////////////////////////////////////
706 void SetCoding (int coding)
707 {
708   const etable *p = encoding_table;
709   p += coding;
710 
711   gNowCoding = coding;
712 
713   return;
714 }
715 ////////////////////////////////////////////////////////////////////////////
716 // DoPageSetUp ()
717 //
718 ////////////////////////////////////////////////////////////////////////////
719 status_t
720 TermWindow::DoPageSetup()
721 {
722   status_t rv;
723   BPrintJob job("PageSetup");
724 
725   /* display the page configure panel */
726   rv = job.ConfigPage();
727 
728   /* save a pointer to the settings */
729   fPrintSettings = job.Settings();
730 
731   return rv;
732 }
733 
734 ////////////////////////////////////////////////////////////////////////////
735 // DoPrint ()
736 //
737 ////////////////////////////////////////////////////////////////////////////
738 void
739 TermWindow::DoPrint()
740 {
741 //#if B_BEOS_VERSION < 0x0460
742   BPrintJob job("Print");
743 
744   if((! fPrintSettings) || (DoPageSetup() != B_NO_ERROR)) {
745     (new BAlert("Cancel", "Print cancelled.", "OK"))->Go();
746   return;
747   }
748 
749   job.SetSettings(new BMessage(*fPrintSettings));
750 
751   BRect pageRect = job.PrintableRect();
752   BRect curPageRect = pageRect;
753 
754   int pHeight = (int)pageRect.Height();
755   int pWidth = (int)pageRect.Width();
756   float w,h;
757   fTermView->GetFrameSize (&w, &h);
758   int xPages = (int)ceil(w / pWidth);
759   int yPages = (int)ceil(h / pHeight);
760 
761    /* engage the print server */
762   job.BeginJob();
763 
764   /* loop through and draw each page, and write to spool */
765   for(int x = 0; x < xPages; x++)
766     for(int y = 0; y < yPages; y++){
767       curPageRect.OffsetTo(x * pWidth, y * pHeight);
768       job.DrawView(fTermView, curPageRect, BPoint(0, 0));
769       job.SpoolPage();
770 
771       if(!job.CanContinue()){
772       	  // It is likely that the only way that the job was cancelled is
773       	  // because the user hit 'Cancel' in the page setup window, in which
774       	  // case, the user does *not* need to be told that it was cancelled.
775       	  // He/she will simply expect that it was done.
776 //        (new BAlert("Cancel", "Print job cancelled", "OK"))->Go();
777         return;
778       }
779   }
780 
781   /* commit the job, send the spool file */
782   job.CommitJob();
783 //#endif
784 }
785 
786 
787 
788