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