Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* HebSupport - Hebrew support for iPhone
- * Copyright (C) 2009 Aviram Segal (planB) Liraz Elias (Liraz) and Omri Gilad (mmgm)
- */
- /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #import <Foundation/Foundation.h>
- #import "RegexKitLite.h"
- #include "substrate.h"
- #include "iVrit.h"
- #include <alloca.h>
- #include <unistd.h>
- #include "ABMemberCell.h"
- #include <execinfo.h>
- /* Declare ICU functions */
- extern "C" void* ubidi_open();
- extern "C" void ubidi_close(void*);
- extern "C" void ubidi_setPara( void*, UChar*, int, UBiDiLevel, void*, UErrorCode* );
- extern "C" int32_t ubidi_writeReordered( void*, UChar*, int, uint16_t, UErrorCode* );
- extern "C" void ubidi_setReorderingMode(void*, UBiDiReorderingMode);
- extern "C" UBiDiDirection ubidi_getDirection(void*);
- extern "C" UBiDiLevel ubidi_getLevelAt(void*, int32_t);
- extern "C" UBiDiLevel ubidi_getParaLevel(void*);
- extern "C" UBool u_isalpha (UChar);
- #define WEBCORE_FRAMEWORK "/System/Library/PrivateFrameworks/WebCore.framework/WebCore"
- #define LIBICUCORE "/usr/lib/libicucore.dylib"
- /* Bidi */
- FloatSize (*__orig__Font$drawText)(void* _this, void* context, TextRun& run, FloatPoint& point, int from, int to) = 0x0;
- FloatSize __Font$drawText(void* _this, void* context, TextRun& run, FloatPoint& point, int from, int to) {
- void *bidi;
- UErrorCode err = U_ZERO_ERROR;
- UBiDiLevel level = UBIDI_DEFAULT_LTR;
- bidi=ubidi_open();
- ubidi_setReorderingMode(bidi, UBIDI_REORDER_NUMBERS_SPECIAL);
- UChar* input = (UChar*)run.m_characters;
- int len = run.m_len;
- ubidi_setPara( bidi, input, len, level, NULL, &err );
- TextRun newRun = run;
- UChar* output = (UChar*)alloca(len * sizeof(UChar));
- UBiDiDirection dir;
- //NSLog(@"Inside hooked Font$drawText, len=%d", len);
- dir = ubidi_getDirection(bidi);
- if(dir == UBIDI_MIXED){
- level = ubidi_getParaLevel(bidi);
- if(level % 2 == 0){
- ubidi_writeReordered( bidi, output, len, UBIDI_DO_MIRRORING, &err );
- newRun.m_characters = output;
- } else {
- ubidi_writeReordered( bidi, output, len, UBIDI_OUTPUT_REVERSE, &err );
- newRun.m_characters = output;
- newRun.m_rtl = true;
- }
- } else if(!(run.m_rtl) && (dir == UBIDI_RTL)){
- ubidi_writeReordered( bidi, output, len, UBIDI_OUTPUT_REVERSE, &err );
- newRun.m_characters = output;
- newRun.m_rtl = true;
- }
- FloatSize ret = __orig__Font$drawText(_this, context, newRun, point, from, to);
- ubidi_close(bidi);
- return ret;
- }
- static id ABMembersController$sectionIndexTitlesForTableView(id self, SEL sel, id tableView) {
- NSInteger numOfSections = [self numberOfSectionsInTableView:tableView];
- NSMutableArray* mutableTitles = [NSMutableArray arrayWithCapacity:(numOfSections+1)];
- [mutableTitles insertObject:@"{search}" atIndex:0];
- NSUInteger i;
- for (i = 0; i < numOfSections; i++) {
- NSObject* obj = [self tableView:tableView titleForHeaderInSection:i];
- if(obj != nil) {
- [mutableTitles insertObject:obj atIndex:(i+1)];
- }
- }
- return mutableTitles;
- }
- static void ABMemberCell$drawContentInRectSelected(id self, SEL sel, CGRect rect, BOOL selected) {
- ABMemberCell* _self = (ABMemberCell*)self;
- NSArray* origNamePieces = _self->_namePieces;
- // If empty array we can stop
- if([origNamePieces count] == 0) {
- [self orig$drawContentInRect:rect selected:selected];
- return;
- }
- NSMutableArray* namePieces = [NSMutableArray arrayWithArray:origNamePieces];
- BOOL isHebrew = false;
- int origHighlightIndex = _self->_highlightIndex;
- NSString* firstName = [namePieces objectAtIndex:0];
- unichar firstNameFirstChar = [firstName characterAtIndex:0];
- if(0x0590 <= firstNameFirstChar && firstNameFirstChar <= 0x05FF) {
- isHebrew = true;
- }
- if(isHebrew) {
- int count = [namePieces count];
- if(count == 2) {
- [namePieces exchangeObjectAtIndex:0 withObjectAtIndex:1];
- _self->_highlightIndex = (origHighlightIndex+1)%2;
- } else if(count ==3) {
- // Person with prefix such as Doctor
- [namePieces exchangeObjectAtIndex:0 withObjectAtIndex:2];
- if(_self->_highlightIndex != 1) {
- _self->_highlightIndex = (origHighlightIndex+2)%4;
- }
- }
- _self->_namePieces = namePieces;
- }
- [self orig$drawContentInRect:rect selected:selected];
- _self->_highlightIndex = origHighlightIndex;
- _self->_namePieces = origNamePieces;
- }
- void dumpSubviews(UIView *view, int level){
- NSMutableString *padding = [[NSMutableString alloc] init];
- for(int i=0; i<level; i++){
- [padding appendString:@"\t"];
- }
- NSLog(@"%@%@", padding, [view class]);
- [padding dealloc];
- NSArray *subviews = [view subviews];
- NSInteger count;
- if((count = [subviews count]) == 0){
- return;
- } else {
- level++;
- for(int i=0; i<count; i++){
- dumpSubviews([subviews objectAtIndex:i], level);
- }
- return;
- }
- }
- void setText(id self, SEL sel, NSString *text){
- void *bidi;
- UErrorCode err = U_ZERO_ERROR;
- UBiDiLevel level = UBIDI_DEFAULT_LTR;
- UBiDiDirection dir;
- /*if([text compare:@"dumpit"] == 0){
- dumpSubviews([[UIApplication sharedApplication] keyWindow], 0);
- return;
- }*/
- int len = [text length];
- bidi=ubidi_open();
- UChar *input = (UChar *)calloc(len, sizeof(UChar));
- [text getCharacters:(unichar *)input];
- ubidi_setPara( bidi, (UChar*)input, len, level, NULL, &err );
- dir = ubidi_getDirection(bidi);
- Class cls = object_getClass(self);
- //NSLog(@"Inside hooked [%@ setText:], text=%@, dir=%s", cls, text, dir==UBIDI_LTR?"LTR":"RTL/Mixed");
- if(dir == UBIDI_RTL){
- [self setTextAlignment:UITextAlignmentRight];
- } else if (dir == UBIDI_MIXED) {
- level = ubidi_getParaLevel(bidi);
- if(level % 2 == 1) {
- [self setTextAlignment:UITextAlignmentRight];
- }
- else {
- [self setTextAlignment:UITextAlignmentLeft];
- }
- }
- else {
- [self setTextAlignment:UITextAlignmentLeft];
- }
- [self orig$setText:text];
- ubidi_close(bidi);
- free(input);
- }
- void setTextAlignment(id self, SEL selector, UITextAlignment align) {
- Class cls = [self class];
- //NSLog(@"Inside hooked [%@ setTextAlignment:]", cls);
- [self orig$setTextAlignment:align];
- Ivar var = class_getInstanceVariable(cls, "_style");
- NSString *string = [self _style];
- if(string == nil){
- //NSLog(@"Failed to load style, aborting direction mods");
- return;
- }
- NSMutableString *newStyle = [[NSMutableString alloc] initWithString:string];
- [string release];
- NSString *newDir = [[NSString alloc] initWithFormat:@"%s", align==UITextAlignmentLeft?"ltr":"rtl"];
- //TODO: Perform this without regex. I know its a waste of cycles on a device like the iPhone, but I <3 regex too much.
- if([newStyle replaceOccurrencesOfRegex:@"direction\: (.){3}" withString:[NSString stringWithFormat:@"direction: %@", newDir]] == 0){
- [newStyle appendFormat:@"direction: %@;", newDir];
- }
- [newDir dealloc];
- object_setIvar(self, var, newStyle);
- }
- NSString *styleString(id self, SEL selector){
- UITextAlignment align = [self textAlignment];
- NSString *newDir = [[NSString alloc] initWithFormat:@"%s", align==UITextAlignmentLeft?"ltr":"rtl"];
- NSString *newAlign = [[NSString alloc] initWithFormat:@"%s", align==UITextAlignmentLeft?"left":"right"];
- NSMutableString *newStyle = [NSMutableString stringWithString:[self orig$styleString]];
- NSLog(@"Original style: %@", newStyle);
- if([newStyle replaceOccurrencesOfRegex:@"text\-align\: (.){4,5};" withString:[NSString stringWithFormat:@"text-align: %@;", newAlign]] == 0){
- [newStyle appendFormat:@"text-align: %@;", newAlign];
- }
- if([newStyle replaceOccurrencesOfRegex:@"direction\: (.){3}" withString:[NSString stringWithFormat:@"direction: %@", newDir]] == 0){
- [newStyle appendFormat:@"direction: %@;", newDir];
- }
- [newDir dealloc];
- [newAlign dealloc];
- NSLog(@"Returning style: %@", newStyle);
- return newStyle;
- }
- void setContentToHTMLString(id self, SEL selector, NSString *html){
- NSMutableString *text = [[NSMutableString alloc] initWithString:html];
- [text replaceOccurrencesOfRegex:@"<(\/)?div>" withString:@""];
- void *bidi;
- UErrorCode err = U_ZERO_ERROR;
- UBiDiLevel level = UBIDI_DEFAULT_LTR;
- UBiDiDirection dir;
- int len = [text length];
- bidi=ubidi_open();
- UChar *input = (UChar *)calloc(len, sizeof(UChar));
- [text getCharacters:(unichar *)input];
- ubidi_setPara( bidi, (UChar*)input, len, level, NULL, &err );
- dir = ubidi_getDirection(bidi);
- static UITextAlignment align;
- if(dir == UBIDI_RTL){
- align = UITextAlignmentRight;
- } else if (dir == UBIDI_MIXED) {
- level = ubidi_getParaLevel(bidi);
- if(level % 2 == 1) {
- align = UITextAlignmentRight;
- }
- else {
- align = UITextAlignmentLeft;
- }
- }
- else {
- align = UITextAlignmentLeft;
- }
- [self setTextAlignment:align];
- ubidi_close(bidi);
- free(input);
- [text release];
- [self orig$setContentToHTMLString:html];
- }
- extern "C" void HSInitialize() {
- //freopen([@"/tmp/ivrit_log.txt" fileSystemRepresentation], "a", stderr);
- /* BiDi supprt */
- struct nlist nl[4];
- int res = 0;
- memset(nl, 0x0, sizeof(nl));
- /* Hooks to WebCore/platform/graphics/Font.h - Font::drawText(GraphicsContext*, TextRun&, FloatPoint&, int from, int to); */
- nl[0].n_un.n_name = (char *) "__ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii";
- if((res = nlist(WEBCORE_FRAMEWORK, nl)) != -1) {
- MSHookFunction((void *)nl[0].n_value, (void *)&__Font$drawText, (void **)&__orig__Font$drawText);
- NSLog(@"Finished hooking funcs, res=%d", res);
- } else {
- NSLog(@"Failed to hook drawText, res=%d", res);
- }
- // We need this lib for Bidi
- if (dlopen(LIBICUCORE, RTLD_LAZY) == NULL) {
- NSLog(@"Failed to load icu");
- }
- MSHookMessage(objc_getClass("ABMembersController"), @selector(sectionIndexTitlesForTableView:), &ABMembersController$sectionIndexTitlesForTableView, "orig$");
- MSHookMessage(objc_getClass("UITextField"), @selector(setText:), &setText, "orig$");
- MSHookMessage(objc_getClass("UITextViewLegacy"), @selector(setText:), &setText, "orig$");
- MSHookMessage(objc_getClass("UILabel"), @selector(setText:), &setText, "orig$");
- MSHookMessage(objc_getClass("UITableViewCell"), @selector(setText:), &setText, "orig$");
- MSHookMessage(objc_getClass("UITextField"), @selector(setTextAlignment:), &setTextAlignment, "orig$");
- MSHookMessage(objc_getClass("UITextViewLegacy"), @selector(setContentToHTMLString:), &setContentToHTMLString, "orig$");
- MSHookMessage(objc_getClass("UITextViewLegacy"), @selector(styleString), &styleString, "orig$");
- /*Class cls = objc_getClass("UITextViewLegacy");
- unsigned int methodCount, i;
- Method * methods = class_copyMethodList(cls, &methodCount);
- for(i=0;i<methodCount;i++){
- char *methodType = method_copyReturnType(methods[i]);
- const char *methodName = sel_getName(method_getName(methods[i]));
- NSLog(@"%s %s", methodType, methodName);
- free(methodType);
- }*/
- /*Class cls = objc_getClass("UITextViewLegacy");
- unsigned int ivarCount, i;
- Ivar * ivars = class_copyIvarList(cls, &ivarCount);
- for(i=0;i<ivarCount;i++){
- NSLog(@"%s %s", ivar_getTypeEncoding(ivars[i]), ivar_getName(ivars[i]));
- }*/
- //Instead of ABModelRecord to support Cyntact in search
- MSHookMessage(objc_getClass("ABMemberCell"), @selector(drawContentInRect:selected:), &ABMemberCell$drawContentInRectSelected, "orig$");
- // Wait for saurik
- //MSHookMessage(objc_getClass("ABMemberCell"), @selector(initWithSize:member:), &ABMemberCell$initWithSizeMember, "orig$");
- /***************************************************************************************************************************/
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement