1*cdf0e10cSrcweir/************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir// MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir#include "precompiled_vcl.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir#include "aqua/salinst.h" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir#include "aqua11ytextattributeswrapper.h" 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir#include <com/sun/star/accessibility/AccessibleTextType.hpp> 36*cdf0e10cSrcweir#include <com/sun/star/awt/FontUnderline.hpp> 37*cdf0e10cSrcweir#include <com/sun/star/awt/FontWeight.hpp> 38*cdf0e10cSrcweir#include <com/sun/star/awt/FontStrikeout.hpp> 39*cdf0e10cSrcweir 40*cdf0e10cSrcweirusing namespace ::com::sun::star::accessibility; 41*cdf0e10cSrcweirusing namespace ::com::sun::star::awt; 42*cdf0e10cSrcweirusing namespace ::com::sun::star::beans; 43*cdf0e10cSrcweirusing namespace ::com::sun::star::lang; 44*cdf0e10cSrcweirusing namespace ::com::sun::star::uno; 45*cdf0e10cSrcweirusing namespace ::rtl; 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir@implementation AquaA11yTextAttributesWrapper : NSObject 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir+(int)convertUnderlineStyle:(PropertyValue)property { 50*cdf0e10cSrcweir int underlineStyle = NSNoUnderlineStyle; 51*cdf0e10cSrcweir sal_Int16 value = 0; 52*cdf0e10cSrcweir property.Value >>= value; 53*cdf0e10cSrcweir if ( value != FontUnderline::NONE 54*cdf0e10cSrcweir && value != FontUnderline::DONTKNOW) { 55*cdf0e10cSrcweir underlineStyle = NSSingleUnderlineStyle; 56*cdf0e10cSrcweir } 57*cdf0e10cSrcweir return underlineStyle; 58*cdf0e10cSrcweir} 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir+(int)convertBoldStyle:(PropertyValue)property { 61*cdf0e10cSrcweir int boldStyle = 0; 62*cdf0e10cSrcweir float value = 0; 63*cdf0e10cSrcweir property.Value >>= value; 64*cdf0e10cSrcweir if ( value == FontWeight::SEMIBOLD 65*cdf0e10cSrcweir || value == FontWeight::BOLD 66*cdf0e10cSrcweir || value == FontWeight::ULTRABOLD 67*cdf0e10cSrcweir || value == FontWeight::BLACK ) { 68*cdf0e10cSrcweir boldStyle = NSBoldFontMask; 69*cdf0e10cSrcweir } 70*cdf0e10cSrcweir return boldStyle; 71*cdf0e10cSrcweir} 72*cdf0e10cSrcweir 73*cdf0e10cSrcweir+(int)convertItalicStyle:(PropertyValue)property { 74*cdf0e10cSrcweir int italicStyle = 0; 75*cdf0e10cSrcweir sal_Int16 value = property.Value.get<FontSlant>(); 76*cdf0e10cSrcweir if ( value == FontSlant_ITALIC ) { 77*cdf0e10cSrcweir italicStyle = NSItalicFontMask; 78*cdf0e10cSrcweir } 79*cdf0e10cSrcweir return italicStyle; 80*cdf0e10cSrcweir} 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir+(BOOL)isStrikethrough:(PropertyValue)property { 83*cdf0e10cSrcweir BOOL strikethrough = NO; 84*cdf0e10cSrcweir sal_Int16 value = 0; 85*cdf0e10cSrcweir property.Value >>= value; 86*cdf0e10cSrcweir if ( value != FontStrikeout::NONE 87*cdf0e10cSrcweir && value != FontStrikeout::DONTKNOW ) { 88*cdf0e10cSrcweir strikethrough = YES; 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir return strikethrough; 91*cdf0e10cSrcweir} 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir+(BOOL)convertBoolean:(PropertyValue)property { 94*cdf0e10cSrcweir BOOL myBoolean = NO; 95*cdf0e10cSrcweir bool value = sal_False; 96*cdf0e10cSrcweir property.Value >>= value; 97*cdf0e10cSrcweir if ( value ) { 98*cdf0e10cSrcweir myBoolean = YES; 99*cdf0e10cSrcweir } 100*cdf0e10cSrcweir return myBoolean; 101*cdf0e10cSrcweir} 102*cdf0e10cSrcweir 103*cdf0e10cSrcweir+(NSNumber *)convertShort:(PropertyValue)property { 104*cdf0e10cSrcweir sal_Int16 value = 0; 105*cdf0e10cSrcweir property.Value >>= value; 106*cdf0e10cSrcweir return [ NSNumber numberWithShort: value ]; 107*cdf0e10cSrcweir} 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir+(void)addColor:(sal_Int32)salColor forAttribute:(NSString *)attribute andRange:(NSRange)range toString:(NSMutableAttributedString *)string { 110*cdf0e10cSrcweir if ( salColor != -1 ) { 111*cdf0e10cSrcweir float elements[] = { salColor & 0x00ff0000, salColor & 0x0000ff00, salColor & 0x000000ff }; 112*cdf0e10cSrcweir CGColorRef color = CGColorCreate ( CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ), elements ); 113*cdf0e10cSrcweir [ string addAttribute: attribute value: (id) color range: range ]; 114*cdf0e10cSrcweir CGColorRelease ( color ); 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir} 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir+(void)addFont:(NSFont *)font toString:(NSMutableAttributedString *)string forRange:(NSRange)range { 119*cdf0e10cSrcweir if ( font != nil ) { 120*cdf0e10cSrcweir NSDictionary * fontDictionary = [ NSDictionary dictionaryWithObjectsAndKeys: 121*cdf0e10cSrcweir [ font fontName ], NSAccessibilityFontNameKey, 122*cdf0e10cSrcweir [ font familyName ], NSAccessibilityFontFamilyKey, 123*cdf0e10cSrcweir [ font displayName ], NSAccessibilityVisibleNameKey, 124*cdf0e10cSrcweir [ NSNumber numberWithFloat: [ font pointSize ] ], NSAccessibilityFontSizeKey, 125*cdf0e10cSrcweir nil 126*cdf0e10cSrcweir ]; 127*cdf0e10cSrcweir [ string addAttribute: NSAccessibilityFontTextAttribute 128*cdf0e10cSrcweir value: fontDictionary 129*cdf0e10cSrcweir range: range 130*cdf0e10cSrcweir ]; 131*cdf0e10cSrcweir } 132*cdf0e10cSrcweir} 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir+(void)applyAttributesFrom:(Sequence < PropertyValue >)attributes toString:(NSMutableAttributedString *)string forRange:(NSRange)range storeDefaultsTo:(AquaA11yWrapper *)wrapperStore getDefaultsFrom:(AquaA11yWrapper *)wrapper { 135*cdf0e10cSrcweir NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; 136*cdf0e10cSrcweir // constants 137*cdf0e10cSrcweir static const OUString attrUnderline = OUString::createFromAscii("CharUnderline"); 138*cdf0e10cSrcweir static const OUString attrBold = OUString::createFromAscii("CharWeight"); 139*cdf0e10cSrcweir static const OUString attrFontname = OUString::createFromAscii("CharFontName"); 140*cdf0e10cSrcweir static const OUString attrItalic = OUString::createFromAscii("CharPosture"); 141*cdf0e10cSrcweir static const OUString attrHeight = OUString::createFromAscii("CharHeight"); 142*cdf0e10cSrcweir static const OUString attrStrikethrough = OUString::createFromAscii("CharStrikeout"); 143*cdf0e10cSrcweir static const OUString attrShadow = OUString::createFromAscii("CharShadowed"); 144*cdf0e10cSrcweir static const OUString attrUnderlineColor = OUString::createFromAscii("CharUnderlineColor"); 145*cdf0e10cSrcweir static const OUString attrUnderlineHasColor = OUString::createFromAscii("CharUnderlineHasColor"); 146*cdf0e10cSrcweir static const OUString attrForegroundColor = OUString::createFromAscii("CharColor"); 147*cdf0e10cSrcweir static const OUString attrBackgroundColor = OUString::createFromAscii("CharBackColor"); 148*cdf0e10cSrcweir static const OUString attrSuperscript = OUString::createFromAscii("CharEscapement"); 149*cdf0e10cSrcweir // vars 150*cdf0e10cSrcweir OUString fontname; 151*cdf0e10cSrcweir int fonttraits = 0; 152*cdf0e10cSrcweir float fontsize = 0.0; 153*cdf0e10cSrcweir sal_Int32 underlineColor = 0; 154*cdf0e10cSrcweir BOOL underlineHasColor = NO; 155*cdf0e10cSrcweir // add attributes to string 156*cdf0e10cSrcweir for ( int attrIndex = 0; attrIndex < attributes.getLength(); attrIndex++ ) { 157*cdf0e10cSrcweir PropertyValue property = attributes [ attrIndex ]; 158*cdf0e10cSrcweir // TODO: NSAccessibilityMisspelledTextAttribute, NSAccessibilityAttachmentTextAttribute, NSAccessibilityLinkTextAttribute 159*cdf0e10cSrcweir // NSAccessibilityStrikethroughColorTextAttribute is unsupported by UNP-API 160*cdf0e10cSrcweir if ( property.Value.hasValue() ) { 161*cdf0e10cSrcweir if ( property.Name.equals ( attrUnderline ) ) { 162*cdf0e10cSrcweir int style = [ AquaA11yTextAttributesWrapper convertUnderlineStyle: property ]; 163*cdf0e10cSrcweir if ( style != NSNoUnderlineStyle ) { 164*cdf0e10cSrcweir [ string addAttribute: NSAccessibilityUnderlineTextAttribute value: [ NSNumber numberWithInt: style ] range: range ]; 165*cdf0e10cSrcweir } 166*cdf0e10cSrcweir } else if ( property.Name.equals ( attrFontname ) ) { 167*cdf0e10cSrcweir property.Value >>= fontname; 168*cdf0e10cSrcweir } else if ( property.Name.equals ( attrBold ) ) { 169*cdf0e10cSrcweir fonttraits |= [ AquaA11yTextAttributesWrapper convertBoldStyle: property ]; 170*cdf0e10cSrcweir } else if ( property.Name.equals ( attrItalic ) ) { 171*cdf0e10cSrcweir fonttraits |= [ AquaA11yTextAttributesWrapper convertItalicStyle: property ]; 172*cdf0e10cSrcweir } else if ( property.Name.equals ( attrHeight ) ) { 173*cdf0e10cSrcweir property.Value >>= fontsize; 174*cdf0e10cSrcweir } else if ( property.Name.equals ( attrStrikethrough ) ) { 175*cdf0e10cSrcweir if ( [ AquaA11yTextAttributesWrapper isStrikethrough: property ] ) { 176*cdf0e10cSrcweir [ string addAttribute: NSAccessibilityStrikethroughTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ]; 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir } else if ( property.Name.equals ( attrShadow ) ) { 179*cdf0e10cSrcweir if ( [ AquaA11yTextAttributesWrapper convertBoolean: property ] ) { 180*cdf0e10cSrcweir [ string addAttribute: NSAccessibilityShadowTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ]; 181*cdf0e10cSrcweir } 182*cdf0e10cSrcweir } else if ( property.Name.equals ( attrUnderlineColor ) ) { 183*cdf0e10cSrcweir property.Value >>= underlineColor; 184*cdf0e10cSrcweir } else if ( property.Name.equals ( attrUnderlineHasColor ) ) { 185*cdf0e10cSrcweir underlineHasColor = [ AquaA11yTextAttributesWrapper convertBoolean: property ]; 186*cdf0e10cSrcweir } else if ( property.Name.equals ( attrForegroundColor ) ) { 187*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper addColor: property.Value.get<sal_Int32>() forAttribute: NSAccessibilityForegroundColorTextAttribute andRange: range toString: string ]; 188*cdf0e10cSrcweir } else if ( property.Name.equals ( attrBackgroundColor ) ) { 189*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper addColor: property.Value.get<sal_Int32>() forAttribute: NSAccessibilityBackgroundColorTextAttribute andRange: range toString: string ]; 190*cdf0e10cSrcweir } else if ( property.Name.equals ( attrSuperscript ) ) { 191*cdf0e10cSrcweir // values < zero mean subscript 192*cdf0e10cSrcweir // values > zero mean superscript 193*cdf0e10cSrcweir // this is true for both NSAccessibility-API and UNO-API 194*cdf0e10cSrcweir NSNumber * number = [ AquaA11yTextAttributesWrapper convertShort: property ]; 195*cdf0e10cSrcweir if ( [ number shortValue ] != 0 ) { 196*cdf0e10cSrcweir [ string addAttribute: NSAccessibilitySuperscriptTextAttribute value: number range: range ]; 197*cdf0e10cSrcweir } 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir // add underline information 202*cdf0e10cSrcweir if ( underlineHasColor ) { 203*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper addColor: underlineColor forAttribute: NSAccessibilityUnderlineColorTextAttribute andRange: range toString: string ]; 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir // add font information 206*cdf0e10cSrcweir if ( wrapperStore != nil ) { // default 207*cdf0e10cSrcweir [ wrapperStore setDefaultFontname: CreateNSString ( fontname ) ]; 208*cdf0e10cSrcweir [ wrapperStore setDefaultFontsize: fontsize ]; 209*cdf0e10cSrcweir NSFont * font = [ [ NSFontManager sharedFontManager ] fontWithFamily: CreateNSString ( fontname ) traits: fonttraits weight: 0 size: fontsize ]; 210*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper addFont: font toString: string forRange: range ]; 211*cdf0e10cSrcweir } else if ( wrapper != nil && fonttraits != 0 ) { // attribute run and bold and/or italic was found 212*cdf0e10cSrcweir NSFont * font = [ [ NSFontManager sharedFontManager ] fontWithFamily: [ wrapper defaultFontname ] traits: fonttraits weight: 0 size: [ wrapper defaultFontsize ] ]; 213*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper addFont: font toString: string forRange: range ]; 214*cdf0e10cSrcweir } 215*cdf0e10cSrcweir [ pool release ]; 216*cdf0e10cSrcweir} 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir+(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange { 219*cdf0e10cSrcweir static const Sequence < OUString > emptySequence; 220*cdf0e10cSrcweir // vars 221*cdf0e10cSrcweir NSMutableAttributedString * string = nil; 222*cdf0e10cSrcweir int loc = [ origRange rangeValue ].location; 223*cdf0e10cSrcweir int len = [ origRange rangeValue ].length; 224*cdf0e10cSrcweir int endIndex = loc + len; 225*cdf0e10cSrcweir int currentIndex = loc; 226*cdf0e10cSrcweir try { 227*cdf0e10cSrcweir NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817 228*cdf0e10cSrcweir string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; 229*cdf0e10cSrcweir if ( [ wrapper accessibleTextAttributes ] != nil && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817 230*cdf0e10cSrcweir [ string beginEditing ]; 231*cdf0e10cSrcweir // add default attributes for whole string 232*cdf0e10cSrcweir Sequence < PropertyValue > defaultAttributes = [ wrapper accessibleTextAttributes ] -> getDefaultAttributes ( emptySequence ); 233*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper applyAttributesFrom: defaultAttributes toString: string forRange: [ origRange rangeValue ] storeDefaultsTo: wrapper getDefaultsFrom: nil ]; 234*cdf0e10cSrcweir // add attributes for attribute run(s) 235*cdf0e10cSrcweir while ( currentIndex < endIndex ) { 236*cdf0e10cSrcweir TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( currentIndex, AccessibleTextType::ATTRIBUTE_RUN ); 237*cdf0e10cSrcweir int endOfRange = endIndex > textSegment.SegmentEnd ? textSegment.SegmentEnd : endIndex; 238*cdf0e10cSrcweir NSRange rangeForAttributeRun = NSMakeRange ( currentIndex, endOfRange - currentIndex ); 239*cdf0e10cSrcweir // add run attributes 240*cdf0e10cSrcweir Sequence < PropertyValue > attributes = [ wrapper accessibleTextAttributes ] -> getRunAttributes ( currentIndex, emptySequence ); 241*cdf0e10cSrcweir [ AquaA11yTextAttributesWrapper applyAttributesFrom: attributes toString: string forRange: rangeForAttributeRun storeDefaultsTo: nil getDefaultsFrom: wrapper ]; 242*cdf0e10cSrcweir currentIndex = textSegment.SegmentEnd; 243*cdf0e10cSrcweir } 244*cdf0e10cSrcweir [ string endEditing ]; 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir } catch ( IllegalArgumentException & e ) { 247*cdf0e10cSrcweir // empty 248*cdf0e10cSrcweir } catch ( IndexOutOfBoundsException & e ) { 249*cdf0e10cSrcweir // empty 250*cdf0e10cSrcweir } catch ( RuntimeException& ) { 251*cdf0e10cSrcweir // at least don't crash 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir return string; 254*cdf0e10cSrcweir} 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir@end 257