19949213aSStephan Aßmus //////////////////////////////////////////////////////////////////////////////// 29949213aSStephan Aßmus // 39949213aSStephan Aßmus // File: GIFTranslator.cpp 49949213aSStephan Aßmus // 59949213aSStephan Aßmus // Date: December 1999 69949213aSStephan Aßmus // 79949213aSStephan Aßmus // Author: Daniel Switkin 89949213aSStephan Aßmus // 99949213aSStephan Aßmus // Copyright 2003 (c) by Daniel Switkin. This file is made publically available 109949213aSStephan Aßmus // under the BSD license, with the stipulations that this complete header must 119949213aSStephan Aßmus // remain at the top of the file indefinitely, and credit must be given to the 129949213aSStephan Aßmus // original author in any about box using this software. 139949213aSStephan Aßmus // 149949213aSStephan Aßmus //////////////////////////////////////////////////////////////////////////////// 15*5e4c29a6SJohn Scipione 16abfe23dcSPhilippe Saint-Pierre // Additional authors: Stephan Aßmus, <superstippi@gmx.de> 17*5e4c29a6SJohn Scipione // John Scipione, <jscipione@gmail.com> 189949213aSStephan Aßmus 199949213aSStephan Aßmus #include "GIFTranslator.h" 20*5e4c29a6SJohn Scipione 21*5e4c29a6SJohn Scipione #include <stdio.h> 22*5e4c29a6SJohn Scipione #include <stdlib.h> 23*5e4c29a6SJohn Scipione #include <string.h> 24*5e4c29a6SJohn Scipione #include <syslog.h> 2570d59669SSiarzhuk Zharski 26abfe23dcSPhilippe Saint-Pierre #include <Application.h> 279949213aSStephan Aßmus #include <ByteOrder.h> 2870d59669SSiarzhuk Zharski #include <Catalog.h> 299949213aSStephan Aßmus #include <DataIO.h> 3070d59669SSiarzhuk Zharski #include <InterfaceDefs.h> 3170d59669SSiarzhuk Zharski #include <TypeConstants.h> 329949213aSStephan Aßmus #include <TranslatorAddOn.h> 339949213aSStephan Aßmus #include <TranslatorFormats.h> 3470d59669SSiarzhuk Zharski 35*5e4c29a6SJohn Scipione #include "GIFView.h" 36*5e4c29a6SJohn Scipione #include "GIFSave.h" 37*5e4c29a6SJohn Scipione #include "GIFLoad.h" 38abfe23dcSPhilippe Saint-Pierre #include "TranslatorWindow.h" 39abfe23dcSPhilippe Saint-Pierre 40*5e4c29a6SJohn Scipione 419949213aSStephan Aßmus #ifndef GIF_TYPE 429949213aSStephan Aßmus #define GIF_TYPE 'GIF ' 439949213aSStephan Aßmus #endif 449949213aSStephan Aßmus 45546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 46546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "GIFTranslator" 4770d59669SSiarzhuk Zharski 4870d59669SSiarzhuk Zharski 499949213aSStephan Aßmus bool debug = false; 50*5e4c29a6SJohn Scipione // this global will be externed in other files - set once here 51*5e4c29a6SJohn Scipione // for the entire translator 529949213aSStephan Aßmus 53*5e4c29a6SJohn Scipione bool DetermineType(BPositionIO* source, bool* isGif); 549949213aSStephan Aßmus status_t GetBitmap(BPositionIO* in, BBitmap** out); 559949213aSStephan Aßmus 56abfe23dcSPhilippe Saint-Pierre static const translation_format sInputFormats[] = { 57*5e4c29a6SJohn Scipione { 58*5e4c29a6SJohn Scipione GIF_TYPE, 59*5e4c29a6SJohn Scipione B_TRANSLATOR_BITMAP, 60*5e4c29a6SJohn Scipione GIF_IN_QUALITY, 61*5e4c29a6SJohn Scipione GIF_IN_CAPABILITY, 62*5e4c29a6SJohn Scipione "image/gif", 63*5e4c29a6SJohn Scipione "GIF image" 64*5e4c29a6SJohn Scipione }, 65*5e4c29a6SJohn Scipione { 66*5e4c29a6SJohn Scipione B_TRANSLATOR_BITMAP, 67*5e4c29a6SJohn Scipione B_TRANSLATOR_BITMAP, 68*5e4c29a6SJohn Scipione BBM_IN_QUALITY, 69*5e4c29a6SJohn Scipione BBM_IN_CAPABILITY, 70*5e4c29a6SJohn Scipione "image/x-be-bitmap", 71*5e4c29a6SJohn Scipione "Be Bitmap Format (GIFTranslator)" 72*5e4c29a6SJohn Scipione } 739949213aSStephan Aßmus }; 749949213aSStephan Aßmus 75abfe23dcSPhilippe Saint-Pierre static const translation_format sOutputFormats[] = { 76*5e4c29a6SJohn Scipione { 77*5e4c29a6SJohn Scipione GIF_TYPE, 78*5e4c29a6SJohn Scipione B_TRANSLATOR_BITMAP, 79*5e4c29a6SJohn Scipione GIF_OUT_QUALITY, 80*5e4c29a6SJohn Scipione GIF_OUT_CAPABILITY, 81*5e4c29a6SJohn Scipione "image/gif", 82*5e4c29a6SJohn Scipione "GIF image" 83*5e4c29a6SJohn Scipione }, 84*5e4c29a6SJohn Scipione { 85*5e4c29a6SJohn Scipione B_TRANSLATOR_BITMAP, 86*5e4c29a6SJohn Scipione B_TRANSLATOR_BITMAP, 87*5e4c29a6SJohn Scipione BBM_OUT_QUALITY, 88*5e4c29a6SJohn Scipione BBM_OUT_CAPABILITY, 89*5e4c29a6SJohn Scipione "image/x-be-bitmap", 90*5e4c29a6SJohn Scipione "Be Bitmap Format (GIFTranslator)" 91*5e4c29a6SJohn Scipione } 929949213aSStephan Aßmus }; 939949213aSStephan Aßmus 94abfe23dcSPhilippe Saint-Pierre // Default settings for the Translator 95abfe23dcSPhilippe Saint-Pierre static const TranSetting sDefaultSettings[] = { 96abfe23dcSPhilippe Saint-Pierre { B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false }, 97abfe23dcSPhilippe Saint-Pierre { B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false }, 98abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_INTERLACED, TRAN_SETTING_BOOL, false }, 99abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_USE_TRANSPARENT, TRAN_SETTING_BOOL, false }, 100abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_USE_TRANSPARENT_AUTO, TRAN_SETTING_BOOL, false }, 101abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_USE_DITHERING, TRAN_SETTING_BOOL, false }, 102abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_PALETTE_MODE, TRAN_SETTING_INT32, 0 }, 103abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_PALETTE_SIZE, TRAN_SETTING_INT32, 8 }, 104abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_TRANSPARENT_RED, TRAN_SETTING_INT32, 0 }, 105abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_TRANSPARENT_GREEN, TRAN_SETTING_INT32, 0 }, 106abfe23dcSPhilippe Saint-Pierre { GIF_SETTING_TRANSPARENT_BLUE, TRAN_SETTING_INT32, 0 } 107abfe23dcSPhilippe Saint-Pierre }; 1089949213aSStephan Aßmus 109abfe23dcSPhilippe Saint-Pierre const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format); 110abfe23dcSPhilippe Saint-Pierre const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format); 111abfe23dcSPhilippe Saint-Pierre const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting); 1129949213aSStephan Aßmus 1139949213aSStephan Aßmus 1149949213aSStephan Aßmus /* Look at first few bytes in stream to determine type - throw it back 115*5e4c29a6SJohn Scipione * if it is not a GIF or a BBitmap that we understand. 116*5e4c29a6SJohn Scipione */ 1179949213aSStephan Aßmus bool 118*5e4c29a6SJohn Scipione DetermineType(BPositionIO* source, bool* isGif) 1199949213aSStephan Aßmus { 1209949213aSStephan Aßmus unsigned char header[7]; 121*5e4c29a6SJohn Scipione *isGif = true; 122abfe23dcSPhilippe Saint-Pierre if (source->Read(header, 6) != 6) 123abfe23dcSPhilippe Saint-Pierre return false; 1249949213aSStephan Aßmus header[6] = 0x00; 1259949213aSStephan Aßmus 126*5e4c29a6SJohn Scipione if (strcmp((char*)header, "GIF87a") != 0 127*5e4c29a6SJohn Scipione && strcmp((char*)header, "GIF89a") != 0) { 128*5e4c29a6SJohn Scipione *isGif = false; 12970d59669SSiarzhuk Zharski int32 magic = (header[0] << 24) + (header[1] << 16) + (header[2] << 8) 13070d59669SSiarzhuk Zharski + header[3]; 131abfe23dcSPhilippe Saint-Pierre if (magic != B_TRANSLATOR_BITMAP) 132abfe23dcSPhilippe Saint-Pierre return false; 133*5e4c29a6SJohn Scipione 1349949213aSStephan Aßmus source->Seek(5 * 4 - 2, SEEK_CUR); 1359949213aSStephan Aßmus color_space cs; 136abfe23dcSPhilippe Saint-Pierre if (source->Read(&cs, 4) != 4) 137abfe23dcSPhilippe Saint-Pierre return false; 138*5e4c29a6SJohn Scipione 1399949213aSStephan Aßmus cs = (color_space)B_BENDIAN_TO_HOST_INT32(cs); 140abfe23dcSPhilippe Saint-Pierre if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG 141*5e4c29a6SJohn Scipione && cs != B_RGBA32_BIG) { 142abfe23dcSPhilippe Saint-Pierre return false; 1439949213aSStephan Aßmus } 144*5e4c29a6SJohn Scipione } 1459949213aSStephan Aßmus 1469949213aSStephan Aßmus source->Seek(0, SEEK_SET); 1479949213aSStephan Aßmus return true; 1489949213aSStephan Aßmus } 1499949213aSStephan Aßmus 1509949213aSStephan Aßmus 1519949213aSStephan Aßmus status_t 1529949213aSStephan Aßmus GetBitmap(BPositionIO* in, BBitmap** out) 1539949213aSStephan Aßmus { 1549949213aSStephan Aßmus TranslatorBitmap header; 1559949213aSStephan Aßmus status_t err = in->Read(&header, sizeof(header)); 1569949213aSStephan Aßmus if (err != sizeof(header)) 1579949213aSStephan Aßmus return B_IO_ERROR; 1589949213aSStephan Aßmus 1599949213aSStephan Aßmus header.magic = B_BENDIAN_TO_HOST_INT32(header.magic); 1609949213aSStephan Aßmus header.bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left); 1619949213aSStephan Aßmus header.bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top); 1629949213aSStephan Aßmus header.bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right); 1639949213aSStephan Aßmus header.bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom); 1649949213aSStephan Aßmus header.rowBytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes); 1659949213aSStephan Aßmus header.colors = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors); 1669949213aSStephan Aßmus header.dataSize = B_BENDIAN_TO_HOST_INT32(header.dataSize); 1679949213aSStephan Aßmus 168*5e4c29a6SJohn Scipione // dump data from stream into a BBitmap 169abfe23dcSPhilippe Saint-Pierre BBitmap* bitmap = new(std::nothrow) BBitmap(header.bounds, header.colors); 1709949213aSStephan Aßmus *out = bitmap; 171abfe23dcSPhilippe Saint-Pierre if (bitmap == NULL) 172abfe23dcSPhilippe Saint-Pierre return B_NO_MEMORY; 173*5e4c29a6SJohn Scipione 1749949213aSStephan Aßmus unsigned char* bits = (unsigned char*)bitmap->Bits(); 1759949213aSStephan Aßmus if (bits == NULL) { 1769949213aSStephan Aßmus delete bitmap; 1779949213aSStephan Aßmus return B_NO_MEMORY; 1789949213aSStephan Aßmus } 179*5e4c29a6SJohn Scipione 1809949213aSStephan Aßmus err = in->Read(bits, header.dataSize); 181abfe23dcSPhilippe Saint-Pierre if (err == (status_t)header.dataSize) 182abfe23dcSPhilippe Saint-Pierre return B_OK; 183de6ba1a0SAdrien Destugues else { 184de6ba1a0SAdrien Destugues delete bitmap; 185de6ba1a0SAdrien Destugues return B_IO_ERROR; 186de6ba1a0SAdrien Destugues } 1879949213aSStephan Aßmus } 1889949213aSStephan Aßmus 1899949213aSStephan Aßmus 1909949213aSStephan Aßmus status_t 191abfe23dcSPhilippe Saint-Pierre GIFTranslator::DerivedIdentify(BPositionIO* inSource, 192abfe23dcSPhilippe Saint-Pierre const translation_format* inFormat, BMessage* ioExtension, 193abfe23dcSPhilippe Saint-Pierre translator_info* outInfo, uint32 outType) 1949949213aSStephan Aßmus { 195*5e4c29a6SJohn Scipione // Required identify function - may need to read entire header, not sure 1969949213aSStephan Aßmus const char* debug_text = getenv("GIF_TRANSLATOR_DEBUG"); 197abfe23dcSPhilippe Saint-Pierre if (debug_text != NULL && atoi(debug_text) != 0) 198abfe23dcSPhilippe Saint-Pierre debug = true; 1999949213aSStephan Aßmus 200abfe23dcSPhilippe Saint-Pierre if (outType == 0) 201abfe23dcSPhilippe Saint-Pierre outType = B_TRANSLATOR_BITMAP; 202*5e4c29a6SJohn Scipione 20370d59669SSiarzhuk Zharski if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) 20470d59669SSiarzhuk Zharski return B_NO_TRANSLATOR; 2059949213aSStephan Aßmus 206*5e4c29a6SJohn Scipione bool isGif; 207*5e4c29a6SJohn Scipione if (!DetermineType(inSource, &isGif)) 208abfe23dcSPhilippe Saint-Pierre return B_NO_TRANSLATOR; 209*5e4c29a6SJohn Scipione 210*5e4c29a6SJohn Scipione if (!isGif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP) 2119949213aSStephan Aßmus return B_NO_TRANSLATOR; 2129949213aSStephan Aßmus 2139949213aSStephan Aßmus outInfo->group = B_TRANSLATOR_BITMAP; 214*5e4c29a6SJohn Scipione if (isGif) { 2159949213aSStephan Aßmus outInfo->type = GIF_TYPE; 216abfe23dcSPhilippe Saint-Pierre outInfo->quality = GIF_IN_QUALITY; 217abfe23dcSPhilippe Saint-Pierre outInfo->capability = GIF_IN_CAPABILITY; 218aec33db1SPhilippe Saint-Pierre strlcpy(outInfo->name, B_TRANSLATE("GIF image"), sizeof(outInfo->name)); 2199949213aSStephan Aßmus strcpy(outInfo->MIME, "image/gif"); 220abfe23dcSPhilippe Saint-Pierre } else { 2219949213aSStephan Aßmus outInfo->type = B_TRANSLATOR_BITMAP; 222abfe23dcSPhilippe Saint-Pierre outInfo->quality = BBM_IN_QUALITY; 223abfe23dcSPhilippe Saint-Pierre outInfo->capability = BBM_IN_CAPABILITY; 224aec33db1SPhilippe Saint-Pierre strlcpy(outInfo->name, B_TRANSLATE("Be Bitmap Format (GIFTranslator)"), 2253927bd3cSPhilippe Saint-Pierre sizeof(outInfo->name)); 2269949213aSStephan Aßmus strcpy(outInfo->MIME, "image/x-be-bitmap"); 2279949213aSStephan Aßmus } 228*5e4c29a6SJohn Scipione 2299949213aSStephan Aßmus return B_OK; 2309949213aSStephan Aßmus } 2319949213aSStephan Aßmus 2329949213aSStephan Aßmus 2339949213aSStephan Aßmus /* Main required function - assumes that an incoming GIF must be translated 234*5e4c29a6SJohn Scipione * to a BBitmap, and vice versa - this could be improved 235*5e4c29a6SJohn Scipione */ 2369949213aSStephan Aßmus status_t 237abfe23dcSPhilippe Saint-Pierre GIFTranslator::DerivedTranslate(BPositionIO* inSource, 238abfe23dcSPhilippe Saint-Pierre const translator_info* inInfo, BMessage* ioExtension, uint32 outType, 239abfe23dcSPhilippe Saint-Pierre BPositionIO* outDestination, int32 baseType) 2409949213aSStephan Aßmus { 2419949213aSStephan Aßmus const char* debug_text = getenv("GIF_TRANSLATOR_DEBUG"); 242*5e4c29a6SJohn Scipione if (debug_text != NULL && atoi(debug_text) != 0) 243*5e4c29a6SJohn Scipione debug = true; 2449949213aSStephan Aßmus 245*5e4c29a6SJohn Scipione if (outType == 0) 246*5e4c29a6SJohn Scipione outType = B_TRANSLATOR_BITMAP; 247*5e4c29a6SJohn Scipione 248*5e4c29a6SJohn Scipione if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) 2499949213aSStephan Aßmus return B_NO_TRANSLATOR; 2509949213aSStephan Aßmus 251*5e4c29a6SJohn Scipione bool isGif; 252*5e4c29a6SJohn Scipione if (!DetermineType(inSource, &isGif)) 253*5e4c29a6SJohn Scipione return B_NO_TRANSLATOR; 254*5e4c29a6SJohn Scipione 255*5e4c29a6SJohn Scipione if (!isGif && inInfo->type != B_TRANSLATOR_BITMAP) 256*5e4c29a6SJohn Scipione return B_NO_TRANSLATOR; 2579949213aSStephan Aßmus 2589949213aSStephan Aßmus status_t err = B_OK; 2599949213aSStephan Aßmus bigtime_t now = system_time(); 260*5e4c29a6SJohn Scipione 261*5e4c29a6SJohn Scipione if (!isGif) { 262*5e4c29a6SJohn Scipione // BBitmap to GIF 2637bc02c61SStefano Ceccherini BBitmap* bitmap = NULL; 2647bc02c61SStefano Ceccherini err = GetBitmap(inSource, &bitmap); 2657bc02c61SStefano Ceccherini if (err != B_OK) 2667bc02c61SStefano Ceccherini return err; 267*5e4c29a6SJohn Scipione 268*5e4c29a6SJohn Scipione GIFSave* gitSave = new GIFSave(bitmap, outDestination, fSettings); 269*5e4c29a6SJohn Scipione if (gitSave->fatalerror) { 270*5e4c29a6SJohn Scipione delete gitSave; 2717bc02c61SStefano Ceccherini delete bitmap; 2729949213aSStephan Aßmus return B_NO_MEMORY; 2739949213aSStephan Aßmus } 274*5e4c29a6SJohn Scipione delete gitSave; 2757bc02c61SStefano Ceccherini delete bitmap; 276*5e4c29a6SJohn Scipione } else { 277*5e4c29a6SJohn Scipione // GIF to BBitmap 278*5e4c29a6SJohn Scipione GIFLoad* gifLoad = new GIFLoad(inSource, outDestination); 279*5e4c29a6SJohn Scipione if (gifLoad->fatalerror) { 280*5e4c29a6SJohn Scipione delete gifLoad; 2819949213aSStephan Aßmus return B_NO_MEMORY; 2829949213aSStephan Aßmus } 283*5e4c29a6SJohn Scipione delete gifLoad; 2849949213aSStephan Aßmus } 2859949213aSStephan Aßmus 2869949213aSStephan Aßmus if (debug) { 2879949213aSStephan Aßmus now = system_time() - now; 288*5e4c29a6SJohn Scipione syslog(LOG_ERR, "Translate() - Translation took %Ld microseconds\n", 289*5e4c29a6SJohn Scipione now); 2909949213aSStephan Aßmus } 2919949213aSStephan Aßmus return B_OK; 2929949213aSStephan Aßmus } 2939949213aSStephan Aßmus 2949949213aSStephan Aßmus 295abfe23dcSPhilippe Saint-Pierre BTranslator* 296abfe23dcSPhilippe Saint-Pierre make_nth_translator(int32 n, image_id you, uint32 flags, ...) 2979949213aSStephan Aßmus { 298abfe23dcSPhilippe Saint-Pierre if (n == 0) 299abfe23dcSPhilippe Saint-Pierre return new GIFTranslator(); 300abfe23dcSPhilippe Saint-Pierre 301abfe23dcSPhilippe Saint-Pierre return NULL; 302abfe23dcSPhilippe Saint-Pierre } 303abfe23dcSPhilippe Saint-Pierre 304abfe23dcSPhilippe Saint-Pierre 305abfe23dcSPhilippe Saint-Pierre GIFTranslator::GIFTranslator() 306*5e4c29a6SJohn Scipione : 307*5e4c29a6SJohn Scipione BaseTranslator(B_TRANSLATE("GIF images"), 308abfe23dcSPhilippe Saint-Pierre B_TRANSLATE("GIF image translator"), 309abfe23dcSPhilippe Saint-Pierre GIF_TRANSLATOR_VERSION, 310abfe23dcSPhilippe Saint-Pierre sInputFormats, kNumInputFormats, 311abfe23dcSPhilippe Saint-Pierre sOutputFormats, kNumOutputFormats, 312abfe23dcSPhilippe Saint-Pierre "GIFTranslator_Settings", 313abfe23dcSPhilippe Saint-Pierre sDefaultSettings, kNumDefaultSettings, 314abfe23dcSPhilippe Saint-Pierre B_TRANSLATOR_BITMAP, B_GIF_FORMAT) 315abfe23dcSPhilippe Saint-Pierre { 316abfe23dcSPhilippe Saint-Pierre } 317abfe23dcSPhilippe Saint-Pierre 318abfe23dcSPhilippe Saint-Pierre 319abfe23dcSPhilippe Saint-Pierre GIFTranslator::~GIFTranslator() 320abfe23dcSPhilippe Saint-Pierre { 321abfe23dcSPhilippe Saint-Pierre } 322abfe23dcSPhilippe Saint-Pierre 323abfe23dcSPhilippe Saint-Pierre 324abfe23dcSPhilippe Saint-Pierre BView* 325abfe23dcSPhilippe Saint-Pierre GIFTranslator::NewConfigView(TranslatorSettings* settings) 326abfe23dcSPhilippe Saint-Pierre { 327abfe23dcSPhilippe Saint-Pierre return new GIFView(settings); 3289949213aSStephan Aßmus } 3299949213aSStephan Aßmus 3309949213aSStephan Aßmus 3319949213aSStephan Aßmus int 3329949213aSStephan Aßmus main() 3339949213aSStephan Aßmus { 334abfe23dcSPhilippe Saint-Pierre BApplication app("application/x-vnd.Haiku-GIFTranslator"); 335*5e4c29a6SJohn Scipione status_t result = LaunchTranslatorWindow(new GIFTranslator, 336abfe23dcSPhilippe Saint-Pierre B_TRANSLATE("GIF Settings"), kRectView); 337abfe23dcSPhilippe Saint-Pierre if (result == B_OK) { 338abfe23dcSPhilippe Saint-Pierre app.Run(); 3399949213aSStephan Aßmus return 0; 340*5e4c29a6SJohn Scipione } 341*5e4c29a6SJohn Scipione 342abfe23dcSPhilippe Saint-Pierre return 1; 3439949213aSStephan Aßmus } 344