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