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