diff options
| author | nyamatongwe <unknown> | 2011-06-04 21:46:49 +1000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2011-06-04 21:46:49 +1000 | 
| commit | c53e82e6002f1edce443260d48e45688fbbca85c (patch) | |
| tree | 60de4594da696d4ac2ba1a1d27fbb336d5d07269 /cocoa | |
| parent | 1e8e06f21d6b2b74e0db767890058a48d9cc81b1 (diff) | |
| download | scintilla-mirror-c53e82e6002f1edce443260d48e45688fbbca85c.tar.gz | |
Added encoding-sensitive case folding.
Diffstat (limited to 'cocoa')
| -rw-r--r-- | cocoa/ScintillaCocoa.h | 1 | ||||
| -rw-r--r-- | cocoa/ScintillaCocoa.mm | 153 | 
2 files changed, 147 insertions, 7 deletions
| diff --git a/cocoa/ScintillaCocoa.h b/cocoa/ScintillaCocoa.h index a5d6575f4..639a714cc 100644 --- a/cocoa/ScintillaCocoa.h +++ b/cocoa/ScintillaCocoa.h @@ -122,6 +122,7 @@ protected:    virtual void Initialise();    virtual void Finalise(); +  virtual CaseFolder *CaseFolderForEncoding();    virtual std::string CaseMapString(const std::string &s, int caseMapping);  public:    ScintillaCocoa(NSView* view); diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm index 1bc062ced..9321666d8 100644 --- a/cocoa/ScintillaCocoa.mm +++ b/cocoa/ScintillaCocoa.mm @@ -256,25 +256,164 @@ void ScintillaCocoa::Finalise()  //--------------------------------------------------------------------------------------------------  /** + * Convert a core foundation string into an array of bytes in a particular encoding + */ + +static char *EncodedBytes(CFStringRef cfsRef, CFStringEncoding encoding) { +    CFRange rangeAll = {0, CFStringGetLength(cfsRef)}; +    CFIndex usedLen = 0; +    CFStringGetBytes(cfsRef, rangeAll, encoding, '?', +                     false, NULL, 0, &usedLen); +     +    char *buffer = new char[usedLen+1]; +    CFStringGetBytes(cfsRef, rangeAll, encoding, '?', +                     false, (UInt8 *)buffer,usedLen, NULL); +    buffer[usedLen] = '\0'; +    return buffer; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Case folders. + */ + +class CaseFolderUTF8 : public CaseFolderTable { +public: +	CaseFolderUTF8() { +		StandardASCII(); +	} +	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { +		if ((lenMixed == 1) && (sizeFolded > 0)) { +			folded[0] = mapping[static_cast<unsigned char>(mixed[0])]; +			return 1; +		} else { +            CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, +                                                         reinterpret_cast<const UInt8 *>(mixed),  +                                                         lenMixed, kCFStringEncodingUTF8, false); + +            NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch +                                                            locale:[NSLocale currentLocale]]; + +            const char *cpMapped = [sMapped UTF8String]; +			size_t lenMapped = strlen(cpMapped); +			if (lenMapped < sizeFolded) { +				memcpy(folded, cpMapped,  lenMapped); +			} else { +				lenMapped = 0; +			} +            CFRelease(cfsVal); +			return lenMapped; +		} +	} +}; + +class CaseFolderDBCS : public CaseFolderTable { +	CFStringEncoding encoding; +public: +	CaseFolderDBCS(CFStringEncoding encoding_) : encoding(encoding_) { +		StandardASCII(); +	} +	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { +		if ((lenMixed == 1) && (sizeFolded > 0)) { +			folded[0] = mapping[static_cast<unsigned char>(mixed[0])]; +			return 1; +		} else { +            CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, +                                                         reinterpret_cast<const UInt8 *>(mixed),  +                                                         lenMixed, encoding, false); + +            NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch +                                                                        locale:[NSLocale currentLocale]]; +             +            char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); + +			size_t lenMapped = strlen(encoded); +            if (lenMapped < sizeFolded) { +                memcpy(folded, encoded,  lenMapped); +            } else { +                folded[0] = '\0'; +                lenMapped = 1; +            } +            delete []encoded; +            CFRelease(cfsVal); +			return lenMapped; +		} +		// Something failed so return a single NUL byte +		folded[0] = '\0'; +		return 1; +	} +}; + +CaseFolder *ScintillaCocoa::CaseFolderForEncoding() { +	if (pdoc->dbcsCodePage == SC_CP_UTF8) { +		return new CaseFolderUTF8(); +	} else { +        CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), +                                                             vs.styles[STYLE_DEFAULT].characterSet); +        if (pdoc->dbcsCodePage == 0) { +            CaseFolderTable *pcf = new CaseFolderTable(); +            pcf->StandardASCII(); +            // Only for single byte encodings +            for (int i=0x80; i<0x100; i++) { +                char sCharacter[2] = "A"; +                sCharacter[0] = i; +                CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, +                                                             reinterpret_cast<const UInt8 *>(sCharacter),  +                                                             1, encoding, false); +                 +                NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch +                                                                            locale:[NSLocale currentLocale]]; +                 +                char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); +                 +                if (strlen(encoded) == 1) { +                    pcf->SetTranslation(sCharacter[0], encoded[0]); +                } +                 +                delete []encoded; +                CFRelease(cfsVal); +            } +            return pcf; +        } else { +            return new CaseFolderDBCS(encoding); +        } +		return 0; +	} +} + + +//-------------------------------------------------------------------------------------------------- + +/**   * Case-fold the given string depending on the specified case mapping type. - * Note: ScintillaCocoa exclusively works with Unicode. We don't even think about adding support for - *       obsolete code page stuff.       */  std::string ScintillaCocoa::CaseMapString(const std::string &s, int caseMapping)  { -  NSString* textToConvert = [NSString stringWithUTF8String: s.c_str()]; -  std::string result; +  CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(), +                                                       vs.styles[STYLE_DEFAULT].characterSet); +  CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault, +                                               reinterpret_cast<const UInt8 *>(s.c_str()),  +                                               s.length(), encoding, false); + +  NSString *sMapped;    switch (caseMapping)    {      case cmUpper: -      result = [[textToConvert uppercaseString] UTF8String]; +      sMapped = [(NSString *)cfsVal uppercaseString];        break;      case cmLower: -      result = [[textToConvert lowercaseString] UTF8String]; +      sMapped = [(NSString *)cfsVal lowercaseString];        break;      default: -      result = s; +      sMapped = [(NSString *)cfsVal copy];    } + +  // Back to encoding +  char *encoded = EncodedBytes((CFStringRef)sMapped, encoding); +  std::string result(encoded); +  delete []encoded; +  CFRelease(cfsVal);    return result;  } | 
