utf8 special online code checker characters cocoa special-characters hidden-characters

cocoa - special - á utf 8 code



Mostrar caracteres ocultos en NSTextView (7)

Eche un vistazo a la clase NSLayoutManager. Su NSTextView tendrá un administrador de diseño asociado, y el administrador de diseño es responsable de asociar un carácter (espacio, pestaña, etc.) con un glifo (la imagen de ese personaje dibujada en la pantalla).

En su caso, probablemente le interese más el replaceGlyphAtIndex:withGlyph: que le permitirá reemplazar glifos individuales.

Estoy escribiendo un editor de texto para Mac OS X. Necesito mostrar caracteres ocultos en un NSTextView (como espacios, pestañas y caracteres especiales). He pasado mucho tiempo buscando cómo hacer esto, pero hasta ahora no he encontrado una respuesta. Si alguien pudiera señalarme en la dirección correcta, estaría agradecido.


Lo que he hecho es anular el método a continuación en una subclase de NSLayoutManager.

- (void)drawGlyphsForGlyphRange:(NSRange)range atPoint:(NSPoint)origin { [super drawGlyphsForGlyphRange:range atPoint:origin]; for (int i = range.location; i != range.location + range.length; i++) { // test each character in this range // if appropriate replace it with -replaceGlyphAtIndex:withGlyph: } }

Recorro el índice de cada personaje. El problema que ahora tengo es cómo determinar qué personaje se encuentra en cada ubicación. ¿Debo usar un método NSLayoutManager o preguntar a NSTextView? ¿Los índices en el primero son los mismos que en el segundo?

Puedo obtener un glifo individual con -glyphAtIndex: pero no puedo averiguar cómo determinar a qué personaje corresponde.


Resolví el problema de convertir entre NSGlyphs y el unichar correspondiente en NSTextView. El siguiente código funciona maravillosamente y reemplaza espacios con viñetas para texto visible:

- (void)drawGlyphsForGlyphRange:(NSRange)range atPoint:(NSPoint)origin { NSFont *font = [[CURRENT_TEXT_VIEW typingAttributes] objectForKey:NSFontAttributeName]; NSGlyph bullet = [font glyphWithName:@"bullet"]; for (int i = range.location; i != range.location + range.length; i++) { unsigned charIndex = [self characterIndexForGlyphAtIndex:i]; unichar c =[[[self textStorage] string] characterAtIndex:charIndex]; if (c == '' '') [self replaceGlyphAtIndex:charIndex withGlyph:bullet]; } [super drawGlyphsForGlyphRange:range atPoint:origin]; }


Hace algunos años escribí un editor de texto: aquí hay un código sin sentido que debería hacer que mires (con suerte) la dirección correcta (esta es una subclase de NSLayoutManager, por cierto, y sí, sé que está goteando como el proverbial fregadero de la cocina):

- (void)drawGlyphsForGlyphRange:(NSRange)glyphRange atPoint:(NSPoint)containerOrigin { if ([[[[MJDocumentController sharedDocumentController] currentDocument] editor] showInvisibles]) { //init glyphs unichar crlf = 0x00B6; NSString *CRLF = [[NSString alloc] initWithCharacters:&crlf length:1]; unichar space = 0x00B7; NSString *SPACE = [[NSString alloc] initWithCharacters:&space length:1]; unichar tab = 0x2192; NSString *TAB = [[NSString alloc] initWithCharacters:&tab length:1]; NSString *docContents = [[self textStorage] string]; NSString *glyph; NSPoint glyphPoint; NSRect glyphRect; NSDictionary *attr = [[NSDictionary alloc] initWithObjectsAndKeys:[NSUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"invisiblesColor"]], NSForegroundColorAttributeName, nil]; //loop thru current range, drawing glyphs int i; for (i = glyphRange.location; i < NSMaxRange(glyphRange); i++) { glyph = @""; //look for special chars switch ([docContents characterAtIndex:i]) { //space case '' '': glyph = SPACE; break; //tab case ''/t'': glyph = TAB; break; //eol case 0x2028: case 0x2029: case ''/n'': case ''/r'': glyph = CRLF; break; //do nothing default: glyph = @""; break; } //should we draw? if ([glyph length]) { glyphPoint = [self locationForGlyphAtIndex:i]; glyphRect = [self lineFragmentRectForGlyphAtIndex:i effectiveRange:NULL]; glyphPoint.x += glyphRect.origin.x; glyphPoint.y = glyphRect.origin.y; [glyph drawAtPoint:glyphPoint withAttributes:attr]; } } } [super drawGlyphsForGlyphRange:glyphRange atPoint:containerOrigin]; }


Quizás - [NSLayoutManager setShowsControlCharacters:] y / o - [NSLayoutManager setShowsInvisibleCharacters:] hará lo que usted desee.


Aquí hay una implementación completamente funcional y limpia

@interface GILayoutManager : NSLayoutManager @end @implementation GILayoutManager - (void)drawGlyphsForGlyphRange:(NSRange)range atPoint:(NSPoint)point { NSTextStorage* storage = self.textStorage; NSString* string = storage.string; for (NSUInteger glyphIndex = range.location; glyphIndex < range.location + range.length; glyphIndex++) { NSUInteger characterIndex = [self characterIndexForGlyphAtIndex: glyphIndex]; switch ([string characterAtIndex:characterIndex]) { case '' '': { NSFont* font = [storage attribute:NSFontAttributeName atIndex:characterIndex effectiveRange:NULL]; [self replaceGlyphAtIndex:glyphIndex withGlyph:[font glyphWithName:@"periodcentered"]]; break; } case ''/n'': { NSFont* font = [storage attribute:NSFontAttributeName atIndex:characterIndex effectiveRange:NULL]; [self replaceGlyphAtIndex:glyphIndex withGlyph:[font glyphWithName:@"carriagereturn"]]; break; } } } [super drawGlyphsForGlyphRange:range atPoint:point]; } @end

Para instalar, use:

[myTextView.textContainer replaceLayoutManager:[[GILayoutManager alloc] init]];

Para encontrar nombres de glifos de fuente, debe ir a CoreGraphics:

CGFontRef font = CGFontCreateWithFontName(CFSTR("Menlo-Regular")); for (size_t i = 0; i < CGFontGetNumberOfGlyphs(font); ++i) { printf("%s/n", [CFBridgingRelease(CGFontCopyGlyphNameForGlyph(font, i)) UTF8String]); }


Aquí está la solución de Pol en Swift:

class MyLayoutManager: NSLayoutManager { override func drawGlyphsForGlyphRange(glyphsToShow: NSRange, atPoint origin: NSPoint) { if let storage = self.textStorage { let s = storage.string let startIndex = s.startIndex for var glyphIndex = glyphsToShow.location; glyphIndex < glyphsToShow.location + glyphsToShow.length; glyphIndex++ { let characterIndex = self.characterIndexForGlyphAtIndex(glyphIndex) let ch = s[startIndex.advancedBy(characterIndex)] switch ch { case " ": let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil) if let font = attrs[NSFontAttributeName] { let g = font.glyphWithName("periodcentered") self.replaceGlyphAtIndex(glyphIndex, withGlyph: g) } case "/n": let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil) if let font = attrs[NSFontAttributeName] { // let g = font.glyphWithName("carriagereturn") let g = font.glyphWithName("paragraph") self.replaceGlyphAtIndex(glyphIndex, withGlyph: g) } case "/t": let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil) if let font = attrs[NSFontAttributeName] { let g = font.glyphWithName("arrowdblright") self.replaceGlyphAtIndex(glyphIndex, withGlyph: g) } default: break } } } super.drawGlyphsForGlyphRange(glyphsToShow, atPoint: origin) } }

Y para enumerar los nombres de los glifos:

func listFonts() { let font = CGFontCreateWithFontName("Menlo-Regular") for var i:UInt16 = 0; i < UInt16(CGFontGetNumberOfGlyphs(font)); i++ { if let name = CGFontCopyGlyphNameForGlyph(font, i) { print("name: /(name) at index /(i)") } } }