// Be-defined headers #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //****** Application defined header files************/. #include "Constants.h" #include "ColorMenuItem.h" #include "FindWindow.h" #include "ReplaceWindow.h" #include "StyledEditApp.h" #include "StyledEditView.h" #include "StyledEditWindow.h" using namespace BPrivate; StyledEditWindow::StyledEditWindow(BRect frame, int32 id, uint32 encoding) : BWindow(frame,"untitled",B_DOCUMENT_WINDOW,0) { InitWindow(encoding); BString unTitled; unTitled.SetTo("Untitled "); unTitled << id; SetTitle(unTitled.String()); fSaveItem->SetEnabled(true); // allow saving empty files Show(); } /***StyledEditWindow()***/ StyledEditWindow::StyledEditWindow(BRect frame, entry_ref *ref, uint32 encoding) : BWindow(frame,"untitled",B_DOCUMENT_WINDOW,0) { InitWindow(encoding); OpenFile(ref); Show(); } /***StyledEditWindow()***/ StyledEditWindow::~StyledEditWindow() { delete fSaveMessage; delete fPrintSettings; delete fSavePanel; } /***~StyledEditWindow()***/ void StyledEditWindow::InitWindow(uint32 encoding) { fPrintSettings= NULL; fSaveMessage= NULL; // undo modes fUndoFlag = false; fCanUndo = false; fRedoFlag = false; fCanRedo = false; // clean modes fUndoCleans = false; fRedoCleans = false; fClean = true; //search- state fReplaceString= ""; fStringToFind=""; fCaseSens= false; fWrapAround= false; fBackSearch= false; //add menubar fMenuBar = new BMenuBar(BRect(0,0,0,0),"menubar"); AddChild(fMenuBar); //add textview and scrollview BRect viewFrame; BRect textBounds; viewFrame= Bounds(); viewFrame.top = fMenuBar->Bounds().Height()+1; //021021 viewFrame.right -= B_V_SCROLL_BAR_WIDTH; viewFrame.left = 0; //021021 viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT; textBounds= viewFrame; textBounds.OffsetTo(B_ORIGIN); textBounds.InsetBy(TEXT_INSET, TEXT_INSET); fTextView= new StyledEditView(viewFrame, textBounds, this); fTextView->SetDoesUndo(true); fTextView->SetStylable(true); fTextView->SetEncoding(encoding); fScrollView= new BScrollView("scrollview", fTextView, B_FOLLOW_ALL, 0, true, true, B_PLAIN_BORDER); AddChild(fScrollView); fTextView->MakeFocus(true); //Add "File"-menu: BMenu *menu; BMenu *subMenu; BMenuItem *menuItem; menu= new BMenu("File"); fMenuBar->AddItem(menu); menu->AddItem(menuItem= new BMenuItem("New", new BMessage(MENU_NEW), 'N')); menuItem->SetTarget(be_app); menu->AddItem(menuItem= new BMenuItem(fRecentMenu= new BMenu("Open..."), new BMessage(MENU_OPEN))); menuItem->SetShortcut('O',0); menuItem->SetTarget(be_app); menu->AddSeparatorItem(); menu->AddItem(fSaveItem= new BMenuItem("Save", new BMessage(MENU_SAVE), 'S')); fSaveItem->SetEnabled(false); menu->AddItem(menuItem= new BMenuItem("Save As...", new BMessage(MENU_SAVEAS))); menuItem->SetShortcut('S',B_SHIFT_KEY); menuItem->SetEnabled(true); menu->AddItem(fRevertItem= new BMenuItem("Revert to Saved...", new BMessage(MENU_REVERT))); fRevertItem->SetEnabled(false); menu->AddItem(menuItem= new BMenuItem("Close", new BMessage(MENU_CLOSE), 'W')); menu->AddSeparatorItem(); menu->AddItem(menuItem= new BMenuItem("Page Setup...", new BMessage(MENU_PAGESETUP))); menu->AddItem(menuItem= new BMenuItem("Print...", new BMessage(MENU_PRINT), 'P')); menu->AddSeparatorItem(); menu->AddItem(menuItem= new BMenuItem("Quit", new BMessage(MENU_QUIT), 'Q')); //Add the "Edit"-menu: menu= new BMenu("Edit"); fMenuBar->AddItem(menu); menu->AddItem(fUndoItem= new BMenuItem("Can't Undo", new BMessage(B_UNDO), 'Z')); fUndoItem->SetEnabled(false); menu->AddSeparatorItem(); menu->AddItem(fCutItem= new BMenuItem("Cut", new BMessage(B_CUT), 'X')); fCutItem->SetEnabled(false); fCutItem->SetTarget(fTextView); menu->AddItem(fCopyItem= new BMenuItem("Copy", new BMessage(B_COPY), 'C')); fCopyItem->SetEnabled(false); fCopyItem->SetTarget(fTextView); menu->AddItem(menuItem= new BMenuItem("Paste", new BMessage(B_PASTE), 'V')); menuItem->SetTarget(fTextView); menu->AddItem(fClearItem= new BMenuItem("Clear", new BMessage(MENU_CLEAR))); fClearItem->SetEnabled(false); fClearItem->SetTarget(fTextView); menu->AddSeparatorItem(); menu->AddItem(menuItem=new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A')); menuItem->SetTarget(fTextView); menu->AddSeparatorItem(); menu->AddItem(menuItem= new BMenuItem("Find...", new BMessage(MENU_FIND),'F')); menu->AddItem(fFindAgainItem= new BMenuItem("Find Again",new BMessage(MENU_FIND_AGAIN),'G')); fFindAgainItem->SetEnabled(false); menu->AddItem(menuItem= new BMenuItem("Find Selection", new BMessage(MENU_FIND_SELECTION),'H')); menu->AddItem(menuItem= new BMenuItem("Replace...", new BMessage(MENU_REPLACE),'R')); menu->AddItem(fReplaceSameItem= new BMenuItem("Replace Same", new BMessage(MENU_REPLACE_SAME),'T')); fReplaceSameItem->SetEnabled(false); //Add the "Font"-menu: BMessage *fontMessage; fFontMenu = new BMenu("Font"); fMenuBar->AddItem(fFontMenu); //"Size"-subMenu fFontSizeMenu=new BMenu("Size"); fFontSizeMenu->SetRadioMode(true); fFontMenu->AddItem(fFontSizeMenu); fFontSizeMenu->AddItem(menuItem= new BMenuItem("9", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size", 9.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("10", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",10.0); menuItem->SetMarked(true); fFontSizeMenu->AddItem(menuItem= new BMenuItem("11", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",11.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("12", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",12.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("14", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",14.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("18", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",18.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("24", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",24.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("36", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",36.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("48", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",48.0); fFontSizeMenu->AddItem(menuItem= new BMenuItem("72", fontMessage= new BMessage(FONT_SIZE))); fontMessage->AddFloat("size",72.0); //"Color"-subMenu fFontColorMenu= new BMenu("Color"); fFontColorMenu->SetRadioMode(true); fFontMenu->AddItem(fFontColorMenu); fFontColorMenu->AddItem(fBlackItem= new BMenuItem("Black", new BMessage(FONT_COLOR))); fBlackItem->SetMarked(true); fFontColorMenu->AddItem(fRedItem= new ColorMenuItem("Red", RED, new BMessage(FONT_COLOR))); fFontColorMenu->AddItem(fGreenItem= new ColorMenuItem("Green", GREEN, new BMessage(FONT_COLOR))); fFontColorMenu->AddItem(fBlueItem= new ColorMenuItem("Blue", BLUE, new BMessage(FONT_COLOR))); fFontColorMenu->AddItem(fCyanItem= new ColorMenuItem("Cyan", CYAN, new BMessage(FONT_COLOR))); fFontColorMenu->AddItem(fMagentaItem= new ColorMenuItem("Magenta", MAGENTA, new BMessage(FONT_COLOR))); fFontColorMenu->AddItem(fYellowItem= new ColorMenuItem("Yellow", YELLOW, new BMessage(FONT_COLOR))); fFontMenu->AddSeparatorItem(); //Available fonts font_family plain_family; font_style plain_style; be_plain_font->GetFamilyAndStyle(&plain_family,&plain_style); fCurrentFontItem = 0; int32 numFamilies = count_font_families(); for ( int32 i = 0; i < numFamilies; i++ ) { font_family localfamily; if ( get_font_family ( i, &localfamily ) == B_OK ) { subMenu=new BMenu(localfamily); subMenu->SetRadioMode(true); fFontMenu->AddItem(menuItem = new BMenuItem(subMenu, new BMessage(FONT_FAMILY))); if (!strcmp(plain_family,localfamily)) { menuItem->SetMarked(true); fCurrentFontItem = menuItem; } int32 numStyles=count_font_styles(localfamily); for(int32 j = 0;jAddItem(menuItem = new BMenuItem(style, new BMessage(FONT_STYLE))); if (!strcmp(plain_style,style)) { menuItem->SetMarked(true); } } } } } //Add the "Document"-menu: menu= new BMenu("Document"); fMenuBar->AddItem(menu); //"Align"-subMenu: subMenu= new BMenu("Align"); subMenu->SetRadioMode(true); subMenu->AddItem(fAlignLeft = new BMenuItem("Left", new BMessage(ALIGN_LEFT))); menuItem->SetMarked(true); subMenu->AddItem(fAlignCenter = new BMenuItem("Center", new BMessage(ALIGN_CENTER))); subMenu->AddItem(fAlignRight = new BMenuItem("Right", new BMessage(ALIGN_RIGHT))); menu->AddItem(subMenu); menu->AddItem(fWrapItem = new BMenuItem("Wrap Lines", new BMessage(WRAP_LINES))); fWrapItem->SetMarked(true); /***************************MENUS ADDED***********************/ fSavePanel = 0; // build lazily fSavePanelEncodingMenu = 0; // build lazily } /***StyledEditWindow::Initwindow()***/ void StyledEditWindow::MessageReceived(BMessage *message) { if(message->WasDropped()) { entry_ref ref; if(message->FindRef("refs",0,&ref)==B_OK) { message->what=B_REFS_RECEIVED; be_app->PostMessage(message); } } switch(message->what){ /************file menu:***************/ case MENU_SAVE: { if(!fSaveMessage) SaveAs(); else Save(fSaveMessage); } break; case MENU_SAVEAS: SaveAs(); break; case B_SAVE_REQUESTED: Save(message); break; case SAVE_THEN_QUIT: if (Save(message) == B_OK) { BAutolock lock(this); Quit(); } break; case MENU_REVERT: RevertToSaved(); break; case MENU_CLOSE: { if(this->QuitRequested()) { BAutolock lock(this); Quit(); } } break; case MENU_PAGESETUP: PageSetup(fTextView->Window()->Title()); break; case MENU_PRINT: Print(fTextView->Window()->Title()); break; case MENU_QUIT: be_app->PostMessage(B_QUIT_REQUESTED); break; /*********commands from the "Edit"-menu:**************/ case B_UNDO: ASSERT(fCanUndo || fCanRedo); ASSERT(!(fCanUndo && fCanRedo)); if (fCanUndo) { fUndoFlag = true; } if (fCanRedo) { fRedoFlag = true; } fTextView->Undo(be_clipboard); break; case B_CUT: fTextView->Cut(be_clipboard); break; case B_COPY: fTextView->Copy(be_clipboard); break; case B_PASTE: fTextView->Paste(be_clipboard); break; case MENU_CLEAR: fTextView->Clear(); break; case MENU_FIND: { BRect findWindowFrame(100,100,400,235); FindWindow *find; find= new FindWindow(findWindowFrame, this, &fStringToFind, &fCaseSens, &fWrapAround, &fBackSearch); } break; case MSG_SEARCH: { message->FindString("findtext", &fStringToFind); fFindAgainItem->SetEnabled(true); message->FindBool("casesens", &fCaseSens); message->FindBool("wrap", &fWrapAround); message->FindBool("backsearch", &fBackSearch); Search(fStringToFind, fCaseSens, fWrapAround, fBackSearch); } break; case MENU_FIND_AGAIN: Search(fStringToFind, fCaseSens, fWrapAround, fBackSearch); break; case MENU_FIND_SELECTION: FindSelection(); break; case MENU_REPLACE: { BRect replaceWindowFrame(100,100,400,284); ReplaceWindow *replace; replace= new ReplaceWindow(replaceWindowFrame, this, &fStringToFind, &fReplaceString, &fCaseSens, &fWrapAround, &fBackSearch); } break; case MSG_REPLACE: { BString findIt; BString replaceWith; bool caseSens, wrap, backSearch; message->FindBool("casesens", &caseSens); message->FindBool("wrap", &wrap); message->FindBool("backsearch", &backSearch); message->FindString("FindText",&findIt); message->FindString("ReplaceText",&replaceWith); fStringToFind= findIt; fFindAgainItem->SetEnabled(true); fReplaceString= replaceWith; fReplaceSameItem->SetEnabled(true); fCaseSens= caseSens; fWrapAround= wrap; fBackSearch= backSearch; Replace(findIt, replaceWith, caseSens, wrap, backSearch); } break; case MENU_REPLACE_SAME: { Replace(fStringToFind,fReplaceString,fCaseSens,fWrapAround,fBackSearch); } break; case MSG_REPLACE_ALL: { BString findIt; BString replaceWith; bool caseSens, allWindows; message->FindBool("casesens", &caseSens); message->FindString("FindText",&findIt); message->FindString("ReplaceText",&replaceWith); message->FindBool("allwindows", &allWindows); fStringToFind= findIt; fFindAgainItem->SetEnabled(true); fReplaceString= replaceWith; fReplaceSameItem->SetEnabled(true); fCaseSens= caseSens; if(allWindows) SearchAllWindows(findIt, replaceWith, caseSens); else ReplaceAll(findIt, replaceWith,caseSens); } break; /*********"Font"-menu*****************/ case FONT_SIZE: { float fontSize; message->FindFloat("size",&fontSize); SetFontSize(fontSize); } break; case FONT_FAMILY: { const char * fontFamily = 0, * fontStyle = 0; void * ptr; if (message->FindPointer("source",&ptr) == B_OK) { fCurrentFontItem = static_cast(ptr); fontFamily = fCurrentFontItem->Label(); } SetFontStyle(fontFamily, fontStyle); } break; case FONT_STYLE: { const char * fontFamily = 0, * fontStyle = 0; void * ptr; if (message->FindPointer("source",&ptr) == B_OK) { BMenuItem * item = static_cast(ptr); fontStyle = item->Label(); BMenu * menu = item->Menu(); if (menu != 0) { fCurrentFontItem = menu->Superitem(); if (fCurrentFontItem != 0) { fontFamily = fCurrentFontItem->Label(); } } } SetFontStyle(fontFamily, fontStyle); } break; case FONT_COLOR: { void * ptr; if (message->FindPointer("source",&ptr) == B_OK) { if (ptr == fBlackItem) { SetFontColor(&BLACK); } else if (ptr == fRedItem) { SetFontColor(&RED); } else if (ptr == fGreenItem) { SetFontColor(&GREEN); } else if (ptr == fBlueItem) { SetFontColor(&BLUE); } else if (ptr == fCyanItem) { SetFontColor(&CYAN); } else if (ptr == fMagentaItem) { SetFontColor(&MAGENTA); } else if (ptr == fYellowItem) { SetFontColor(&YELLOW); } } } break; /*********"Document"-menu*************/ case ALIGN_LEFT: fTextView->SetAlignment(B_ALIGN_LEFT); fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; break; case ALIGN_CENTER: fTextView->SetAlignment(B_ALIGN_CENTER); fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; break; case ALIGN_RIGHT: fTextView->SetAlignment(B_ALIGN_RIGHT); fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; break; case WRAP_LINES: if (fTextView->DoesWordWrap()) { fTextView->SetWordWrap(false); fWrapItem->SetMarked(false); BRect textRect; textRect = fTextView->Bounds(); textRect.OffsetTo(B_ORIGIN); textRect.InsetBy(TEXT_INSET,TEXT_INSET); // the width comes from stylededit R5. TODO: find a better way textRect.SetRightBottom(BPoint(1500.0,textRect.RightBottom().y)); fTextView->SetTextRect(textRect); } else { fTextView->SetWordWrap(true); fWrapItem->SetMarked(true); BRect textRect; textRect = fTextView->Bounds(); textRect.OffsetTo(B_ORIGIN); textRect.InsetBy(TEXT_INSET,TEXT_INSET); fTextView->SetTextRect(textRect); } fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; break; case ENABLE_ITEMS: { fCutItem->SetEnabled(true); fCopyItem->SetEnabled(true); fClearItem->SetEnabled(true); } break; case DISABLE_ITEMS: { fCutItem->SetEnabled(false); fCopyItem->SetEnabled(false); fClearItem->SetEnabled(false); } break; case TEXT_CHANGED: { if (fUndoFlag) { if (fUndoCleans) { // we cleaned! fClean = true; fUndoCleans = false; } else if (fClean) { // if we were clean // then a redo will make us clean again fRedoCleans = true; fClean = false; } // set mode fCanUndo = false; fCanRedo = true; fUndoItem->SetLabel("Redo Typing"); fUndoItem->SetEnabled(true); fUndoFlag = false; } else { if (fRedoFlag && fRedoCleans) { // we cleaned! fClean = true; fRedoCleans = false; } else if (fClean) { // if we were clean // then an undo will make us clean again fUndoCleans = true; fClean = false; } else { // no more cleaning from undo now... fUndoCleans = false; } // set mode fCanUndo = true; fCanRedo = false; fUndoItem->SetLabel("Undo Typing"); fUndoItem->SetEnabled(true); fRedoFlag = false; } if (fClean) { fRevertItem->SetEnabled(false); fSaveItem->SetEnabled(fSaveMessage == NULL); } else { fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); } // clear flags } break; /*********"Document"-menu*************/ case SAVE_AS_ENCODING: void * ptr; if (message->FindPointer("source",&ptr) == B_OK) { if (fSavePanelEncodingMenu != 0) { fTextView->SetEncoding((uint32)fSavePanelEncodingMenu->IndexOf((BMenuItem*)ptr)); } } break; default: BWindow::MessageReceived(message); break; } }/***StyledEditWindow::MessageReceived() ***/ void StyledEditWindow::MenusBeginning() { // set up the recent documents menu BMessage documents; be_roster->GetRecentDocuments(&documents,9,NULL,APP_SIGNATURE); // delete old items.. // shatty: it would be preferable to keep the old // menu around instead of continuously thrashing // the menu, but unfortunately there does not // seem to be a straightforward way to update it // going backwards may simplify memory management for (int i = fRecentMenu->CountItems()-1 ; (i >= 0) ; i--) { delete fRecentMenu->RemoveItem(i); } // add new items int count = 0; entry_ref ref; while (documents.FindRef("refs",count++,&ref) == B_OK) { if ((ref.device != -1) && (ref.directory != -1)) { // sanity check passed BMessage * openRecent = new BMessage(B_REFS_RECEIVED); openRecent->AddRef("refs",&ref); BMenuItem * item = new BMenuItem(ref.name,openRecent); item->SetTarget(be_app); fRecentMenu->AddItem(item); } } // update the font menu be/interface/GraphicsDefs.h // unselect the old values if (fCurrentFontItem != 0) { fCurrentFontItem->SetMarked(false); } BMenuItem * oldColorItem = fFontColorMenu->FindMarked(); if (oldColorItem != 0) { oldColorItem->SetMarked(false); } BMenuItem * oldSizeItem = fFontSizeMenu->FindMarked(); if (oldSizeItem != 0) { oldSizeItem->SetMarked(false); } // find the current font, color, size BFont font; uint32 sameProperties; rgb_color color = BLACK; bool sameColor; fTextView->GetFontAndColor(&font,&sameProperties,&color,&sameColor); if (sameColor && (color.alpha == 255)) { // select the current color if (color.red == 0) { if (color.green == 0) { if (color.blue == 0) { fBlackItem->SetMarked(true); } else if (color.blue == 255) { fBlueItem->SetMarked(true); } } else if (color.green == 255) { if (color.blue == 0) { fGreenItem->SetMarked(true); } else if (color.blue == 255) { fCyanItem->SetMarked(true); } } } else if (color.red == 255) { if (color.green == 0) { if (color.blue == 0) { fRedItem->SetMarked(true); } else if (color.blue == 255) { fMagentaItem->SetMarked(true); } } else if (color.green == 255) { if (color.blue == 0) { fYellowItem->SetMarked(true); } } } } if (sameProperties & B_FONT_SIZE) { if ((int)font.Size() == font.Size()) { // select the current font size char fontSizeStr[16]; snprintf(fontSizeStr,15,"%i",(int)font.Size()); BMenuItem * item = fFontSizeMenu->FindItem(fontSizeStr); if (item != 0) { item->SetMarked(true); } } } if (sameProperties & B_FONT_FAMILY_AND_STYLE) { font_family family; font_style style; font.GetFamilyAndStyle(&family,&style); fCurrentFontItem = fFontMenu->FindItem(family); if (fCurrentFontItem != 0) { fCurrentFontItem->SetMarked(true); BMenu * menu = fCurrentFontItem->Submenu(); if (menu != 0) { BMenuItem * item = menu->FindItem(style); if (item != 0) { item->SetMarked(true); } } } } switch (fTextView->Alignment()) { case B_ALIGN_LEFT: fAlignLeft->SetMarked(true); break; case B_ALIGN_CENTER: fAlignCenter->SetMarked(true); break; case B_ALIGN_RIGHT: fAlignRight->SetMarked(true); break; default: // I am so confused. break; } } void StyledEditWindow::Quit() { styled_edit_app->CloseDocument(); BWindow::Quit(); } bool StyledEditWindow::QuitRequested() { int32 buttonIndex= 0; if (fClean) return true; BAlert *saveAlert; BString alertText; alertText.SetTo("Save changes to the document \""); alertText<< Title(); alertText<<"\"? "; saveAlert= new BAlert("savealert",alertText.String(), "Cancel", "Don't Save","Save", B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); saveAlert->SetShortcut(0, B_ESCAPE); saveAlert->SetShortcut(1,'d'); saveAlert->SetShortcut(2,'s'); buttonIndex= saveAlert->Go(); if (buttonIndex==0) { //"cancel": dont save, dont close the window return false; } else if(buttonIndex==1) { // "don't save": just close the window return true; } else if(!fSaveMessage) { //save as BMessage * message = new BMessage(SAVE_THEN_QUIT); SaveAs(message); return false; } else { return (Save() == B_OK); } }/***QuitRequested()***/ status_t StyledEditWindow::Save(BMessage *message) { status_t err = B_OK; if(!message){ message=fSaveMessage; if(!message) return B_ERROR; } entry_ref dirref; err= message->FindRef("directory", &dirref); if(err!= B_OK) return err; const char *name; err=message->FindString("name", &name); if (err!= B_OK) return err; BDirectory dir(&dirref); err= dir.InitCheck(); if(err!= B_OK) return err; BEntry entry(&dir, name); err= entry.InitCheck(); if(err!= B_OK) return err; BFile file(&entry, B_READ_WRITE | B_CREATE_FILE); err= file.InitCheck(); if(err!= B_OK) return err; err = fTextView->WriteStyledEditFile(&file); if(err != B_OK) { BAlert *saveFailedAlert; BString alertText; if (err == B_TRANSLATION_ERROR_BASE) { alertText.SetTo("Translation error saving \""); } else { alertText.SetTo("Unknown error saving \""); } alertText<< name; alertText<<"\"."; saveFailedAlert= new BAlert("saveFailedAlert",alertText.String(), "Bummer", 0, 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT); saveFailedAlert->SetShortcut(0, B_ESCAPE); saveFailedAlert->Go(); return err; } SetTitle(name); if(fSaveMessage!= message) { delete fSaveMessage; fSaveMessage= new BMessage(*message); } entry_ref ref; if (entry.GetRef(&ref) == B_OK) { be_roster->AddToRecentDocuments(&ref,APP_SIGNATURE); } // clear clean modes fSaveItem->SetEnabled(false); fRevertItem->SetEnabled(false); fUndoCleans = false; fRedoCleans = false; fClean = true; return err; } /***Save()***/ status_t StyledEditWindow::SaveAs(BMessage *message) { if (fSavePanel == 0) { entry_ref * directory = 0; if (fSaveMessage != 0) { entry_ref dirref; if (fSaveMessage->FindRef("directory", &dirref)) { directory = new entry_ref(dirref); } } fSavePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this), directory, B_FILE_NODE, false); BMenuBar * menuBar = dynamic_cast(fSavePanel->Window()->FindView("MenuBar")); fSavePanelEncodingMenu= new BMenu("Encoding"); menuBar->AddItem(fSavePanelEncodingMenu); fSavePanelEncodingMenu->SetRadioMode(true); BCharacterSetRoster roster; BCharacterSet charset; while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) { BString name(charset.GetPrintName()); const char * mime = charset.GetMIMEName(); if (mime) { name.Append(" ("); name.Append(mime); name.Append(")"); } BMenuItem * item = new BMenuItem(name.String(),new BMessage(SAVE_AS_ENCODING)); item->SetTarget(this); fSavePanelEncodingMenu->AddItem(item); if (charset.GetFontID() == fTextView->GetEncoding()) { item->SetMarked(true); } } } fSavePanel->SetSaveText(Title()); if (message != 0) { fSavePanel->SetMessage(message); } fSavePanel->Show(); return B_OK; } void StyledEditWindow::OpenFile(entry_ref *ref) { BFile file; status_t fileinit; fileinit = file.SetTo(ref, B_READ_ONLY); if (fileinit == B_OK){ status_t result; result = fTextView->GetStyledText(&file); //he he he :) if (result != B_OK) { BEntry entry(ref, true); char name[B_FILE_NAME_LENGTH]; entry.GetName(name); BAlert *loadFailedAlert; BString alertText; if (result == B_TRANSLATION_ERROR_BASE) { alertText.SetTo("Translation error loading \""); } else { alertText.SetTo("Unknown error loading \""); } alertText<< name; alertText<<"\"."; loadFailedAlert= new BAlert("loadFailedAlert",alertText.String(), "Bummer", 0, 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT); loadFailedAlert->Go(); return; } // update alignment switch (fTextView->Alignment()) { case B_ALIGN_LEFT: fAlignLeft->SetMarked(true); break; case B_ALIGN_CENTER: fAlignCenter->SetMarked(true); break; case B_ALIGN_RIGHT: fAlignRight->SetMarked(true); break; default: // weird break; } // update word wrapping fWrapItem->SetMarked(fTextView->DoesWordWrap()); } else { fSaveItem->SetEnabled(true); // allow saving new files } be_roster->AddToRecentDocuments(ref,APP_SIGNATURE); fSaveMessage = new BMessage(B_SAVE_REQUESTED); if(fSaveMessage){ BEntry entry(ref, true); BEntry parent; entry_ref parentRef; char name[B_FILE_NAME_LENGTH]; entry.GetParent(&parent); entry.GetName(name); parent.GetRef(&parentRef); fSaveMessage->AddRef("directory",&parentRef); fSaveMessage->AddString("name", name); SetTitle(name); } fTextView->Select(0,0); }/*** StyledEditWindow::OpenFile() ***/ void StyledEditWindow::RevertToSaved() { entry_ref ref; const char *name; fSaveMessage->FindRef("directory", &ref); fSaveMessage->FindString("name", &name); BDirectory dir(&ref); BFile file(&dir, name, B_READ_ONLY); status_t result; result = file.InitCheck(); if (result != B_OK) { BAlert *vanishedAlert; BString alertText; alertText.SetTo("Cannot revert, file not found: \""); alertText<< name; alertText<<"\"."; vanishedAlert = new BAlert("vanishedAlert",alertText.String(), "Bummer", 0, 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT); vanishedAlert->SetShortcut(0, B_ESCAPE); vanishedAlert->Go(); return; } int32 buttonIndex= 0; BAlert *revertAlert; BString alertText; alertText.SetTo("Revert to the last version of \""); alertText<< Title(); alertText<<"\"? "; revertAlert= new BAlert("revertAlert",alertText.String(), "Cancel", "OK", 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT); revertAlert->SetShortcut(0, B_ESCAPE); revertAlert->SetShortcut(1, 'o'); buttonIndex= revertAlert->Go(); if (buttonIndex!=1) { // some sort of cancel, don't revert return; } fTextView->Reset(); //clear the textview... result = fTextView->GetStyledText(&file); //he he he :) if (result != B_OK) { BAlert *loadFailedAlert; BString alertText; if (result == B_TRANSLATION_ERROR_BASE) { alertText.SetTo("Translation error loading \""); } else { alertText.SetTo("Unknown error loading \""); } alertText<< name; alertText<<"\"."; loadFailedAlert= new BAlert("loadFailedAlert",alertText.String(), "Bummer", 0, 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT); loadFailedAlert->SetShortcut(0, B_ESCAPE); loadFailedAlert->Go(); return; } // update alignment switch (fTextView->Alignment()) { case B_ALIGN_LEFT: fAlignLeft->SetMarked(true); break; case B_ALIGN_CENTER: fAlignCenter->SetMarked(true); break; case B_ALIGN_RIGHT: fAlignRight->SetMarked(true); break; default: // weird break; } // update word wrapping fWrapItem->SetMarked(fTextView->DoesWordWrap()); // clear undo modes fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fUndoFlag = false; fCanUndo = false; fRedoFlag = false; fCanRedo = false; // clear clean modes fSaveItem->SetEnabled(false); fRevertItem->SetEnabled(false); fUndoCleans = false; fRedoCleans = false; fClean = true; }/***StyledEditWindow::RevertToSaved()***/ status_t StyledEditWindow::PageSetup(const char *documentname) { status_t result = B_OK; BPrintJob printJob(documentname); if (fPrintSettings != NULL) { printJob.SetSettings(new BMessage(*fPrintSettings)); } result = printJob.ConfigPage(); if (result == B_NO_ERROR) { delete fPrintSettings; fPrintSettings = printJob.Settings(); } return result; }/***StyledEditWindow::PageSetup()***/ void StyledEditWindow::Print(const char *documentname) { status_t result = B_OK; if (fPrintSettings == NULL) { result = PageSetup(documentname); if (result != B_OK) { return; } } BPrintJob printJob(documentname); printJob.SetSettings(new BMessage(*fPrintSettings)); result = printJob.ConfigJob(); if (result != B_OK) { return; } // information from printJob BRect printable_rect = printJob.PrintableRect(); int32 firstPage = printJob.FirstPage(); int32 lastPage = printJob.LastPage(); // lines eventually to be used to compute pages to print int32 firstLine = 0; int32 lastLine = fTextView->CountLines(); // values to be computed int32 pagesInDocument = 1; int32 linesInDocument = fTextView->CountLines(); int32 currentLine = 0; while (currentLine < linesInDocument) { float currentHeight = 0; while ((currentHeight < printable_rect.Height()) && (currentLine < linesInDocument)) { currentHeight += fTextView->LineHeight(currentLine); if (currentHeight < printable_rect.Height()) { currentLine++; } } if (pagesInDocument == lastPage) { lastLine = currentLine; } if (currentHeight >= printable_rect.Height()) { pagesInDocument++; if (pagesInDocument == firstPage) { firstLine = currentLine; } } } if (lastPage > pagesInDocument - 1) { lastPage = pagesInDocument - 1; lastLine = currentLine - 1; } printJob.BeginJob(); int32 printLine = firstLine; while (printLine < lastLine) { float currentHeight = 0; int32 firstLineOnPage = printLine; while ((currentHeight < printable_rect.Height()) && (printLine < lastLine)) { currentHeight += fTextView->LineHeight(printLine); if (currentHeight < printable_rect.Height()) { printLine++; } } float top = 0; if (firstLineOnPage != 0) { top = fTextView->TextHeight(0,firstLineOnPage-1); } float bottom = fTextView->TextHeight(0,printLine-1); BRect textRect(0.0,top+TEXT_INSET,printable_rect.Width(),bottom+TEXT_INSET); printJob.DrawView(fTextView,textRect,BPoint(0.0,0.0)); printJob.SpoolPage(); } printJob.CommitJob(); }/***StyledEditWindow::Print()***/ bool StyledEditWindow::Search(BString string, bool casesens, bool wrap, bool backsearch) { int32 start; int32 finish; int32 strlen; start = B_ERROR; strlen = string.Length(); if (strlen== 0) return false; BString viewText(fTextView->Text()); int32 textStart, textFinish; fTextView->GetSelection(&textStart, &textFinish); if (backsearch == true) { if (casesens == true) { start = viewText.FindLast(string, textStart); } else { start = viewText.IFindLast(string, textStart); } } else { if (casesens == true) { start = viewText.FindFirst(string, textFinish); } else { start = viewText.IFindFirst(string, textFinish); } } if ((start == B_ERROR) && (wrap == true)) { if (backsearch == true) { if (casesens == true) { start = viewText.FindLast(string, viewText.Length()); } else { start = viewText.IFindLast(string, viewText.Length()); } } else { if (casesens == true) { start = viewText.FindFirst(string, 0); } else { start = viewText.IFindFirst(string, 0); } } } if (start != B_ERROR) { finish = start + strlen; fTextView->Select(start, finish); fTextView->ScrollToSelection(); return true; } else { return false; } }/***StyledEditWindow::Search***/ void StyledEditWindow::FindSelection() { int32 selectionStart, selectionFinish; fTextView->GetSelection(&selectionStart,&selectionFinish); int32 selectionLength; selectionLength= selectionFinish- selectionStart; BString viewText; viewText= fTextView->Text(); viewText.CopyInto(fStringToFind, selectionStart, selectionLength); fFindAgainItem->SetEnabled(true); Search(fStringToFind, fCaseSens, fWrapAround, fBackSearch); }/***StyledEditWindow::FindSelection()***/ bool StyledEditWindow::Replace(BString findthis, BString replaceWith, bool casesens, bool wrap, bool backsearch) { if (Search(findthis, casesens, wrap, backsearch)) { int32 start, finish; fTextView->GetSelection(&start, &finish); fTextView->Delete(start, start + findthis.Length()); fTextView->Insert(start, replaceWith.String(), replaceWith.Length()); fTextView->Select(start, start + replaceWith.Length()); fTextView->ScrollToSelection(); return true; } else { return false; } }/***StyledEditWindow::Replace()***/ void StyledEditWindow::ReplaceAll(BString findIt, BString replaceWith, bool caseSens) { BString viewText(fTextView->Text()); if (caseSens) viewText.ReplaceAll(findIt.String(),replaceWith.String()); else viewText.IReplaceAll(findIt.String(),replaceWith.String()); if (viewText.Compare(fTextView->Text()) == 0) { // they are the same return; } int32 textStart, textFinish; fTextView->GetSelection(&textStart, &textFinish); fTextView->SetText(viewText.String()); if (viewText.Length() < textStart) textStart = viewText.Length(); if (viewText.Length() < textFinish) textFinish = viewText.Length(); fTextView->Select(textStart,textFinish); fTextView->ScrollToSelection(); fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; }/***StyledEditWindow::ReplaceAll()***/ void StyledEditWindow::SearchAllWindows(BString find, BString replace, bool casesens) { int32 numWindows; numWindows= be_app->CountWindows(); BMessage *message; message= new BMessage(MSG_REPLACE_ALL); message->AddString("FindText",find); message->AddString("ReplaceText",replace); message->AddBool("casesens", casesens); BMessenger *messenger; while(numWindows>=0){ StyledEditWindow *win= dynamic_cast(be_app->WindowAt(numWindows)); messenger= new BMessenger(win); messenger->SendMessage(message); numWindows--; } }/***StyledEditWindow::SearchAllWindows***/ void StyledEditWindow::SetFontSize(float fontSize) { uint32 sameProperties; BFont font; fTextView->GetFontAndColor(&font,&sameProperties); font.SetSize(fontSize); fTextView->SetFontAndColor(&font,B_FONT_SIZE); fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; }/***StyledEditWindow::SetFontSize()***/ void StyledEditWindow::SetFontColor(const rgb_color *color) { uint32 sameProperties; BFont font; fTextView->GetFontAndColor(&font,&sameProperties,NULL,NULL); fTextView->SetFontAndColor(&font, 0, color); fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; }/***StyledEditWindow::SetFontColor()***/ void StyledEditWindow::SetFontStyle(const char *fontFamily, const char *fontStyle) { BFont font; uint32 sameProperties; // find out what the old font was font_family oldFamily; font_style oldStyle; fTextView->GetFontAndColor(&font,&sameProperties); font.GetFamilyAndStyle(&oldFamily,&oldStyle); // clear that family's bit on the menu, if necessary if (strcmp(oldFamily,fontFamily)) { BMenuItem * oldItem = fFontMenu->FindItem(oldFamily); if (oldItem != 0) { oldItem->SetMarked(false); } } font.SetFamilyAndStyle(fontFamily,fontStyle); fTextView->SetFontAndColor(&font); BMenuItem * superItem; superItem = fFontMenu->FindItem(fontFamily); if (superItem != 0) { superItem->SetMarked(true); } fClean = false; fUndoCleans = false; fRedoCleans = false; fRevertItem->SetEnabled(fSaveMessage != NULL); fSaveItem->SetEnabled(true); fUndoItem->SetLabel("Can't Undo"); fUndoItem->SetEnabled(false); fCanUndo = false; fCanRedo = false; }/***StyledEditWindow::SetFontStyle()***/