1 /* 2 * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <new> 8 9 #include <Directory.h> 10 #include <Entry.h> 11 #include <FindDirectory.h> 12 #include <InterfaceDefs.h> 13 #include <MenuItem.h> 14 #include <Message.h> 15 #include <Node.h> 16 #include <Path.h> 17 #include <PopUpMenu.h> 18 #include <String.h> 19 20 21 static BPoint 22 mouse_position() 23 { 24 // Returns the mouse position in screen coordinates 25 BPoint position; 26 get_mouse(&position, NULL); 27 return position; 28 } 29 30 31 static void 32 add_status_item(BMenu* menu, const char* name) 33 { 34 if (menu->FindItem(name) != NULL) 35 return; 36 37 // Sort items alphabetically 38 int32 index; 39 for (index = 0; index < menu->CountItems(); index++) { 40 if (strcmp(menu->ItemAt(index)->Label(), name) > 0) 41 break; 42 } 43 44 menu->AddItem(new BMenuItem(name, NULL), index); 45 } 46 47 48 static void 49 retrieve_status_items(BMenu* menu) 50 { 51 BPath path; 52 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 53 return; 54 55 path.Append("Mail/status"); 56 57 BDirectory directory(path.Path()); 58 59 entry_ref ref; 60 while (directory.GetNextRef(&ref) == B_OK) { 61 if (!strcmp(ref.name, ".") || !strcmp(ref.name, "..")) 62 continue; 63 64 add_status_item(menu, ref.name); 65 } 66 67 add_status_item(menu, "New"); 68 add_status_item(menu, "Read"); 69 add_status_item(menu, "Replied"); 70 } 71 72 73 // #pragma mark - 74 75 76 extern "C" void 77 process_refs(entry_ref dir, BMessage* message, void* /*reserved*/) 78 { 79 BPopUpMenu* menu = new BPopUpMenu("status"); 80 retrieve_status_items(menu); 81 82 BMenuItem* item = menu->Go(mouse_position() - BPoint(5, 5), false, true); 83 if (item == NULL) 84 return; 85 86 BString status = item->Label(); 87 88 entry_ref ref; 89 for (int i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { 90 BNode node(&ref); 91 BString type; 92 93 if (node.InitCheck() == B_OK 94 && node.ReadAttrString("BEOS:TYPE", &type) == B_OK 95 && type == "text/x-email") { 96 BString previousStatus; 97 98 // Only update the attribute if there is an actual change 99 if (node.ReadAttrString("MAIL:status", &previousStatus) != B_OK 100 || previousStatus != status) 101 node.WriteAttrString("MAIL:status", &status); 102 } 103 } 104 } 105 106