1 /* 2 * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. 3 * Copyright 2014 Haiku, Inc. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors: 8 * Ralf Schülke, ralf.schuelke@googlemail.com 9 * John Scipione, jscipione@gmail.com 10 */ 11 12 13 #include "Pairs.h" 14 15 #include <stdio.h> 16 // for snprintf() 17 #include <stdlib.h> 18 19 #include <Alert.h> 20 #include <Catalog.h> 21 #include <Message.h> 22 #include <MimeType.h> 23 #include <String.h> 24 25 #include "PairsWindow.h" 26 27 28 #undef B_TRANSLATION_CONTEXT 29 #define B_TRANSLATION_CONTEXT "Pairs" 30 31 32 const char* kSignature = "application/x-vnd.Haiku-Pairs"; 33 34 static const size_t kMinIconCount = 64; 35 static const size_t kMaxIconCount = 384; 36 37 38 // #pragma mark - Pairs 39 40 41 Pairs::Pairs() 42 : 43 BApplication(kSignature), 44 fWindow(NULL) 45 { 46 _GetVectorIcons(); 47 } 48 49 50 Pairs::~Pairs() 51 { 52 } 53 54 55 void 56 Pairs::ReadyToRun() 57 { 58 fWindow = new PairsWindow(); 59 fWindow->Show(); 60 } 61 62 63 void 64 Pairs::RefsReceived(BMessage* message) 65 { 66 fWindow->PostMessage(message); 67 } 68 69 70 void 71 Pairs::MessageReceived(BMessage* message) 72 { 73 BApplication::MessageReceived(message); 74 } 75 76 77 bool 78 Pairs::QuitRequested() 79 { 80 // delete vector icons 81 for (IconMap::iterator iter = fIconMap.begin(); iter != fIconMap.end(); 82 ++iter) { 83 delete fIconMap[iter->first]; 84 } 85 86 return true; 87 } 88 89 90 // #pragma mark - Pairs private methods 91 92 93 void 94 Pairs::_GetVectorIcons() 95 { 96 // Load vector icons from the MIME type database and add a pointer to them 97 // into a std::map keyed by a generated hash. 98 99 BMessage types; 100 if (BMimeType::GetInstalledTypes("application", &types) != B_OK) 101 return; 102 103 const char* type; 104 for (int32 i = 0; types.FindString("types", i, &type) == B_OK; i++) { 105 BMimeType mimeType(type); 106 if (mimeType.InitCheck() != B_OK) 107 continue; 108 109 uint8* data; 110 size_t size; 111 112 if (mimeType.GetIcon(&data, &size) != B_OK) { 113 // didn't find an icon 114 continue; 115 } 116 117 size_t hash = 0xdeadbeef; 118 for (size_t i = 0; i < size; i++) 119 hash = 31 * hash + data[i]; 120 121 if (fIconMap.find(hash) != fIconMap.end()) { 122 // key has already been added to the map 123 delete[] data; 124 continue; 125 } 126 127 vector_icon* icon = (vector_icon*)malloc(sizeof(vector_icon)); 128 if (icon == NULL) { 129 delete[] data; 130 free(icon); 131 continue; 132 } 133 134 icon->data = data; 135 icon->size = size; 136 137 // found a vector icon, add it to the list 138 fIconMap[hash] = icon; 139 if (fIconMap.size() >= kMaxIconCount) { 140 // this is enough to choose from, stop eating memory... 141 return; 142 } 143 } 144 145 if (fIconMap.size() < kMinIconCount) { 146 char buffer[512]; 147 snprintf(buffer, sizeof(buffer), 148 B_TRANSLATE_COMMENT("Pairs did not find enough vector icons " 149 "to start; it needs at least %zu, found %zu.\n", 150 "Don't translate \"%zu\", but make sure to keep them."), 151 kMinIconCount, fIconMap.size()); 152 BString messageString(buffer); 153 BAlert* alert = new BAlert("Fatal", messageString.String(), 154 B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, 155 B_STOP_ALERT); 156 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 157 alert->Go(); 158 exit(1); 159 } 160 } 161 162 163 // #pragma mark - main 164 165 166 int 167 main(void) 168 { 169 Pairs pairs; 170 pairs.Run(); 171 172 return 0; 173 } 174