1 /* 2 * Copyright 2002-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Mattias Sundblad 7 * Andrew Bachmann 8 * Jonas Sundström 9 */ 10 11 12 #include "Constants.h" 13 #include "StyledEditApp.h" 14 #include "StyledEditWindow.h" 15 16 #include <Alert.h> 17 #include <Autolock.h> 18 #include <Catalog.h> 19 #include <Locale.h> 20 #include <MenuBar.h> 21 #include <CharacterSet.h> 22 #include <CharacterSetRoster.h> 23 #include <FilePanel.h> 24 #include <MenuItem.h> 25 #include <Message.h> 26 #include <Path.h> 27 #include <Screen.h> 28 29 #include <stdio.h> 30 31 32 using namespace BPrivate; 33 34 35 BRect gWindowRect(7 - 15, 26 - 15, 507, 426); 36 37 38 namespace 39 { 40 void 41 cascade() 42 { 43 BScreen screen; 44 BRect screenBorder = screen.Frame(); 45 float left = gWindowRect.left + 15; 46 if (left + gWindowRect.Width() > screenBorder.right) 47 left = 7; 48 49 float top = gWindowRect.top + 15; 50 if (top + gWindowRect.Height() > screenBorder.bottom) 51 top = 26; 52 53 gWindowRect.OffsetTo(BPoint(left, top)); 54 } 55 56 57 void 58 uncascade() 59 { 60 BScreen screen; 61 BRect screenBorder = screen.Frame(); 62 63 float left = gWindowRect.left - 15; 64 if (left < 7) { 65 left = screenBorder.right - gWindowRect.Width() - 7; 66 left = left - ((int)left % 15) + 7; 67 } 68 69 float top = gWindowRect.top - 15; 70 if (top < 26) { 71 top = screenBorder.bottom - gWindowRect.Height() - 26; 72 top = top - ((int)left % 15) + 26; 73 } 74 75 gWindowRect.OffsetTo(BPoint(left, top)); 76 } 77 } 78 79 80 // #pragma mark - 81 82 83 #undef B_TRANSLATION_CONTEXT 84 #define B_TRANSLATION_CONTEXT "Open_and_SaveAsPanel" 85 86 87 StyledEditApp::StyledEditApp() 88 : 89 BApplication(APP_SIGNATURE), 90 fOpenPanel(NULL) 91 { 92 B_TRANSLATE_MARK_SYSTEM_NAME_VOID("StyledEdit"); 93 94 fOpenPanel = new BFilePanel(); 95 fOpenAsEncoding = 0; 96 97 BMenuBar* menuBar 98 = dynamic_cast<BMenuBar*>(fOpenPanel->Window()->FindView("MenuBar")); 99 if (menuBar != NULL) { 100 fOpenPanelEncodingMenu = new BMenu(B_TRANSLATE("Encoding")); 101 fOpenPanelEncodingMenu->SetRadioMode(true); 102 103 menuBar->AddItem(fOpenPanelEncodingMenu); 104 105 BCharacterSetRoster roster; 106 BCharacterSet charset; 107 while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) { 108 BString name; 109 if (charset.GetFontID() == B_UNICODE_UTF8) 110 name = B_TRANSLATE("Default"); 111 else 112 name = charset.GetPrintName(); 113 114 const char* mime = charset.GetMIMEName(); 115 if (mime != NULL) { 116 name.Append(" ("); 117 name.Append(mime); 118 name.Append(")"); 119 } 120 BMenuItem* item 121 = new BMenuItem(name.String(), new BMessage(OPEN_AS_ENCODING)); 122 item->SetTarget(this); 123 fOpenPanelEncodingMenu->AddItem(item); 124 if (charset.GetFontID() == fOpenAsEncoding) 125 item->SetMarked(true); 126 } 127 } else 128 fOpenPanelEncodingMenu = NULL; 129 130 fWindowCount = 0; 131 fNextUntitledWindow = 1; 132 fBadArguments = false; 133 } 134 135 136 StyledEditApp::~StyledEditApp() 137 { 138 delete fOpenPanel; 139 } 140 141 142 void 143 StyledEditApp::MessageReceived(BMessage* message) 144 { 145 switch (message->what) { 146 case MENU_NEW: 147 OpenDocument(); 148 break; 149 case MENU_OPEN: 150 fOpenPanel->Show(); 151 break; 152 case B_SILENT_RELAUNCH: 153 OpenDocument(); 154 break; 155 case OPEN_AS_ENCODING: 156 void* ptr; 157 if (message->FindPointer("source", &ptr) == B_OK 158 && fOpenPanelEncodingMenu != NULL) { 159 fOpenAsEncoding = (uint32)fOpenPanelEncodingMenu->IndexOf( 160 (BMenuItem*)ptr); 161 } 162 break; 163 164 default: 165 BApplication::MessageReceived(message); 166 break; 167 } 168 } 169 170 171 void 172 StyledEditApp::OpenDocument() 173 { 174 cascade(); 175 new StyledEditWindow(gWindowRect, fNextUntitledWindow++, fOpenAsEncoding); 176 fWindowCount++; 177 } 178 179 180 status_t 181 StyledEditApp::OpenDocument(entry_ref* ref) 182 { 183 // traverse eventual symlink 184 BEntry entry(ref, true); 185 entry.GetRef(ref); 186 187 if (entry.IsDirectory()) { 188 BPath path(&entry); 189 fprintf(stderr, 190 "Can't open directory \"%s\" for editing.\n", 191 path.Path()); 192 return B_ERROR; 193 } 194 195 BEntry parent; 196 entry.GetParent(&parent); 197 198 if (!entry.Exists() && !parent.Exists()) { 199 fprintf(stderr, 200 "Can't create file. Missing parent directory.\n"); 201 return B_ERROR; 202 } 203 204 BWindow* window = NULL; 205 StyledEditWindow* document = NULL; 206 207 for (int32 index = 0; ; index++) { 208 window = WindowAt(index); 209 if (window == NULL) 210 break; 211 212 document = dynamic_cast<StyledEditWindow*>(window); 213 if (document == NULL) 214 continue; 215 216 if (document->IsDocumentEntryRef(ref)) { 217 if (document->Lock()) { 218 document->Activate(); 219 document->Unlock(); 220 return B_OK; 221 } 222 } 223 } 224 225 cascade(); 226 new StyledEditWindow(gWindowRect, ref, fOpenAsEncoding); 227 fWindowCount++; 228 229 return B_OK; 230 } 231 232 233 void 234 StyledEditApp::CloseDocument() 235 { 236 uncascade(); 237 fWindowCount--; 238 if (fWindowCount == 0) { 239 BAutolock lock(this); 240 Quit(); 241 } 242 } 243 244 245 void 246 StyledEditApp::RefsReceived(BMessage* message) 247 { 248 int32 index = 0; 249 entry_ref ref; 250 251 while (message->FindRef("refs", index++, &ref) == B_OK) { 252 OpenDocument(&ref); 253 } 254 } 255 256 257 void 258 StyledEditApp::ArgvReceived(int32 argc, char* argv[]) 259 { 260 // If StyledEdit is already running and gets invoked again 261 // we need to account for a possible mismatch in current 262 // working directory. The paths of the new arguments are 263 // relative to the cwd of the invocation, if they are not 264 // absolute. This cwd we find as a string named "cwd" in 265 // the BLooper's current message. 266 267 const char* cwd = ""; 268 BMessage* message = CurrentMessage(); 269 270 if (message != NULL) { 271 if (message->FindString("cwd", &cwd) != B_OK) 272 cwd = ""; 273 } 274 275 for (int i = 1 ; (i < argc) ; i++) { 276 BPath path; 277 if (argv[i][0] == '/') { 278 path.SetTo(argv[i]); 279 } else { 280 path.SetTo(cwd, argv[i]); 281 // patch relative paths only 282 } 283 284 entry_ref ref; 285 get_ref_for_path(path.Path(), &ref); 286 287 status_t status; 288 status = OpenDocument(&ref); 289 290 if (status != B_OK && IsLaunching()) 291 fBadArguments = true; 292 } 293 } 294 295 296 void 297 StyledEditApp::ReadyToRun() 298 { 299 if (fWindowCount > 0) 300 return; 301 302 if (fBadArguments) 303 Quit(); 304 else 305 OpenDocument(); 306 } 307 308 309 int32 310 StyledEditApp::NumberOfWindows() 311 { 312 return fWindowCount; 313 } 314 315 316 // #pragma mark - 317 318 319 int 320 main(int argc, char** argv) 321 { 322 StyledEditApp styledEdit; 323 styledEdit.Run(); 324 return 0; 325 } 326 327