/* * Copyright 2002-2016, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Mattias Sundblad * Andrew Bachmann * Jonas Sundström */ #include "Constants.h" #include "StyledEditApp.h" #include "StyledEditWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace BPrivate; static BRect sWindowRect(7, 26, 507, 426); static float sCascadeOffset = 15; static BPoint sTopLeft = BPoint(7, 26); namespace { void cascade() { BScreen screen; BRect screenBorder = screen.Frame(); float left = sWindowRect.left + sCascadeOffset; if (left + sWindowRect.Width() > screenBorder.right) left = sTopLeft.x; float top = sWindowRect.top + sCascadeOffset; if (top + sWindowRect.Height() > screenBorder.bottom) top = sTopLeft.y; sWindowRect.OffsetTo(BPoint(left, top)); } void uncascade() { BScreen screen; BRect screenBorder = screen.Frame(); float left = sWindowRect.left - sCascadeOffset; if (left < sTopLeft.x) { left = screenBorder.right - sWindowRect.Width() - sTopLeft.x; left = left - ((int)left % (int)sCascadeOffset) + sTopLeft.x; } float top = sWindowRect.top - sCascadeOffset; if (top < sTopLeft.y) { top = screenBorder.bottom - sWindowRect.Height() - sTopLeft.y; top = top - ((int)left % (int)sCascadeOffset) + sTopLeft.y; } sWindowRect.OffsetTo(BPoint(left, top)); } } // #pragma mark - #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Open_and_SaveAsPanel" StyledEditApp::StyledEditApp() : BApplication(APP_SIGNATURE), fOpenPanel(NULL) { B_TRANSLATE_MARK_SYSTEM_NAME_VOID("StyledEdit"); fOpenPanel = new BFilePanel(); fOpenAsEncoding = 0; BMenuBar* menuBar = dynamic_cast(fOpenPanel->Window()->FindView("MenuBar")); if (menuBar != NULL) { fOpenPanelEncodingMenu = new BMenu(B_TRANSLATE("Encoding")); fOpenPanelEncodingMenu->SetRadioMode(true); menuBar->AddItem(fOpenPanelEncodingMenu); BCharacterSetRoster roster; BCharacterSet charset; while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) { BString name; if (charset.GetFontID() == B_UNICODE_UTF8) name = B_TRANSLATE("Default"); else name = charset.GetPrintName(); const char* mime = charset.GetMIMEName(); if (mime != NULL) { name.Append(" ("); name.Append(mime); name.Append(")"); } BMenuItem* item = new BMenuItem(name.String(), new BMessage(OPEN_AS_ENCODING)); item->SetTarget(this); fOpenPanelEncodingMenu->AddItem(item); if (charset.GetFontID() == fOpenAsEncoding) item->SetMarked(true); } } else fOpenPanelEncodingMenu = NULL; fWindowCount = 0; fNextUntitledWindow = 1; fBadArguments = false; float factor = be_plain_font->Size() / 12.0f; sCascadeOffset *= factor; sTopLeft.x *= factor; sTopLeft.y *= factor; sWindowRect.left *= factor; sWindowRect.top *= factor; sWindowRect.right *= factor; sWindowRect.bottom *= factor; } StyledEditApp::~StyledEditApp() { delete fOpenPanel; } void StyledEditApp::MessageReceived(BMessage* message) { switch (message->what) { case MENU_NEW: OpenDocument(); break; case MENU_OPEN: fOpenPanel->Show(); break; case B_SILENT_RELAUNCH: OpenDocument(); break; case OPEN_AS_ENCODING: void* ptr; if (message->FindPointer("source", &ptr) == B_OK && fOpenPanelEncodingMenu != NULL) { fOpenAsEncoding = (uint32)fOpenPanelEncodingMenu->IndexOf( (BMenuItem*)ptr); } break; default: BApplication::MessageReceived(message); break; } } void StyledEditApp::OpenDocument() { new StyledEditWindow(sWindowRect, fNextUntitledWindow++, fOpenAsEncoding); cascade(); fWindowCount++; } status_t StyledEditApp::OpenDocument(entry_ref* ref, BMessage* message) { // traverse eventual symlink BEntry entry(ref, true); entry.GetRef(ref); if (entry.IsDirectory()) { BPath path(&entry); fprintf(stderr, "Can't open directory \"%s\" for editing.\n", path.Path()); return B_ERROR; } BEntry parent; entry.GetParent(&parent); if (!entry.Exists() && !parent.Exists()) { fprintf(stderr, "Can't create file. Missing parent directory.\n"); return B_ERROR; } BWindow* window = NULL; StyledEditWindow* document = NULL; for (int32 index = 0; ; index++) { window = WindowAt(index); if (window == NULL) break; document = dynamic_cast(window); if (document == NULL) continue; if (document->IsDocumentEntryRef(ref)) { if (document->Lock()) { document->Activate(); document->Unlock(); if (message != NULL) document->PostMessage(message); return B_OK; } } } document = new StyledEditWindow(sWindowRect, ref, fOpenAsEncoding); cascade(); if (message != NULL) document->PostMessage(message); fWindowCount++; return B_OK; } void StyledEditApp::CloseDocument() { uncascade(); fWindowCount--; if (fWindowCount == 0) { BAutolock lock(this); Quit(); } } void StyledEditApp::RefsReceived(BMessage* message) { int32 index = 0; entry_ref ref; while (message->FindRef("refs", index, &ref) == B_OK) { int32 line; if (message->FindInt32("be:line", index, &line) != B_OK) line = -1; int32 start, length; if (message->FindInt32("be:selection_length", index, &length) != B_OK || message->FindInt32("be:selection_offset", index, &start) != B_OK) { start = -1; length = -1; } BMessage* selection = NULL; if (line >= 0 || (start >= 0 && length >= 0)) { selection = new BMessage(UPDATE_LINE_SELECTION); if (line >= 0) selection->AddInt32("be:line", line); if (start >= 0) { selection->AddInt32("be:selection_offset", start); selection->AddInt32("be:selection_length", max_c(0, length)); } } OpenDocument(&ref, selection); index++; } } void StyledEditApp::ArgvReceived(int32 argc, char* argv[]) { // If StyledEdit is already running and gets invoked again // we need to account for a possible mismatch in current // working directory. The paths of the new arguments are // relative to the cwd of the invocation, if they are not // absolute. This cwd we find as a string named "cwd" in // the BLooper's current message. const char* cwd = ""; BMessage* message = CurrentMessage(); if (message != NULL) { if (message->FindString("cwd", &cwd) != B_OK) cwd = ""; } for (int i = 1 ; (i < argc) ; i++) { BPath path; if (argv[i][0] == '/') { path.SetTo(argv[i]); } else { path.SetTo(cwd, argv[i]); // patch relative paths only } entry_ref ref; get_ref_for_path(path.Path(), &ref); status_t status; status = OpenDocument(&ref); if (status != B_OK && IsLaunching()) fBadArguments = true; } } void StyledEditApp::ReadyToRun() { if (fWindowCount > 0) return; if (fBadArguments) Quit(); else OpenDocument(); } int32 StyledEditApp::NumberOfWindows() { return fWindowCount; } // #pragma mark - int main(int argc, char** argv) { StyledEditApp styledEdit; styledEdit.Run(); return 0; }