18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2007 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * its contributors may be used to endorse or promote products derived 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * from this software without specific prior written permission. 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebKitNSStringExtras.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import <WebCore/Font.h> 320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import <WebCore/GraphicsContext.h> 33ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#import <WebCore/TextRun.h> 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <WebCore/WebCoreNSStringExtras.h> 350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import <WebKit/WebNSFileManagerExtras.h> 360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#import <WebKit/WebNSObjectExtras.h> 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <unicode/uchar.h> 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <sys/param.h> 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochNSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache"; 410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline CGFloat webkit_CGCeiling(CGFloat value) 430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (sizeof(value) == sizeof(float)) 450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ceilf(value); 460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ceil(value); 470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochusing namespace WebCore; 500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation NSString (WebKitExtras) 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic BOOL canUseFastRenderer(const UniChar *buffer, unsigned length) 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned i; 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (i = 0; i < length; i++) { 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UCharDirection direction = u_charDirection(buffer[i]); 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (direction == U_RIGHT_TO_LEFT || direction > U_OTHER_NEUTRAL) 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NO; 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return YES; 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 64563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark- (void)_web_drawAtPoint:(NSPoint)point font:(NSFont *)font textColor:(NSColor *)textColor 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 66967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch [self _web_drawAtPoint:point font:font textColor:textColor allowingFontSmoothing:YES]; 67967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 68967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 69967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch- (void)_web_drawAtPoint:(NSPoint)point font:(NSFont *)font textColor:(NSColor *)textColor allowingFontSmoothing:(BOOL)fontSmoothingIsAllowed 70967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned length = [self length]; 720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Vector<UniChar, 2048> buffer(length); 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch [self getCharacters:buffer.data()]; 75967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (canUseFastRenderer(buffer.data(), length)) { 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The following is a half-assed attempt to match AppKit's rounding rules for drawAtPoint. 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It's probably incorrect for high DPI. 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If you change this, be sure to test all the text drawn this way in Safari, including 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the status bar, bookmarks bar, tab bar, and activity window. 810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch point.y = webkit_CGCeiling(point.y); 820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NSGraphicsContext *nsContext = [NSGraphicsContext currentContext]; 840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGContextRef cgContext = static_cast<CGContextRef>([nsContext graphicsPort]); 850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch GraphicsContext graphicsContext(cgContext); 860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Safari doesn't flip the NSGraphicsContext before calling WebKit, yet WebCore requires a flipped graphics context. 880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch BOOL flipped = [nsContext isFlipped]; 890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!flipped) 900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGContextScaleCTM(cgContext, 1, -1); 910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Font webCoreFont(FontPlatformData(font, [font pointSize]), ![nsContext isDrawingToScreen], fontSmoothingIsAllowed ? AutoSmoothing : Antialiased); 930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch TextRun run(buffer.data(), length); 940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGFloat red; 960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGFloat green; 970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGFloat blue; 980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGFloat alpha; 990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch [[textColor colorUsingColorSpaceName:NSDeviceRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha]; 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch graphicsContext.setFillColor(makeRGBA(red * 255, green * 255, blue * 255, alpha * 255), ColorSpaceDeviceRGB); 1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch webCoreFont.drawText(&graphicsContext, run, FloatPoint(point.x, (flipped ? point.y : (-1 * point.y)))); 1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!flipped) 1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch CGContextScaleCTM(cgContext, 1, -1); 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The given point is on the baseline. 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([[NSView focusView] isFlipped]) 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project point.y -= [font ascender]; 1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project point.y += [font descender]; 1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [self drawAtPoint:point withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, textColor, NSForegroundColorAttributeName, nil]]; 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_web_drawDoubledAtPoint:(NSPoint)textPoint 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project withTopColor:(NSColor *)topColor 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bottomColor:(NSColor *)bottomColor 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project font:(NSFont *)font 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // turn off font smoothing so translucent text draws correctly (Radar 3118455) 123967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch [self _web_drawAtPoint:textPoint font:font textColor:bottomColor allowingFontSmoothing:NO]; 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textPoint.y += 1; 126967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch [self _web_drawAtPoint:textPoint font:font textColor:topColor allowingFontSmoothing:NO]; 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (float)_web_widthWithFont:(NSFont *)font 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned length = [self length]; 1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Vector<UniChar, 2048> buffer(length); 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch [self getCharacters:buffer.data()]; 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (canUseFastRenderer(buffer.data(), length)) { 1376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Font webCoreFont(FontPlatformData(font, [font pointSize]), ![[NSGraphicsContext currentContext] isDrawingToScreen]); 1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch TextRun run(buffer.data(), length); 13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return webCoreFont.width(run); 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return [self sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]].width; 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)_web_stringByAbbreviatingWithTildeInPath 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *resolvedHomeDirectory = [NSHomeDirectory() stringByResolvingSymlinksInPath]; 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *path; 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([self hasPrefix:resolvedHomeDirectory]) { 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *relativePath = [self substringFromIndex:[resolvedHomeDirectory length]]; 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project path = [NSHomeDirectory() stringByAppendingPathComponent:relativePath]; 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project path = self; 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [path stringByAbbreviatingWithTildeInPath]; 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)_web_stringByStrippingReturnCharacters 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableString *newString = [[self mutableCopy] autorelease]; 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [newString replaceOccurrencesOfString:@"\r" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [newString length])]; 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [newString replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [newString length])]; 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return newString; 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (NSStringEncoding)_web_encodingForResource:(Handle)resource 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return CFStringConvertEncodingToNSStringEncoding(stringEncodingForResource(resource)); 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (BOOL)_webkit_isCaseInsensitiveEqualToString:(NSString *)string 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return stringIsCaseInsensitiveEqualToString(self, string); 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(BOOL)_webkit_hasCaseInsensitivePrefix:(NSString *)prefix 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [self rangeOfString:prefix options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound; 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(BOOL)_webkit_hasCaseInsensitiveSuffix:(NSString *)suffix 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return hasCaseInsensitiveSuffix(self, suffix); 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(BOOL)_webkit_hasCaseInsensitiveSubstring:(NSString *)substring 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return hasCaseInsensitiveSubstring(self, substring); 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(NSString *)_webkit_filenameByFixingIllegalCharacters 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return filenameByFixingIllegalCharacters(self); 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(NSString *)_webkit_stringByTrimmingWhitespace 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableString *trimmed = [[self mutableCopy] autorelease]; 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFStringTrimWhitespace((CFMutableStringRef)trimmed); 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return trimmed; 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)_webkit_stringByCollapsingNonPrintingCharacters 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableString *result = [NSMutableString string]; 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static NSCharacterSet *charactersToTurnIntoSpaces = nil; 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static NSCharacterSet *charactersToNotTurnIntoSpaces = nil; 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (charactersToTurnIntoSpaces == nil) { 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableCharacterSet *set = [[NSMutableCharacterSet alloc] init]; 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [set addCharactersInRange:NSMakeRange(0x00, 0x21)]; 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [set addCharactersInRange:NSMakeRange(0x7F, 0x01)]; 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project charactersToTurnIntoSpaces = [set copy]; 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [set release]; 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project charactersToNotTurnIntoSpaces = [[charactersToTurnIntoSpaces invertedSet] retain]; 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned length = [self length]; 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned position = 0; 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (position != length) { 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSRange nonSpace = [self rangeOfCharacterFromSet:charactersToNotTurnIntoSpaces 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project options:0 range:NSMakeRange(position, length - position)]; 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nonSpace.location == NSNotFound) { 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSRange space = [self rangeOfCharacterFromSet:charactersToTurnIntoSpaces 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project options:0 range:NSMakeRange(nonSpace.location, length - nonSpace.location)]; 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (space.location == NSNotFound) { 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project space.location = length; 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (space.location > nonSpace.location) { 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (position != 0) { 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [result appendString:@" "]; 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [result appendString:[self substringWithRange: 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMakeRange(nonSpace.location, space.location - nonSpace.location)]]; 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project position = space.location; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return result; 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)_webkit_stringByCollapsingWhitespaceCharacters 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableString *result = [[NSMutableString alloc] initWithCapacity:[self length]]; 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSCharacterSet *spaces = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static NSCharacterSet *notSpaces = nil; 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (notSpaces == nil) 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notSpaces = [[spaces invertedSet] retain]; 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned length = [self length]; 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned position = 0; 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (position != length) { 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSRange nonSpace = [self rangeOfCharacterFromSet:notSpaces options:0 range:NSMakeRange(position, length - position)]; 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nonSpace.location == NSNotFound) 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSRange space = [self rangeOfCharacterFromSet:spaces options:0 range:NSMakeRange(nonSpace.location, length - nonSpace.location)]; 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (space.location == NSNotFound) 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project space.location = length; 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (space.location > nonSpace.location) { 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (position != 0) 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [result appendString:@" "]; 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [result appendString:[self substringWithRange:NSMakeRange(nonSpace.location, space.location - nonSpace.location)]]; 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project position = space.location; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [result autorelease]; 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(NSString *)_webkit_fixedCarbonPOSIXPath 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSFileManager *fileManager = [NSFileManager defaultManager]; 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([fileManager fileExistsAtPath:self]) { 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Files exists, no need to fix. 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return self; 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSMutableArray *pathComponents = [[[self pathComponents] mutableCopy] autorelease]; 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *volumeName = [pathComponents objectAtIndex:1]; 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([volumeName isEqualToString:@"Volumes"]) { 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Path starts with "/Volumes", so the volume name is the next path component. 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project volumeName = [pathComponents objectAtIndex:2]; 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove "Volumes" from the path because it may incorrectly be part of the path (3163647). 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We'll add it back if we have to. 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [pathComponents removeObjectAtIndex:1]; 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!volumeName) { 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Should only happen if self == "/", so this shouldn't happen because that always exists. 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return self; 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ([[fileManager _webkit_startupVolumeName] isEqualToString:volumeName]) { 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Startup volume name is included in path, remove it. 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [pathComponents removeObjectAtIndex:1]; 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if ([[fileManager contentsOfDirectoryAtPath:@"/Volumes" error:NULL] containsObject:volumeName]) { 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Path starts with other volume name, prepend "/Volumes". 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project [pathComponents insertObject:@"Volumes" atIndex:1]; 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It's valid. 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return self; 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NSString *path = [NSString pathWithComponents:pathComponents]; 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (![fileManager fileExistsAtPath:path]) 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // File at canonicalized path doesn't exist, return original. 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return self; 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return path; 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (NSString *)_webkit_localCacheDirectoryWithBundleIdentifier:(NSString*)bundleIdentifier 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NSString *cacheDir = [defaults objectForKey:WebKitLocalCacheDefaultsKey]; 3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!cacheDir || ![cacheDir isKindOfClass:[NSString class]]) { 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER 3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch char cacheDirectory[MAXPATHLEN]; 3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t cacheDirectoryLen = confstr(_CS_DARWIN_USER_CACHE_DIR, cacheDirectory, MAXPATHLEN); 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (cacheDirectoryLen) 3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cacheDir = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:cacheDirectory length:cacheDirectoryLen - 1]; 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return [cacheDir stringByAppendingPathComponent:bundleIdentifier]; 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end 344