RetainPtr<CFStringRef> StringImpl::createCFString() { // Since garbage collection isn't compatible with custom allocators, we // can't use the NoCopy variants of CFStringCreate*() when GC is enabled. if (!m_length || !isMainThread() || garbageCollectionEnabled()) { if (is8Bit()) return adoptCF(CFStringCreateWithBytes(0, reinterpret_cast<const UInt8*>(characters8()), m_length, kCFStringEncodingISOLatin1, false)); return adoptCF(CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(characters16()), m_length)); } CFAllocatorRef allocator = StringWrapperCFAllocator::allocator(); // Put pointer to the StringImpl in a global so the allocator can store it with the CFString. ASSERT(!StringWrapperCFAllocator::currentString); StringWrapperCFAllocator::currentString = this; CFStringRef string; if (is8Bit()) string = CFStringCreateWithBytesNoCopy(allocator, reinterpret_cast<const UInt8*>(characters8()), m_length, kCFStringEncodingISOLatin1, false, kCFAllocatorNull); else string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<const UniChar*>(characters16()), m_length, kCFAllocatorNull); // CoreFoundation might not have to allocate anything, we clear currentString in case we did not execute allocate(). StringWrapperCFAllocator::currentString = 0; return adoptCF(string); }
size_t lastHyphenLocation(const UChar* characters, size_t length, size_t beforeIndex, const AtomicString& localeIdentifier) { RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, characters, length, kCFAllocatorNull)); DEFINE_STATIC_LOCAL(AtomicStringKeyedMRUCache<RetainPtr<CFLocaleRef> >, cfLocaleCache, ()); RetainPtr<CFLocaleRef> locale = cfLocaleCache.get(localeIdentifier); CFIndex result = CFStringGetHyphenationLocationBeforeIndex(string.get(), beforeIndex, CFRangeMake(0, length), 0, locale.get(), 0); return result == kCFNotFound ? 0 : result; }
const char *Tcl_UniCharToUtfDString(Tcl_UniChar *characters, size_t length, Tcl_DString *ds) { CFStringRef str = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,characters, length, kCFAllocatorNull); CFRange range = {0,length}; // all the characters CFIndex bufLen = 0; CFStringGetBytes(str, range, kCFStringEncodingUTF8, true, false, NULL, 0, &bufLen); *ds = (malloc(bufLen)); CFStringGetBytes(str, range, kCFStringEncodingUTF8, true, false, *ds, bufLen, &bufLen); CFRelease(str); return (const char *)*ds; }
void decideDestinationWithSuggestedObjectNameCallback(CFURLDownloadRef cfURLDownloadRef, CFStringRef objectName, const void* clientInfo) { Download* download = downloadFromClientInfo(clientInfo); bool allowOverwrite; String destination = download->decideDestinationWithSuggestedFilename(objectName, allowOverwrite); if (destination.isNull()) return; RetainPtr<CFStringRef> cfPath(AdoptCF, CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar*>(destination.characters()), destination.length(), kCFAllocatorNull)); RetainPtr<CFURLRef> pathURL(AdoptCF, CFURLCreateWithFileSystemPath(0, cfPath.get(), kCFURLWindowsPathStyle, false)); CFURLDownloadSetDestination(cfURLDownloadRef, pathURL.get(), allowOverwrite); }
NatronCFString::operator CFStringRef() const { if (!type) { const_cast<NatronCFString*>(this)->type = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>( string.unicode() ), string.length(), kCFAllocatorNull); } return type; }
CFCharacterSetRef _CFCreateCharacterSetFromUSet(USet *set) { UErrorCode icuErr = U_ZERO_ERROR; CFMutableCharacterSetRef working = CFCharacterSetCreateMutable(NULL); UChar buffer[2048]; // Suitable for most small sets int32_t stringLen; if (working == NULL) return NULL; int32_t itemCount = uset_getItemCount(set); int32_t i; for (i = 0; i < itemCount; ++i) { UChar32 start, end; UChar * string; string = buffer; stringLen = uset_getItem(set, i, &start, &end, buffer, sizeof(buffer)/sizeof(UChar), &icuErr); if (icuErr == U_BUFFER_OVERFLOW_ERROR) { string = (UChar *) malloc(sizeof(UChar)*(stringLen+1)); if (!string) { CFRelease(working); return NULL; } icuErr = U_ZERO_ERROR; (void) uset_getItem(set, i, &start, &end, string, stringLen+1, &icuErr); } if (U_FAILURE(icuErr)) { if (string != buffer) free(string); CFRelease(working); return NULL; } if (stringLen <= 0) CFCharacterSetAddCharactersInRange(working, CFRangeMake(start, end-start+1)); else { CFStringRef cfString = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, (UniChar *)string, stringLen, kCFAllocatorNull); CFCharacterSetAddCharactersInString(working, cfString); CFRelease(cfString); } if (string != buffer) free(string); } CFCharacterSetRef result = CFCharacterSetCreateCopy(kCFAllocatorSystemDefault, working); CFRelease(working); return result; }
QCFString::operator CFStringRef() const { if (!type) { if (string.d->data != string.d->array) const_cast<QCFString*>(this)->string.realloc(); // ### Qt5: do we really need this stupid user protection? const_cast<QCFString*>(this)->type = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(string.unicode()), string.length(), kCFAllocatorNull); } return type; }
void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) { if (!fontData) { // Create a run of missing glyphs from the primary font. m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr())); return; } if (m_fallbackFonts && fontData != m_font.primaryFont()) m_fallbackFonts->add(fontData); RetainPtr<CTLineRef> line; if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) { static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel }; const short ltrForcedEmbeddingLevelValue = 0; const short rtlForcedEmbeddingLevelValue = 1; static const void* ltrOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, <rForcedEmbeddingLevelValue) }; static const void* rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) }; static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) }; RetainPtr<CTTypesetterRef> typesetter(AdoptCF, wkCreateCTTypesetterWithUniCharProviderAndOptions(&provideStringAndAttributes, 0, &info, m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); #else RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, cp, length, kCFAllocatorNull)); RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()))); RetainPtr<CTTypesetterRef> typesetter(AdoptCF, CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); #endif line.adoptCF(CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0))); } else { ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) }; line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info)); } m_coreTextLines.append(line.get()); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); CFIndex runCount = CFArrayGetCount(runArray); for (CFIndex r = 0; r < runCount; r++) { CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r)); ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); CFRange runRange = CTRunGetStringRange(ctRun); m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length, runRange)); } }
void Download::didDecideDestination(const String& destination, bool allowOverwrite) { ASSERT(!destination.isEmpty()); if (destination.isEmpty()) return; m_allowOverwrite = allowOverwrite; m_destination = destination; m_bundlePath = destination + DownloadBundle::fileExtension(); RetainPtr<CFStringRef> bundlePath(AdoptCF, CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar*>(m_bundlePath.characters()), m_bundlePath.length(), kCFAllocatorNull)); RetainPtr<CFURLRef> bundlePathURL(AdoptCF, CFURLCreateWithFileSystemPath(0, bundlePath.get(), kCFURLWindowsPathStyle, false)); CFURLDownloadSetDestination(m_download.get(), bundlePathURL.get(), allowOverwrite); }
CFStringRef StringImpl::createCFString() { CFAllocatorRef allocator = (m_length && isMainThread()) ? StringWrapperCFAllocator::allocator() : 0; if (!allocator) return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(m_data), m_length); // Put pointer to the StringImpl in a global so the allocator can store it with the CFString. ASSERT(!StringWrapperCFAllocator::currentString); StringWrapperCFAllocator::currentString = this; CFStringRef string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<const UniChar*>(m_data), m_length, kCFAllocatorNull); // The allocator cleared the global when it read it, but also clear it here just in case. ASSERT(!StringWrapperCFAllocator::currentString); StringWrapperCFAllocator::currentString = 0; return string; }
static CFBundleRef createWebKitBundle() { if (CFBundleRef existingBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit"))) { CFRetain(existingBundle); return existingBundle; } wchar_t dllPathBuffer[MAX_PATH]; DWORD length = ::GetModuleFileNameW(instanceHandle(), dllPathBuffer, WTF_ARRAY_LENGTH(dllPathBuffer)); ASSERT(length); ASSERT(length < WTF_ARRAY_LENGTH(dllPathBuffer)); RetainPtr<CFStringRef> dllPath(AdoptCF, CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar*>(dllPathBuffer), length, kCFAllocatorNull)); RetainPtr<CFURLRef> dllURL(AdoptCF, CFURLCreateWithFileSystemPath(0, dllPath.get(), kCFURLWindowsPathStyle, false)); RetainPtr<CFURLRef> dllDirectoryURL(AdoptCF, CFURLCreateCopyDeletingLastPathComponent(0, dllURL.get())); RetainPtr<CFURLRef> resourcesDirectoryURL(AdoptCF, CFURLCreateCopyAppendingPathComponent(0, dllDirectoryURL.get(), CFSTR("WebKit.resources"), true)); return CFBundleCreate(0, resourcesDirectoryURL.get()); }
static void _CFStringTransformCopy(UReplaceable *rep, int32_t start, int32_t limit, int32_t dest) { CFMutableStringRef string = (CFMutableStringRef)rep; UniChar stack_text[BUFFER_SIZE]; UniChar *text = &stack_text[0]; if (limit - start > BUFFER_SIZE) { text = malloc(limit - start); if (text == NULL) { // we cant throw a NSException here, but return before anything blows up... DEBUG_LOG("ICU Internal failure occurred, we are out of memory: time to go cry in a corner now..."); return; } } CFStringGetCharacters(string, CFRangeMake(start, limit - start), text); CFStringRef insert = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, text, limit - start, kCFAllocatorNull); CFStringInsert(string, dest, insert); CFRelease(insert); if (text != &stack_text[0]) { free(text); } }
void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) { if (!fontData) { // Create a run of missing glyphs from the primary font. m_coreTextRuns.append(CoreTextRun(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr())); return; } RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull)); RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes())); RetainPtr<CTTypesetterRef> typesetter; if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) { static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel }; static const void* ltrOptionValues[] = { kCFBooleanFalse }; static const void* rtlOptionValues[] = { kCFBooleanTrue }; static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); } else typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get())); RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0))); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); CFIndex runCount = CFArrayGetCount(runArray); for (CFIndex r = 0; r < runCount; r++) { CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r)); ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); m_coreTextRuns.append(CoreTextRun(ctRun, fontData, cp, stringLocation, length)); } }
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { bool haveGlyphs = false; #ifndef BUILDING_ON_TIGER if (fontData->orientation() == Horizontal || fontData->isBrokenIdeographFont()) { Vector<CGGlyph, 512> glyphs(bufferLength); wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength); for (unsigned i = 0; i < length; ++i) { if (!glyphs[i]) setGlyphDataForIndex(offset + i, 0, 0); else { setGlyphDataForIndex(offset + i, glyphs[i], fontData); haveGlyphs = true; } } } else { // We ask CoreText for possible vertical variant glyphs RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0))); RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get())); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); CFIndex runCount = CFArrayGetCount(runArray); // Initialize glyph entries for (unsigned index = 0; index < length; ++index) setGlyphDataForIndex(offset + index, 0, 0); Vector<CGGlyph, 512> glyphVector; Vector<CFIndex, 512> indexVector; bool done = false; for (CFIndex r = 0; r < runCount && !done ; ++r) { // CTLine could map characters over multiple fonts using its own font fallback list. // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont(). CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r)); ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); CFDictionaryRef attributes = CTRunGetAttributes(ctRun); CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName)); RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0)); // Use CGFont here as CFEqual for CTFont counts all attributes for font. if (CFEqual(fontData->platformData().cgFont(), runCGFont.get())) { // This run uses the font we want. Extract glyphs. CFIndex glyphCount = CTRunGetGlyphCount(ctRun); const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun); if (!glyphs) { glyphVector.resize(glyphCount); CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data()); glyphs = glyphVector.data(); } const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun); if (!stringIndices) { indexVector.resize(glyphCount); CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data()); stringIndices = indexVector.data(); } for (CFIndex i = 0; i < glyphCount; ++i) { if (stringIndices[i] >= static_cast<CFIndex>(length)) { done = true; break; } if (glyphs[i]) { setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData); haveGlyphs = true; } } } } } #else // Use an array of long so we get good enough alignment. long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)]; OSStatus status = wkInitializeGlyphVector(GlyphPage::size, &glyphVector); if (status != noErr) // This should never happen, perhaps indicates a bad font! If it does the // font substitution code will find an alternate font. return false; wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector); unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector); if (numGlyphs != length) { // This should never happen, perhaps indicates a bad font? // If it does happen, the font substitution code will find an alternate font. wkClearGlyphVector(&glyphVector); return false; } ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector); for (unsigned i = 0; i < length; i++) { Glyph glyph = glyphRecord->glyphID; if (!glyph) setGlyphDataForIndex(offset + i, 0, 0); else { setGlyphDataForIndex(offset + i, glyph, fontData); haveGlyphs = true; } glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector)); } wkClearGlyphVector(&glyphVector); #endif return haveGlyphs; }
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { bool haveGlyphs = false; if (!shouldUseCoreText(buffer, bufferLength, fontData)) { Vector<CGGlyph, 512> glyphs(bufferLength); CMFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength); // wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength); for (unsigned i = 0; i < length; ++i) { if (!glyphs[i]) setGlyphDataForIndex(offset + i, 0, 0); else { setGlyphDataForIndex(offset + i, glyphs[i], fontData); haveGlyphs = true; } } } else { // We ask CoreText for possible vertical variant glyphs RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal))); RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get())); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); CFIndex runCount = CFArrayGetCount(runArray); // Initialize glyph entries for (unsigned index = 0; index < length; ++index) setGlyphDataForIndex(offset + index, 0, 0); Vector<CGGlyph, 512> glyphVector; Vector<CFIndex, 512> indexVector; bool done = false; // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may // be non-CFEqual to fontData->platformData().cgFont(). RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0)); for (CFIndex r = 0; r < runCount && !done ; ++r) { // CTLine could map characters over multiple fonts using its own font fallback list. // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont(). CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r)); ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); CFDictionaryRef attributes = CTRunGetAttributes(ctRun); CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName)); RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0)); // Use CGFont here as CFEqual for CTFont counts all attributes for font. if (CFEqual(cgFont.get(), runCGFont.get())) { // This run uses the font we want. Extract glyphs. CFIndex glyphCount = CTRunGetGlyphCount(ctRun); const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun); if (!glyphs) { glyphVector.resize(glyphCount); CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data()); glyphs = glyphVector.data(); } const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun); if (!stringIndices) { indexVector.resize(glyphCount); CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data()); stringIndices = indexVector.data(); } for (CFIndex i = 0; i < glyphCount; ++i) { if (stringIndices[i] >= static_cast<CFIndex>(length)) { done = true; break; } if (glyphs[i]) { setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData); haveGlyphs = true; } } } } } return haveGlyphs; }
// Reads a length field + UTF-16 stream into a wchar_t wchar_t *ReadUnicodeString( std::istream &input, int maxLength, const wchar_t *safeString ) { int size = ReadPackedInt(input); if ( size == -1 ) { return NULL; } else if ( size < 0 || size > maxLength ) { return newStr(safeString); } else { #ifdef TARGET_OS_MACOSX UniChar *unichars = new UniChar[size]; wchar_t *wchars = new wchar_t[size+1]; CFStringRef utf16; for(int i = 0; i < size; i++) ReadNetworkValue( input, unichars[i] ); utf16 = CFStringCreateWithCharactersNoCopy(NULL, unichars, size, kCFAllocatorNull); CFStringGetBytes(utf16, CFRangeMake(0, CFStringGetLength(utf16)), kUTF32Encoding, '?', false, (UInt8 *)wchars, (size+1)*sizeof(wchar_t), NULL); wchars[size] = '\x0'; CFRelease(utf16); delete unichars; return wchars; #elif defined( TARGET_OS_LINUX ) size_t inBytesLeft = size * sizeof(unsigned short); char *utf16 = new char[inBytesLeft]; input.read( utf16, inBytesLeft ); char *inBuf = utf16; size_t bufferSize = size + 1; size_t outBytesLeft = bufferSize * 4; wchar_t *buf = new wchar_t[ bufferSize ]; char *outBuf = (char *) buf; buf[0] = L'\0'; iconv_t utf16_to_utf32 = iconv_open( "UTF32LE", "UTF16LE" ); if( utf16_to_utf32 == (iconv_t) -1 ) { perror( "Failed to open iconv" ); delete[] utf16; return buf; } size_t result = iconv( utf16_to_utf32, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft ); iconv_close( utf16_to_utf32 ); if( result == (size_t) -1 ) { perror( "Failed to convert stream to utf32le" ); delete[] utf16; return buf; } delete[] utf16; buf[size] = L'\x0'; return (wchar_t *) buf; #else wchar_t *string = new wchar_t [size+1]; for(int i = 0; i < size; i++) ReadNetworkValue( input, string[i] ); string[size] = '\x0'; return string; #endif } }
static inline UTransliterator *utrans_find(CFStringRef transform, UTransDirection dir, UErrorCode *error) { UEnumeration *uenum = NULL; UTransliterator *trans = NULL; do { uenum = utrans_openIDs(error); if (U_FAILURE(*error)) { DEBUG_LOG("%s", u_errorName(*error)); break; } int32_t count = uenum_count(uenum, error); if (U_FAILURE(*error)) { DEBUG_LOG("%s", u_errorName(*error)); break; } int32_t trans_idx = 0; while (trans_idx < count && trans == NULL) { int32_t idLen = 0; const UChar *uid = uenum_unext(uenum, &idLen, error); if (U_FAILURE(*error)) { DEBUG_LOG("%s", u_errorName(*error)); break; } // this seems rather unlikely since we should have already broken // by the trans_idx exceeding the count if (uid == NULL) { break; } CFStringRef name = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, uid, idLen, kCFAllocatorNull); // It would have been nice if these stirng constants were actually defined somewhere in icu, but sadly they are runtime metadata... if ((CFEqual(name, CFSTR("Any-Remove")) && CFEqual(transform, kCFStringTransformStripCombiningMarks)) || (CFEqual(name, CFSTR("Any-Latin")) && CFEqual(transform, kCFStringTransformToLatin)) || (CFEqual(name, CFSTR("Latin-Katakana")) && CFEqual(transform, kCFStringTransformLatinKatakana)) || (CFEqual(name, CFSTR("Latin-Hiragana")) && CFEqual(transform, kCFStringTransformLatinHiragana)) || (CFEqual(name, CFSTR("Hiragana-Katakana")) && CFEqual(transform, kCFStringTransformHiraganaKatakana)) || (CFEqual(name, CFSTR("Latin-Hangul")) && CFEqual(transform, kCFStringTransformLatinHangul)) || (CFEqual(name, CFSTR("Latin-Arabic")) && CFEqual(transform, kCFStringTransformLatinArabic)) || (CFEqual(name, CFSTR("Latin-Hebrew")) && CFEqual(transform, kCFStringTransformLatinHebrew)) || (CFEqual(name, CFSTR("Latin-Thai")) && CFEqual(transform, kCFStringTransformLatinThai)) || (CFEqual(name, CFSTR("Latin-Cyrillic")) && CFEqual(transform, kCFStringTransformLatinCyrillic)) || (CFEqual(name, CFSTR("Latin-Greek")) && CFEqual(transform, kCFStringTransformLatinGreek)) || (CFEqual(name, CFSTR("Any-Hex/XML")) && CFEqual(transform, kCFStringTransformToXMLHex)) || (CFEqual(name, CFSTR("Any-Name")) && CFEqual(transform, kCFStringTransformToUnicodeName)) || (CFEqual(name, CFSTR("Accents-Any")) && CFEqual(transform, kCFStringTransformStripDiacritics))) { trans = utrans_openU(uid, idLen, dir, NULL, 0, NULL, error); } CFRelease(name); trans_idx++; } } while (0); if (uenum != NULL) { uenum_reset(uenum, error); uenum_close(uenum); } if (trans == NULL && (CFEqual(transform, kCFStringTransformStripCombiningMarks) || CFEqual(transform, kCFStringTransformToLatin) || CFEqual(transform, kCFStringTransformLatinKatakana) || CFEqual(transform, kCFStringTransformLatinHiragana) || CFEqual(transform, kCFStringTransformHiraganaKatakana) || CFEqual(transform, kCFStringTransformLatinHangul) || CFEqual(transform, kCFStringTransformLatinArabic) || CFEqual(transform, kCFStringTransformLatinHebrew) || CFEqual(transform, kCFStringTransformLatinCyrillic) || CFEqual(transform, kCFStringTransformLatinGreek) || CFEqual(transform, kCFStringTransformToXMLHex) || CFEqual(transform, kCFStringTransformToUnicodeName) || CFEqual(transform, kCFStringTransformStripDiacritics))) { static dispatch_once_t once = 0L; dispatch_once(&once, ^{ RELEASE_LOG("Unable to find transliterators in icu data: likely this is from not including the Transliterators section in building your icu.dat file"); }); }
size_t wxMBConv_cf::FromWChar(char *dst, size_t dstSize, const wchar_t *src, size_t srcSize) const { wxCHECK(src, wxCONV_FAILED); if(srcSize == wxNO_LEN) srcSize = wxStrlen(src) + 1; // Temporary CFString wxCFRef<CFStringRef> theString; /* If we're compiling against Tiger headers we can support direct conversion * from UTF32. If we are then run against a pre-Tiger system, the encoding * won't be available so we'll defer to the UTF-32->UTF-16->string conversion. */ if(CFStringIsEncodingAvailable(wxCFStringEncodingWcharT)) { theString = wxCFRef<CFStringRef>(CFStringCreateWithBytes( kCFAllocatorDefault, (UInt8*)src, srcSize * sizeof(wchar_t), wxCFStringEncodingWcharT, false)); } else { wxMBConvUTF16 converter; size_t cbUniBuffer = converter.FromWChar( NULL, 0, src, srcSize ); wxASSERT(cbUniBuffer % sizeof(UniChar)); // Will be free'd by kCFAllocatorMalloc when CFString is released UniChar *tmpUniBuffer = (UniChar*)malloc(cbUniBuffer); cbUniBuffer = converter.FromWChar( (char*) tmpUniBuffer, cbUniBuffer, src, srcSize ); wxASSERT(cbUniBuffer % sizeof(UniChar)); theString = wxCFRef<CFStringRef>(CFStringCreateWithCharactersNoCopy( kCFAllocatorDefault, tmpUniBuffer, cbUniBuffer / sizeof(UniChar), kCFAllocatorMalloc )); } wxCHECK(theString != NULL, wxCONV_FAILED); CFIndex usedBufLen; CFIndex charsConverted = CFStringGetBytes( theString, CFRangeMake(0, CFStringGetLength(theString)), m_encoding, 0, // FAIL on unconvertible characters false, // not an external representation (UInt8*)dst, dstSize, &usedBufLen ); // when dst is non-NULL, we check usedBufLen against dstSize as // CFStringGetBytes sometimes treats dst as being NULL when dstSize==0 if( (charsConverted < CFStringGetLength(theString)) || (dst && (size_t) usedBufLen > dstSize) ) return wxCONV_FAILED; return usedBufLen; }
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const { bool haveGlyphs = false; Vector<CGGlyph, 512> glyphs(bufferLength); if (!shouldUseCoreText(buffer, bufferLength, this)) { CGFontGetGlyphsForUnichars(platformData().cgFont(), buffer, glyphs.data(), bufferLength); for (unsigned i = 0; i < length; ++i) { if (glyphs[i]) { pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this); haveGlyphs = true; } } } else if (!platformData().isCompositeFontReference() && platformData().widthVariant() != RegularWidth && CTFontGetGlyphsForCharacters(platformData().ctFont(), buffer, glyphs.data(), bufferLength)) { // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters // places the glyphs at indices corresponding to the first character of each pair. unsigned glyphStep = bufferLength / length; for (unsigned i = 0; i < length; ++i) { if (glyphs[i * glyphStep]) { pageToFill->setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], this); haveGlyphs = true; } } } else { // We ask CoreText for possible vertical variant glyphs RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), getCFStringAttributes(0, hasVerticalGlyphs() ? Vertical : Horizontal))); RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get())); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); CFIndex runCount = CFArrayGetCount(runArray); Vector<CGGlyph, 512> glyphVector; Vector<CFIndex, 512> indexVector; bool done = false; // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may // be non-CFEqual to platformData().cgFont(). RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0)); for (CFIndex r = 0; r < runCount && !done ; ++r) { // CTLine could map characters over multiple fonts using its own font fallback list. // We need to pick runs that use the exact font we need, i.e., platformData().ctFont(). CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r)); ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); CFDictionaryRef attributes = CTRunGetAttributes(ctRun); CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName)); RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0)); // Use CGFont here as CFEqual for CTFont counts all attributes for font. bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get()); if (gotBaseFont || platformData().isCompositeFontReference()) { // This run uses the font we want. Extract glyphs. CFIndex glyphCount = CTRunGetGlyphCount(ctRun); const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun); if (!glyphs) { glyphVector.resize(glyphCount); CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data()); glyphs = glyphVector.data(); } const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun); if (!stringIndices) { indexVector.resize(glyphCount); CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data()); stringIndices = indexVector.data(); } if (gotBaseFont) { for (CFIndex i = 0; i < glyphCount; ++i) { if (stringIndices[i] >= static_cast<CFIndex>(length)) { done = true; break; } if (glyphs[i]) { pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], this); haveGlyphs = true; } } } else { const SimpleFontData* runSimple = getCompositeFontReferenceFontData((NSFont *)runFont); if (runSimple) { for (CFIndex i = 0; i < glyphCount; ++i) { if (stringIndices[i] >= static_cast<CFIndex>(length)) { done = true; break; } if (glyphs[i]) { pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple); haveGlyphs = true; } } } } } } } return haveGlyphs; }
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { bool haveGlyphs = false; Vector<CGGlyph, 512> glyphs(bufferLength); if (!shouldUseCoreText(buffer, bufferLength, fontData)) { // We pass in either 256 or 512 UTF-16 characters: 256 for U+FFFF and less, 512 (double character surrogates) // for U+10000 and above. It is indeed possible to get back 512 glyphs back from the API, so the glyph buffer // we pass in must be 512. If we get back more than 256 glyphs though we'll ignore all the ones after 256, // this should not happen as the only time we pass in 512 characters is when they are surrogates. CGFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength); for (unsigned i = 0; i < length; ++i) { if (!glyphs[i]) setGlyphDataForIndex(offset + i, 0, 0); else { setGlyphDataForIndex(offset + i, glyphs[i], fontData); haveGlyphs = true; } } } else if (!fontData->platformData().isCompositeFontReference() && ((fontData->platformData().widthVariant() == RegularWidth) ? wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength) : CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength))) { // When buffer consists of surrogate pairs, wkGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters // place the glyphs at indices corresponding to the first character of each pair. unsigned glyphStep = bufferLength / length; for (unsigned i = 0; i < length; ++i) { if (!glyphs[i * glyphStep]) setGlyphDataForIndex(offset + i, 0, 0); else { setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], fontData); haveGlyphs = true; } } } else { // We ask CoreText for possible vertical variant glyphs RetainPtr<CFStringRef> string = adoptCF(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); RetainPtr<CFAttributedStringRef> attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal))); RetainPtr<CTLineRef> line = adoptCF(CTLineCreateWithAttributedString(attributedString.get())); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); CFIndex runCount = CFArrayGetCount(runArray); // Initialize glyph entries for (unsigned index = 0; index < length; ++index) setGlyphDataForIndex(offset + index, 0, 0); Vector<CGGlyph, 512> glyphVector; Vector<CFIndex, 512> indexVector; bool done = false; // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may // be non-CFEqual to fontData->platformData().cgFont(). RetainPtr<CGFontRef> cgFont = adoptCF(CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0)); for (CFIndex r = 0; r < runCount && !done ; ++r) { // CTLine could map characters over multiple fonts using its own font fallback list. // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont(). CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r)); ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); CFDictionaryRef attributes = CTRunGetAttributes(ctRun); CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName)); RetainPtr<CGFontRef> runCGFont = adoptCF(CTFontCopyGraphicsFont(runFont, 0)); // Use CGFont here as CFEqual for CTFont counts all attributes for font. bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get()); if (gotBaseFont || fontData->platformData().isCompositeFontReference()) { // This run uses the font we want. Extract glyphs. CFIndex glyphCount = CTRunGetGlyphCount(ctRun); const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun); if (!glyphs) { glyphVector.resize(glyphCount); CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data()); glyphs = glyphVector.data(); } const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun); if (!stringIndices) { indexVector.resize(glyphCount); CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data()); stringIndices = indexVector.data(); } if (gotBaseFont) { for (CFIndex i = 0; i < glyphCount; ++i) { if (stringIndices[i] >= static_cast<CFIndex>(length)) { done = true; break; } if (glyphs[i]) { setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData); haveGlyphs = true; } } #if !PLATFORM(IOS) } else { const SimpleFontData* runSimple = fontData->getCompositeFontReferenceFontData((NSFont *)runFont); if (runSimple) { for (CFIndex i = 0; i < glyphCount; ++i) { if (stringIndices[i] >= static_cast<CFIndex>(length)) { done = true; break; } if (glyphs[i]) { setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple); haveGlyphs = true; } } } #endif // !PLATFORM(IOS) } } } } return haveGlyphs; }
static void _CFStringTransformReplace(UReplaceable *rep, int32_t start, int32_t limit, const UChar* text, int32_t textLength) { CFMutableStringRef string = (CFMutableStringRef)rep; CFStringRef replacement = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, text, textLength, kCFAllocatorNull); CFStringReplace(string, CFRangeMake(start, limit - start), replacement); CFRelease(replacement); }
URL_TYPE createURLByMakingDirectoryAtURLWithName(URL_TYPE parent, STRING_TYPE name) { CFURLRef newDirectory = NULL; CFAllocatorRef allocator = parent ? CFGetAllocator(parent) : name ? CFGetAllocator(name) : kCFAllocatorDefault; if (parent) parent = CFRetain(parent); else { char *cwdBytes = alloca(PATH_MAX); getcwd(cwdBytes, PATH_MAX); parent = CFURLCreateFromFileSystemRepresentation(allocator, (const unsigned char *)cwdBytes, strlen(cwdBytes), /*isDirectory*/ true); if (!name) { newDirectory = parent; goto end; } } if (!parent) NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: parent directory URL is NULL (please tell the Growl developers)\n"), parent); else { if (name) name = CFRetain(name); else { name = CFURLCopyLastPathComponent(parent); CFURLRef newParent = CFURLCreateCopyDeletingLastPathComponent(allocator, parent); CFRelease(parent); parent = newParent; } if (!name) NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: name of directory to create is NULL (please tell the Growl developers)\n"), parent); else { FSRef parentRef; if (!CFURLGetFSRef(parent, &parentRef)) NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: could not create FSRef for parent directory at %@ (please tell the Growl developers)\n"), parent); else { FSRef newDirectoryRef; struct HFSUniStr255 nameUnicode; CFRange range = { 0, MIN(CFStringGetLength(name), USHRT_MAX) }; CFStringGetCharacters(name, range, nameUnicode.unicode); nameUnicode.length = range.length; struct FSRefParam refPB = { .ref = &parentRef, .nameLength = nameUnicode.length, .name = nameUnicode.unicode, .whichInfo = kFSCatInfoNone, .catInfo = NULL, .textEncodingHint = kTextEncodingUnknown, .newRef = &newDirectoryRef, }; OSStatus err = PBCreateDirectoryUnicodeSync(&refPB); if (err == dupFNErr) { //dupFNErr == file (or folder) exists already. this is fine. err = PBMakeFSRefUnicodeSync(&refPB); } if (err == noErr) { NSLog(CFSTR("PBCreateDirectoryUnicodeSync or PBMakeFSRefUnicodeSync returned %li; calling CFURLCreateFromFSRef"), (long)err); //XXX newDirectory = CFURLCreateFromFSRef(allocator, &newDirectoryRef); NSLog(CFSTR("CFURLCreateFromFSRef returned %@"), newDirectory); //XXX } else NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: could not create directory '%@' in parent directory at %@: FSCreateDirectoryUnicode returned %li (please tell the Growl developers)"), name, parent, (long)err); } CFRelease(parent); } //if (name) CFRelease(name); } //if (parent) end: return newDirectory; } #ifndef COPYFORK_BUFSIZE # define COPYFORK_BUFSIZE 5242880U /*5 MiB*/ #endif static OSStatus copyFork(const struct HFSUniStr255 *forkName, const FSRef *srcFile, const FSRef *destDir, const struct HFSUniStr255 *destName, FSRef *outDestFile) { OSStatus err, closeErr; struct FSForkIOParam srcPB = { .ref = srcFile, .forkNameLength = forkName->length, .forkName = forkName->unicode, .permissions = fsRdPerm, }; unsigned char debuggingPathBuf[PATH_MAX] = ""; OSStatus debuggingPathErr; err = PBOpenForkSync(&srcPB); if (err != noErr) { debuggingPathErr = FSRefMakePath(srcFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBOpenForkSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } else { FSRef destFile; /*the first thing to do is get the name of the destination file, if one * wasn't provided. *and while we're at it, we get the catalogue info as well. */ struct FSCatalogInfo catInfo; struct FSRefParam refPB = { .ref = srcFile, .whichInfo = kFSCatInfoGettableInfo & kFSCatInfoSettableInfo, .catInfo = &catInfo, .spec = NULL, .parentRef = NULL, .outName = destName ? NULL : (struct HFSUniStr255 *)(destName = alloca(sizeof(struct HFSUniStr255))), }; err = PBGetCatalogInfoSync(&refPB); if (err != noErr) { debuggingPathErr = FSRefMakePath(srcFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBGetCatalogInfoSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } else { refPB.ref = destDir; refPB.nameLength = destName->length; refPB.name = destName->unicode; refPB.textEncodingHint = kTextEncodingUnknown; refPB.newRef = &destFile; const char *functionName = "PBMakeFSRefUnicodeSync"; //for error-reporting message err = PBMakeFSRefUnicodeSync(&refPB); if ((err != noErr) && (err != fnfErr)) { handleMakeFSRefError: debuggingPathErr = FSRefMakePath(destDir, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for destination directory: FSRefMakePath returned %li)", (long)debuggingPathErr); //get filename too CFStringRef debuggingFilename = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, destName->unicode, destName->length, /*contentsDeallocator*/ kCFAllocatorNull); if (!debuggingFilename) debuggingFilename = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, "(could not get filename for destination file: CFStringCreateWithCharactersNoCopy returned NULL)", kCFStringEncodingASCII, /*contentsDeallocator*/ kCFAllocatorNull); NSLog(CFSTR("in copyFork in CFGrowlAdditions: %s (destination: %s/%@) returned %li"), functionName, debuggingPathBuf, debuggingFilename, (long)err); if (debuggingFilename) CFRelease(debuggingFilename); } else { //that file doesn't exist in that folder; create it. err = PBCreateFileUnicodeSync(&refPB); if (err == noErr) { /*make sure the Finder knows about the new file. *FNNotify returns a status code too, but this isn't an * essential step, so we just ignore it. */ FNNotify(destDir, kFNDirectoryModifiedMessage, kNilOptions); } else if (err == dupFNErr) { /*dupFNErr: the file already exists. *we can safely ignore this error. */ err = noErr; } else { functionName = "PBCreateFileUnicodeSync"; goto handleMakeFSRefError; } } } if (err == noErr) { if (outDestFile) memcpy(outDestFile, &destFile, sizeof(destFile)); struct FSForkIOParam destPB = { .ref = &destFile, .forkNameLength = forkName->length, .forkName = forkName->unicode, .permissions = fsWrPerm, }; err = PBOpenForkSync(&destPB); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBOpenForkSync (dest) returned %li"), (long)err); if (err != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for dest file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBOpenForkSync (destination: %s) returned %li"), debuggingPathBuf, (long)err); } else { void *buf = malloc(COPYFORK_BUFSIZE); if (buf) { srcPB.buffer = destPB.buffer = buf; srcPB.requestCount = COPYFORK_BUFSIZE; while (err == noErr) { err = PBReadForkSync(&srcPB); if (err == eofErr) { err = noErr; if (srcPB.actualCount == 0) break; } if (err != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBReadForkSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } else { destPB.requestCount = srcPB.actualCount; err = PBWriteForkSync(&destPB); if (err != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for dest file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBWriteForkSync (destination: %s) returned %li"), debuggingPathBuf, (long)err); } } } free(buf); } closeErr = PBCloseForkSync(&destPB); if (closeErr != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for dest file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBCloseForkSync (destination: %s) returned %li"), debuggingPathBuf, (long)err); } if (err == noErr) err = closeErr; } } closeErr = PBCloseForkSync(&srcPB); if (closeErr != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBCloseForkSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } if (err == noErr) err = closeErr; } return err; } static OSStatus GrowlCopyObjectSync(const FSRef *fileRef, const FSRef *destRef, FSRef *destFileRef) { OSStatus err; struct HFSUniStr255 forkName; struct FSForkIOParam forkPB = { .ref = fileRef, .forkIterator = { .initialize = 0L }, .outForkName = &forkName, }; do { err = PBIterateForksSync(&forkPB); NSLog(CFSTR("PBIterateForksSync returned %li"), (long)err); if (err != noErr) { if (err != errFSNoMoreItems) NSLog(CFSTR("in GrowlCopyObjectSync in CFGrowlAdditions: PBIterateForksSync returned %li"), (long)err); } else { err = copyFork(&forkName, fileRef, destRef, /*destName*/ NULL, /*outDestFile*/ destFileRef); //copyFork prints its own error messages } } while (err == noErr); if (err == errFSNoMoreItems) err = noErr; return err; } CFURLRef createURLByCopyingFileFromURLToDirectoryURL(CFURLRef file, CFURLRef dest) { CFURLRef destFileURL = NULL; FSRef fileRef, destRef, destFileRef; Boolean gotFileRef = CFURLGetFSRef(file, &fileRef); Boolean gotDestRef = CFURLGetFSRef(dest, &destRef); if (!gotFileRef) NSLog(CFSTR("in createURLByCopyingFileFromURLToDirectoryURL in CFGrowlAdditions: CFURLGetFSRef failed with source URL %@"), file); else if (!gotDestRef) NSLog(CFSTR("in createURLByCopyingFileFromURLToDirectoryURL in CFGrowlAdditions: CFURLGetFSRef failed with destination URL %@"), dest); else { OSStatus err; /* * 10.2 has a problem with weak symbols in frameworks so we use * MAC_OS_X_VERSION_MIN_REQUIRED >= 10.3. */ #if defined(NSAppKitVersionNumber10_3) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 if (FSCopyObjectSync) { err = FSCopyObjectSync(&fileRef, &destRef, /*destName*/ NULL, &destFileRef, kFSFileOperationOverwrite); } else { #endif err = GrowlCopyObjectSync(&fileRef, &destRef, &destFileRef); #if defined(NSAppKitVersionNumber10_3) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 } #endif if (err == noErr) destFileURL = CFURLCreateFromFSRef(kCFAllocatorDefault, &destFileRef); else NSLog(CFSTR("in createURLByCopyingFileFromURLToDirectoryURL in CFGrowlAdditions: CopyObjectSync returned %li for source URL %@"), (long)err, file); } return destFileURL; }
/*! * @brief Escape a string for HTML. */ CFStringRef createStringByEscapingForHTML(CFStringRef theString) { Boolean freeWhenDone; unsigned j = 0U; CFIndex count = CFStringGetLength(theString); UniChar c; UniChar *inbuffer = (UniChar *)CFStringGetCharactersPtr(theString); // worst case is a string consisting only of newlines or apostrophes UniChar *outbuffer = (UniChar *)malloc(6 * count * sizeof(UniChar)); if (inbuffer) { freeWhenDone = false; } else { CFRange range; range.location = 0U; range.length = count; freeWhenDone = true; inbuffer = (UniChar *)malloc(count * sizeof(UniChar)); CFStringGetCharacters(theString, range, inbuffer); } for (CFIndex i=0; i < count; ++i) { switch ((c=inbuffer[i])) { default: outbuffer[j++] = c; break; case '&': outbuffer[j++] = '&'; outbuffer[j++] = 'a'; outbuffer[j++] = 'm'; outbuffer[j++] = 'p'; outbuffer[j++] = ';'; break; case '"': outbuffer[j++] = '&'; outbuffer[j++] = 'q'; outbuffer[j++] = 'u'; outbuffer[j++] = 'o'; outbuffer[j++] = 't'; outbuffer[j++] = ';'; break; case '<': outbuffer[j++] = '&'; outbuffer[j++] = 'l'; outbuffer[j++] = 't'; outbuffer[j++] = ';'; break; case '>': outbuffer[j++] = '&'; outbuffer[j++] = 'g'; outbuffer[j++] = 't'; outbuffer[j++] = ';'; break; case '\'': outbuffer[j++] = '&'; outbuffer[j++] = 'a'; outbuffer[j++] = 'p'; outbuffer[j++] = 'o'; outbuffer[j++] = 's'; outbuffer[j++] = ';'; break; case '\n': case '\r': outbuffer[j++] = '<'; outbuffer[j++] = 'b'; outbuffer[j++] = 'r'; outbuffer[j++] = ' '; outbuffer[j++] = '/'; outbuffer[j++] = '>'; break; } } if (freeWhenDone) free(inbuffer); return CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, outbuffer, j, kCFAllocatorMalloc); }