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 "FindWindow.h" 33 #include "PrefWindow.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(B_QUIT_REQUESTED), '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 fMenubar->AddItem (fEditmenu); 251 252 // Make Help Menu. 253 fHelpmenu = new BMenu("Settings"); 254 fWindowSizeMenu = new BMenu("Window Size"); 255 fWindowSizeMenu->AddItem(new BMenuItem("80x24", new BMessage(EIGHTYTWENTYFOUR))); 256 fWindowSizeMenu->AddItem(new BMenuItem("80x25", new BMessage(EIGHTYTWENTYFIVE))); 257 fWindowSizeMenu->AddItem(new BMenuItem("80x40", new BMessage(EIGHTYFORTY))); 258 fWindowSizeMenu->AddItem(new BMenuItem("132x24", new BMessage(ONETHREETWOTWENTYFOUR))); 259 fWindowSizeMenu->AddItem(new BMenuItem("132x25", new BMessage(ONETHREETWOTWENTYFIVE))); 260 fWindowSizeMenu->AddItem(new BMenuItem("Fullscreen", new BMessage(FULLSCREEN), B_ENTER)); 261 262 // Considering we have this in the preferences window, this menu is not 263 // needed and should not be shown if we are to not confuse the user 264 /* fNewFontMenu = new BMenu("Font"); 265 fNewFontMenu->SetRadioMode(true); 266 int32 numFamilies1 = count_font_families(); 267 for ( int32 i = 0; i < numFamilies1; i++ ) { 268 font_family family; 269 uint32 flags; 270 if ( get_font_family(i, &family, &flags) == B_OK ) { 271 fNewFontMenu->AddItem(item = new BMenuItem(family, new BMessage(MSG_FONT_CHANGED))); 272 // if (0 ==i) item->SetMarked(true); 273 } 274 } 275 fNewFontMenu->FindItem (gTermPref->getString(PREF_HALF_FONT_FAMILY))->SetMarked(true); 276 */ 277 278 fEncodingmenu = new BMenu("Font Encoding"); 279 fEncodingmenu->SetRadioMode(true); 280 MakeEncodingMenu(fEncodingmenu, gNowCoding, true); 281 fHelpmenu->AddItem(fWindowSizeMenu); 282 fHelpmenu->AddItem(fEncodingmenu); 283 // fHelpmenu->AddItem(fNewFontMenu); 284 fHelpmenu->AddSeparatorItem(); 285 fHelpmenu->AddItem(new BMenuItem("Preferences", new BMessage(MENU_PREF_OPEN))); 286 fHelpmenu->AddSeparatorItem(); 287 fHelpmenu->AddItem(new BMenuItem("Save as default", new BMessage(SAVE_AS_DEFAULT))); 288 fMenubar->AddItem(fHelpmenu); 289 290 AddChild(fMenubar); 291 } 292 293 294 void 295 TermWindow::MessageReceived(BMessage *message) 296 { 297 int32 coding_id; 298 BRect r; 299 BFont halfFont; 300 BFont fullFont; 301 bool findresult; 302 303 switch (message->what) { 304 case MENU_SWITCH_TERM: { 305 be_app->PostMessage(MENU_SWITCH_TERM); 306 break; 307 } 308 case MENU_NEW_TERM: { 309 app_info info; 310 be_app->GetAppInfo(&info); 311 312 // try launching two different ways to work around possible problems 313 if (be_roster->Launch(&info.ref)!=B_OK) 314 be_roster->Launch(TERM_SIGNATURE); 315 break; 316 } 317 case MENU_PREF_OPEN: { 318 if (!fPrefWindow) 319 fPrefWindow = new PrefWindow(this); 320 else 321 fPrefWindow->Activate(); 322 break; 323 } 324 case MSG_PREF_CLOSED: { 325 fPrefWindow = NULL; 326 break; 327 } 328 case MENU_FIND_STRING: { 329 if (!fFindPanel) { 330 BRect r = Frame(); 331 r.left += 20; 332 r.top += 20; 333 r.right = r.left + 260; 334 r.bottom = r.top + 190; 335 fFindPanel = new FindWindow(r, this, fFindString, fFindSelection, fMatchWord, fMatchCase, fForwardSearch); 336 } 337 else 338 fFindPanel->Activate(); 339 break; 340 } 341 case MSG_FIND: { 342 fFindPanel->PostMessage(B_QUIT_REQUESTED); 343 message->FindBool("findselection", &fFindSelection); 344 if (!fFindSelection) 345 message->FindString("findstring", &fFindString); 346 else 347 fTermView->GetSelection(fFindString); 348 349 if (fFindString.Length() == 0) { 350 BAlert *alert = new BAlert("find failed", "No search string.", "Okay", NULL, 351 NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 352 alert->Go(); 353 fFindBackwardMenuItem->SetEnabled(false); 354 fFindForwardMenuItem->SetEnabled(false); 355 break; 356 } 357 358 message->FindBool("forwardsearch", &fForwardSearch); 359 message->FindBool("matchcase", &fMatchCase); 360 message->FindBool("matchword", &fMatchWord); 361 findresult = fTermView->Find(fFindString, fForwardSearch, fMatchCase, fMatchWord); 362 363 if (!findresult) { 364 BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL, 365 NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 366 alert->Go(); 367 fFindBackwardMenuItem->SetEnabled(false); 368 fFindForwardMenuItem->SetEnabled(false); 369 break; 370 } 371 372 // Enable the menu items Find Forward and Find Backward 373 fFindBackwardMenuItem->SetEnabled(true); 374 fFindForwardMenuItem->SetEnabled(true); 375 break; 376 } 377 case MENU_FIND_FORWARD: { 378 findresult = fTermView->Find(fFindString, true, fMatchCase, fMatchWord); 379 if (!findresult) { 380 BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL, 381 NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 382 alert->Go(); 383 } 384 break; 385 } 386 case MENU_FIND_BACKWARD: { 387 findresult = fTermView->Find(fFindString, false, fMatchCase, fMatchWord); 388 if (!findresult) { 389 BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL, 390 NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 391 alert->Go(); 392 } 393 break; 394 } 395 case MSG_FIND_CLOSED: 396 fFindPanel = NULL; 397 break; 398 399 case MENU_ENCODING: { 400 message->FindInt32 ("op", &coding_id); 401 gNowCoding = coding_id; 402 SetCoding(coding_id); 403 break; 404 } 405 // Extended B_SET_PROPERTY. Dispatch this message, 406 // Set coding ID. 407 case B_SET_PROPERTY: { 408 int32 i; 409 BMessage spe; 410 message->GetCurrentSpecifier(&i, &spe); 411 if (!strcmp("encode", spe.FindString("property", i))){ 412 message->FindInt32 ("data", &coding_id); 413 gNowCoding = coding_id; 414 SetCoding (coding_id); 415 416 message->SendReply(B_REPLY); 417 } else { 418 BWindow::MessageReceived(message); 419 } 420 break; 421 } 422 423 // Extended B_GET_PROPERTY. Dispatch this message, reply now coding ID. 424 case B_GET_PROPERTY: { 425 int32 i; 426 BMessage spe; 427 message->GetCurrentSpecifier(&i, &spe); 428 if (!strcmp("encode", spe.FindString("property", i))){ 429 BMessage reply(B_REPLY); 430 reply.AddInt32("result", gNowCoding); 431 message->SendReply(&reply); 432 } 433 else if (!strcmp("tty", spe.FindString("property", i))) { 434 BMessage reply(B_REPLY); 435 reply.AddString("result", ttyname(fPfd)); 436 message->SendReply(&reply); 437 } else { 438 BWindow::MessageReceived(message); 439 } 440 break; 441 } 442 443 // Message from Preference panel. 444 case MSG_ROWS_CHANGED: 445 case MSG_COLS_CHANGED: { 446 r = fTermView->SetTermSize (gTermPref->getInt32 (PREF_ROWS), 447 gTermPref->getInt32 (PREF_COLS), 0); 448 449 ResizeTo (r.Width()+ B_V_SCROLL_BAR_WIDTH + VIEW_OFFSET * 2, 450 r.Height()+fMenubar->Bounds().Height() + VIEW_OFFSET *2); 451 452 BPath path; 453 if (PrefHandler::GetDefaultPath(path) == B_OK) 454 gTermPref->SaveAsText(path.Path(), PREFFILE_MIMETYPE); 455 break; 456 } 457 case MSG_HALF_FONT_CHANGED: 458 case MSG_FULL_FONT_CHANGED: 459 case MSG_HALF_SIZE_CHANGED: 460 case MSG_FULL_SIZE_CHANGED: { 461 462 halfFont.SetFamilyAndStyle (gTermPref->getString(PREF_HALF_FONT_FAMILY),NULL); 463 halfFont.SetSize (gTermPref->getFloat(PREF_HALF_FONT_SIZE)); 464 halfFont.SetSpacing (B_FIXED_SPACING); 465 466 fullFont.SetFamilyAndStyle (gTermPref->getString(PREF_FULL_FONT_FAMILY),NULL); 467 fullFont.SetSize (gTermPref->getFloat(PREF_FULL_FONT_SIZE)); 468 fullFont.SetSpacing (B_FIXED_SPACING); 469 470 fTermView->SetTermFont (&halfFont, &fullFont); 471 r = fTermView->SetTermSize (0, 0, 0); 472 473 int width, height; 474 475 fTermView->GetFontSize (&width, &height); 476 477 SetSizeLimits (MIN_COLS * width, MAX_COLS * width, 478 MIN_COLS * height, MAX_COLS * height); 479 480 ResizeTo (r.Width()+ B_V_SCROLL_BAR_WIDTH + VIEW_OFFSET * 2, 481 r.Height()+fMenubar->Bounds().Height() + VIEW_OFFSET * 2); 482 483 fTermView->Invalidate(); 484 break; 485 } 486 case EIGHTYTWENTYFOUR: { 487 gTermPref->setString(PREF_COLS, "80"); 488 gTermPref->setString(PREF_ROWS, "24"); 489 this->PostMessage (MSG_ROWS_CHANGED); 490 this->PostMessage (MSG_COLS_CHANGED); 491 break; 492 } 493 case EIGHTYTWENTYFIVE: { 494 gTermPref->setString(PREF_COLS, "80"); 495 gTermPref->setString(PREF_ROWS, "25"); 496 this->PostMessage (MSG_ROWS_CHANGED); 497 this->PostMessage (MSG_COLS_CHANGED); 498 break; 499 } 500 case EIGHTYFORTY: { 501 gTermPref->setString(PREF_COLS, "80"); 502 gTermPref->setString(PREF_ROWS, "40"); 503 this->PostMessage (MSG_ROWS_CHANGED); 504 this->PostMessage (MSG_COLS_CHANGED); 505 break; 506 } 507 case ONETHREETWOTWENTYFOUR: { 508 gTermPref->setString(PREF_COLS, "132"); 509 gTermPref->setString(PREF_ROWS, "24"); 510 this->PostMessage (MSG_ROWS_CHANGED); 511 this->PostMessage (MSG_COLS_CHANGED); 512 break; 513 } 514 case ONETHREETWOTWENTYFIVE: { 515 gTermPref->setString(PREF_COLS, "132"); 516 gTermPref->setString(PREF_ROWS, "25"); 517 this->PostMessage (MSG_ROWS_CHANGED); 518 this->PostMessage (MSG_COLS_CHANGED); 519 break; 520 } 521 case FULLSCREEN: { 522 if (!fSavedFrame.IsValid()) { // go fullscreen 523 float mbHeight = fMenubar->Bounds().Height() + 1; 524 fSavedFrame = Frame(); 525 BScreen screen(this); 526 fTermView->ScrollBar()->Hide(); 527 fMenubar->Hide(); 528 fBaseView->MoveTo(0,0); 529 fBaseView->ResizeBy(B_V_SCROLL_BAR_WIDTH, mbHeight); 530 fSavedLook = Look(); 531 // done before ResizeTo to work around a Dano bug (not erasing the decor) 532 SetLook(B_NO_BORDER_WINDOW_LOOK); 533 ResizeTo(screen.Frame().Width()+1, screen.Frame().Height()+1); 534 MoveTo(screen.Frame().left, screen.Frame().top); 535 } else { // exit fullscreen 536 float mbHeight = fMenubar->Bounds().Height() + 1; 537 fMenubar->Show(); 538 fTermView->ScrollBar()->Show(); 539 ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 540 MoveTo(fSavedFrame.left, fSavedFrame.top); 541 fBaseView->ResizeBy(-B_V_SCROLL_BAR_WIDTH, -mbHeight); 542 fBaseView->MoveTo(0,mbHeight); 543 SetLook(fSavedLook); 544 fSavedFrame = BRect(0,0,-1,-1); 545 } 546 break; 547 } 548 case MSG_FONT_CHANGED: { 549 gTermPref->setString (PREF_HALF_FONT_FAMILY, fNewFontMenu->FindMarked()->Label()); 550 this->PostMessage (MSG_HALF_FONT_CHANGED); 551 break; 552 } 553 case MSG_COLOR_CHANGED: { 554 fBaseView->SetViewColor (gTermPref->getRGB (PREF_TEXT_BACK_COLOR)); 555 fTermView->SetTermColor (); 556 fBaseView->Invalidate(); 557 fTermView->Invalidate(); 558 break; 559 } 560 case SAVE_AS_DEFAULT: { 561 BPath path; 562 if (PrefHandler::GetDefaultPath(path) == B_OK) 563 gTermPref->SaveAsText(path.Path(), PREFFILE_MIMETYPE); 564 break; 565 } 566 case MENU_PAGE_SETUP: { 567 DoPageSetup (); 568 break; 569 } 570 case MENU_PRINT: { 571 DoPrint (); 572 break; 573 } 574 case MSGRUN_WINDOW: { 575 fTermView->UpdateSIGWINCH (); 576 break; 577 } 578 case B_ABOUT_REQUESTED: { 579 be_app->PostMessage(B_ABOUT_REQUESTED); 580 break; 581 } 582 default: { 583 BWindow::MessageReceived(message); 584 break; 585 } 586 } 587 } 588 //////////////////////////////////////////////////////////////////////////// 589 // WindowActivated (bool) 590 // Dispatch Mesasge. 591 //////////////////////////////////////////////////////////////////////////// 592 void 593 TermWindow::WindowActivated (bool ) 594 { 595 596 } 597 598 599 bool 600 TermWindow::QuitRequested() 601 { 602 be_app->PostMessage(B_QUIT_REQUESTED); 603 return true; 604 } 605 606 607 //! Get Machine Timezone. 608 int 609 TermWindow::GetTimeZone() 610 { 611 struct timeval tv; 612 struct timezone tm; 613 614 gettimeofday (&tv, &tm); 615 616 return -tm.tz_minuteswest / 60; 617 } 618 619 620 void 621 TermWindow::TermWinActivate() 622 { 623 Activate(); 624 625 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 626 if (focus_follows_mouse()) { 627 BPoint aMouseLoc = Frame().LeftTop(); 628 set_mouse_position(int32(aMouseLoc.x + 16), int32(aMouseLoc.y + 2)); 629 be_app->SetCursor(B_HAND_CURSOR); 630 } 631 #endif 632 } 633 634 635 status_t 636 TermWindow::GetSupportedSuites(BMessage *msg) 637 { 638 static property_info prop_list[] = { 639 { "encode", 640 {B_GET_PROPERTY, 0}, 641 {B_DIRECT_SPECIFIER, 0}, 642 "get muterminal encode"}, 643 { "encode", 644 {B_SET_PROPERTY, 0}, 645 {B_DIRECT_SPECIFIER, 0}, 646 "set muterminal encode"}, 647 { "tty", 648 {B_GET_PROPERTY, 0}, 649 {B_DIRECT_SPECIFIER, 0}, 650 "get tty_name."}, 651 { 0 } 652 653 }; 654 msg->AddString("suites", "suite/vnd.naan-termwindow"); 655 BPropertyInfo prop_info(prop_list); 656 msg->AddFlat("messages", &prop_info); 657 return BWindow::GetSupportedSuites(msg); 658 } 659 //////////////////////////////////////////////////////////////////////////// 660 // ResolveSpecifier 661 // 662 //////////////////////////////////////////////////////////////////////////// 663 BHandler* 664 TermWindow::ResolveSpecifier(BMessage *msg, int32 index, 665 BMessage *specifier, int32 form, 666 const char *property) 667 { 668 if ( (strcmp(property, "encode") == 0) 669 && ((msg->what == B_SET_PROPERTY) || (msg->what == B_GET_PROPERTY) )) 670 return this; 671 else if ( (strcmp(property, "tty") == 0) 672 && (msg->what == B_GET_PROPERTY) ) 673 return this; 674 675 return BWindow::ResolveSpecifier(msg, index, specifier, form, property); 676 } 677 678 //////////////////////////////////////////////////////////////////////////// 679 // SetCoding 680 // Set coding utility functions. 681 //////////////////////////////////////////////////////////////////////////// 682 void SetCoding (int coding) 683 { 684 const etable *p = encoding_table; 685 p += coding; 686 687 gNowCoding = coding; 688 689 return; 690 } 691 692 693 status_t 694 TermWindow::DoPageSetup() 695 { 696 BPrintJob job("PageSetup"); 697 698 // display the page configure panel 699 status_t status = job.ConfigPage(); 700 701 // save a pointer to the settings 702 fPrintSettings = job.Settings(); 703 704 return status; 705 } 706 707 708 void 709 TermWindow::DoPrint() 710 { 711 if (!fPrintSettings || (DoPageSetup() != B_NO_ERROR)) { 712 (new BAlert("Cancel", "Print cancelled.", "OK"))->Go(); 713 return; 714 } 715 716 BPrintJob job("Print"); 717 job.SetSettings(new BMessage(*fPrintSettings)); 718 719 BRect pageRect = job.PrintableRect(); 720 BRect curPageRect = pageRect; 721 722 int pHeight = (int)pageRect.Height(); 723 int pWidth = (int)pageRect.Width(); 724 float w,h; 725 fTermView->GetFrameSize(&w, &h); 726 int xPages = (int)ceil(w / pWidth); 727 int yPages = (int)ceil(h / pHeight); 728 729 job.BeginJob(); 730 731 // loop through and draw each page, and write to spool 732 for (int x = 0; x < xPages; x++) { 733 for (int y = 0; y < yPages; y++) { 734 curPageRect.OffsetTo(x * pWidth, y * pHeight); 735 job.DrawView(fTermView, curPageRect, B_ORIGIN); 736 job.SpoolPage(); 737 738 if (!job.CanContinue()){ 739 // It is likely that the only way that the job was cancelled is 740 // because the user hit 'Cancel' in the page setup window, in which 741 // case, the user does *not* need to be told that it was cancelled. 742 // He/she will simply expect that it was done. 743 // (new BAlert("Cancel", "Print job cancelled", "OK"))->Go(); 744 return; 745 } 746 } 747 } 748 749 job.CommitJob(); 750 } 751 752