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