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_TRANSLATE_CONTEXT 84 #define B_TRANSLATE_CONTEXT "Open_and_SaveAsPanel" 85 86 87 StyledEditApp::StyledEditApp() 88 : 89 BApplication(APP_SIGNATURE), 90 fOpenPanel(NULL) 91 { 92 fOpenPanel = new BFilePanel(); 93 94 fOpenAsEncoding = 0; 95 96 BMenuBar* menuBar 97 = dynamic_cast<BMenuBar*>(fOpenPanel->Window()->FindView("MenuBar")); 98 if (menuBar != NULL) { 99 fOpenPanelEncodingMenu = new BMenu(B_TRANSLATE("Encoding")); 100 fOpenPanelEncodingMenu->SetRadioMode(true); 101 102 menuBar->AddItem(fOpenPanelEncodingMenu); 103 104 BCharacterSetRoster roster; 105 BCharacterSet charset; 106 while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) { 107 BString name; 108 if (charset.GetFontID() == B_UNICODE_UTF8) 109 name = B_TRANSLATE("Default"); 110 else 111 name = charset.GetPrintName(); 112 113 const char* mime = charset.GetMIMEName(); 114 if (mime != NULL) { 115 name.Append(" ("); 116 name.Append(mime); 117 name.Append(")"); 118 } 119 BMenuItem* item = 120 new BMenuItem(name.String(), new BMessage(OPEN_AS_ENCODING)); 121 item->SetTarget(this); 122 fOpenPanelEncodingMenu->AddItem(item); 123 if (charset.GetFontID() == fOpenAsEncoding) 124 item->SetMarked(true); 125 } 126 } else 127 fOpenPanelEncodingMenu = NULL; 128 129 fWindowCount = 0; 130 fNextUntitledWindow = 1; 131 fBadArguments = false; 132 } 133 134 135 StyledEditApp::~StyledEditApp() 136 { 137 delete fOpenPanel; 138 } 139 140 141 void 142 StyledEditApp::MessageReceived(BMessage* message) 143 { 144 switch (message->what) { 145 case MENU_NEW: 146 OpenDocument(); 147 break; 148 case MENU_OPEN: 149 fOpenPanel->Show(); 150 break; 151 case B_SILENT_RELAUNCH: 152 OpenDocument(); 153 break; 154 case OPEN_AS_ENCODING: 155 void* ptr; 156 if (message->FindPointer("source", &ptr) == B_OK 157 && fOpenPanelEncodingMenu != NULL) { 158 fOpenAsEncoding = (uint32)fOpenPanelEncodingMenu->IndexOf( 159 (BMenuItem*)ptr); 160 } 161 break; 162 163 default: 164 BApplication::MessageReceived(message); 165 break; 166 } 167 } 168 169 170 void 171 StyledEditApp::OpenDocument() 172 { 173 cascade(); 174 new StyledEditWindow(gWindowRect, fNextUntitledWindow++, fOpenAsEncoding); 175 fWindowCount++; 176 } 177 178 179 status_t 180 StyledEditApp::OpenDocument(entry_ref* ref) 181 { 182 // traverse eventual symlink 183 BEntry entry(ref, true); 184 entry.GetRef(ref); 185 186 if (entry.IsDirectory()) { 187 BPath path(&entry); 188 fprintf(stderr, 189 "Can't open directory \"%s\" for editing.\n", 190 path.Path()); 191 return B_ERROR; 192 } 193 194 BEntry parent; 195 entry.GetParent(&parent); 196 197 if (!entry.Exists() && !parent.Exists()) { 198 fprintf(stderr, 199 "Can't create file. Missing parent directory.\n"); 200 return B_ERROR; 201 } 202 203 BWindow* window = NULL; 204 StyledEditWindow* document = NULL; 205 206 for (int32 index = 0; ; index++) { 207 window = WindowAt(index); 208 if (window == NULL) 209 break; 210 211 document = dynamic_cast<StyledEditWindow*>(window); 212 if (document == NULL) 213 continue; 214 215 if (document->IsDocumentEntryRef(ref)) { 216 if (document->Lock()) { 217 document->Activate(); 218 document->Unlock(); 219 return B_OK; 220 } 221 } 222 } 223 224 cascade(); 225 new StyledEditWindow(gWindowRect, ref, fOpenAsEncoding); 226 fWindowCount++; 227 228 return B_OK; 229 } 230 231 232 void 233 StyledEditApp::CloseDocument() 234 { 235 uncascade(); 236 fWindowCount--; 237 if (fWindowCount == 0) { 238 BAutolock lock(this); 239 Quit(); 240 } 241 } 242 243 244 void 245 StyledEditApp::RefsReceived(BMessage* message) 246 { 247 int32 index = 0; 248 entry_ref ref; 249 250 while (message->FindRef("refs", index++, &ref) == B_OK) { 251 OpenDocument(&ref); 252 } 253 } 254 255 256 void 257 StyledEditApp::ArgvReceived(int32 argc, char* argv[]) 258 { 259 // If StyledEdit is already running and gets invoked again 260 // we need to account for a possible mismatch in current 261 // working directory. The paths of the new arguments are 262 // relative to the cwd of the invocation, if they are not 263 // absolute. This cwd we find as a string named "cwd" in 264 // the BLooper's current message. 265 266 const char* cwd = ""; 267 BMessage* message = CurrentMessage(); 268 269 if (message != NULL) { 270 if (message->FindString("cwd", &cwd) != B_OK) 271 cwd = ""; 272 } 273 274 for (int i = 1 ; (i < argc) ; i++) { 275 BPath path; 276 if (argv[i][0] == '/') { 277 path.SetTo(argv[i]); 278 } else { 279 path.SetTo(cwd, argv[i]); 280 // patch relative paths only 281 } 282 283 entry_ref ref; 284 get_ref_for_path(path.Path(), &ref); 285 286 status_t status; 287 status = OpenDocument(&ref); 288 289 if (status != B_OK && IsLaunching()) 290 fBadArguments = true; 291 } 292 } 293 294 295 void 296 StyledEditApp::ReadyToRun() 297 { 298 if (fWindowCount > 0) 299 return; 300 301 if (fBadArguments) 302 Quit(); 303 else 304 OpenDocument(); 305 } 306 307 308 int32 309 StyledEditApp::NumberOfWindows() 310 { 311 return fWindowCount; 312 } 313 314 315 // #pragma mark - 316 317 318 int 319 main(int argc, char** argv) 320 { 321 StyledEditApp styledEdit; 322 styledEdit.Run(); 323 return 0; 324 } 325 326