NSFonts that have ASCII characters - objective-c

I'm making my own font dialogue, but it's embedded within WebKit. It's working pretty much how I want it to, except for one part. It's showing fonts that can not be written using standard ASCII characters. They appear in standard Latin characters, such as below. (note I'm setting the menu font using CSS)
This occurs with fonts such as Wingdings and fonts for languages such as Chinese. From what I've read, this is because there is no mapping between the ASCII characters to the font's characters.
I'd essentially like to filter out these fonts so only fonts that can actually be written with and are distinct appear. It should be possible, Pages manages to do it.
I've attempted to something like this, but it sometimes removes fonts that it shouldn't and leaves fonts that it should remove.
NSArray *availableFontFamilies = [[NSFontManager sharedFontManager] availableFontFamilies];
NSMutableArray *fontFamilies = [NSMutableArray array];
for (NSString *family in availableFontFamilies) {
NSFontDescriptor *fontDescriptor = [NSFontDescriptor fontDescriptorWithName: family size:16];
if ([fontDescriptor symbolicTraits] != 0 && ([fontDescriptor symbolicTraits] & NSFontSymbolicClass) == 0) {
[fontFamilies addObject: family];
}
}
NSLog(#"Families: %#", fontFamilies);

Related

Strange behavior in NSTextView when pressing tabs (Even when tabStops are set)

I'm observing a strange behavior in my NSTextView.
Assume there are multiple lines (separated by enter key presses) and when I keep pressing tabs, the whole paragraph turns into bulleted lines.
I did set the tabStops and enabled the Ruler to see the tabStops as mentioned in
Premature line wrapping in NSTextView when tabs are used
For an empty NSTextView it works fine, but when I apply it to an existing text, even though the tabStops are properly set, there is this strange behavior of turning into bulleted paragraph when pressing tabs.
Here is my code used to retrieve the existing string in the NSTextView and to set the tabStops
- (IBAction)formatTextView:(EditorTextView *)editorTextView tableWidth:(double) width
{
int cnt;
int numStops;
int tabInterval = 30;
NSTextTab *tabStop;
//attributes for attributed String of TextView
NSMutableDictionary* attrs = [[[editorTextView textStorage] attributesAtIndex:0 effectiveRange:NULL] mutableCopy];
NSParagraphStyle *paraStyle = [attrs objectForKey:NSParagraphStyleAttributeName];
NSMutableParagraphStyle *paraStyleM = [paraStyle mutableCopy];
// This first clears all tab stops, then adds tab stops, at desired intervals...
[paraStyle setTabStops:[NSArray array]];
for (cnt = 1; cnt <= numStops; cnt++) {
tabStop = [[NSTextTab alloc] initWithType:NSLeftTabStopType location: tabInterval * (cnt)];
[paraStyleM addTabStop:tabStop];
}
[attrs setObject:paraStyleM forKey:NSParagraphStyleAttributeName];
[[editorTextView textStorage] addAttributes:attrs range:NSMakeRange(0, [[[editorTextView textStorage] string] length])];
}
Is your existing text from HTML? I’m guessing it’s got some kind of <ul> thing going on in it.
They only recently (last six years?) hacked HTML ordered list and unordered list support into NSTextView to support richer messages in Mail, and it’s still pretty ugly.

How do I get a cubed symbol in a text box?

May seem like a silly question, but I simply want to have 'm'[cubed symbol] rather than 'cubic metres' in a text label in XCode.
How is this done?
If you only need ³, you can use the appropriate unicode character (Unicode: U+00B3, UTF-8: C2 B3). On the Mac you can use the "Character Viewer" (e.g. on "Edit" menu - "Special characters"), enter "3" in the search box, and then grab the appropriate "Related character". See the Apple help document entering unicode characters for more information.
If you need a more general use of subscripts (or you need more fine grained control over how the superscript is rendered), you can use attributed strings. Thus, the following will render something like "1,000 m3":
UIFont *font = [UIFont fontWithName:self.label.font.familyName size:self.label.font.pointSize * 0.75];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"1,000 m3"];
NSDictionary *attributes = #{(id)kCTSuperscriptAttributeName : #(1),
(id)NSFontAttributeName : font};
[string addAttributes:attributes range:NSMakeRange(7, 1)];
Simply insert the symbol in the string literal using Edit > Special Characters... (type "cubed" in the search box):
textField.text = [NSString stringWithFormat:#"Your table is %u㎤", tableVolume);
These are the unit-cubed symbols I found:
㎣ ㎤ ㎥ ㎦
If want a generic superscript '3' then that will be harder to arrange...

iOS: ZBar SDK unicode characters

When scanning QR codes with ZBar the string resulting from the process does not display unicode characters properly. The word Márti encoded as a QR code by any free to use QR code generator (like http://qrcode.kaywa.com) would result in Mテ。rti.
In other SO questions (1, 2) it was suggested to embed a BOM at the start of the resulting string, but doing this:
NSString *qrString = [NSString stringWithFormat:#"\xEF\xBB\xBF%#",symbol.data];
or this:
NSString *qrString = [[NSString alloc] initWithFormat:#"\357\273\277%#", symbol.data];
resulted in the same, flawed result with the Asian character. symbol.data is the resulting NSString provided by ZBar.
UPDATE: Based on dda's answer, the solution was the following:
NSString *qrString = symbol.data;
//look for misinterpreted acute characters and convert them to UTF-8
if ([qrString canBeConvertedToEncoding:NSShiftJISStringEncoding]) {
qrString = [NSString stringWithCString:[symbol.data cStringUsingEncoding: NSShiftJISStringEncoding] encoding:NSUTF8StringEncoding];
}
According to the Wikipedia page about QR, the encoding of binary data [for which Márti would apply] is ISO 8859-1. It could be an encoding-as-unicode-encoding problem. But seeing a kanji there, it could be that the problem is an encoding-as-QR-encoding issue: maybe the text, being not ASCII, is encoded by default as Shift JIS X 0208 (ie kanji/kana).
I could create QR codes of "日本語"(japanese) and "Márti" with following libraries:
iOS-QR-Code-Encoder
QR-Code-Encoder-for-Objective-C.
You can read those QR codes with ZBar.
iOS-QR-Code-Encoder:
NSString* orginalString = #"Márti"(or "日本語"(japanese));
NSString *data = [[NSString alloc] initWithFormat:#"\357\273\277%#", orginalString];
UIImage* qrcodeImage = [QRCodeGenerator qrImageForString:data imageSize:imageView.bounds.size.width];
QR-Code-Encoder-for-Objective-C:
NSString* orginalString = #"Márti"(or "日本語"(japanese));
NSString *data = [[NSString alloc] initWithFormat:#"\357\273\277%#", orginalString];
//first encode the string into a matrix of bools, TRUE for black dot and FALSE for white. Let the encoder decide the error correction level and version
DataMatrix* qrMatrix = [QREncoder encodeWithECLevel:QR_ECLEVEL_AUTO version:QR_VERSION_AUTO string:data];
//then render the matrix
UIImage* qrcodeImage = [QREncoder renderDataMatrix:qrMatrix imageDimension:qrcodeImageDimension];
Just a word of caution, the solution as is will exclude use in Japan and scanning of QR Codes with actual Kanji coding inside. In fact it will probably create problems for any QR Code with Unicode characters inside that canBeConvertedToEncoding:NSShiftJISStringEncoding.
A more universal solution is to insert the BOM characters prior to the QR Code encoding to force UTF-8 coding (before it is created). ZBar was never the problem here, it is rooted in the creation of the QR Code.

How to make a NSString always use fixed font width

I want to have an NSString in the format "hh:mm:ss" to use exactly the same amount of pixel space as the string "88:88:88". Is that possible?
Now I'm using:
// ...
NSMutableString * strS = [[NSMutableString alloc] initWithFormat:#"%d", Seconds];
if (Seconds<10){
[strS insertString:#"0" atIndex:0];
}
// Make the time to show
[ClocklLabel setText:[NSString stringWithFormat:#"%2#:%2#:%2#", strH,strM,strS]];
with no success!
I think you're looking for a monospaced font. Try using Courier for example:
UIFont *courier = [UIFont fontWithName:#"Courier" size:12.0f];
label.font = courier;
If you're trying to create a digital clock display, you could also simply use a separate label for each number and position the labels however you want.
You could use a monospace font. If you do not want this, use a UILabel and set adjustsFontSizeToFitWidth to YES. However, in this case the height will vary.
The title of your question hints to the fact that you are missing an important detail. NSString only contains the actual text.
It is not the NSString that dictates font, color or other attributes. As other answers have suggested you should set the font to the label/textfield/button or whatever visual gadget is supposed to display the string.
If you want to combine both text and text attributes, you may want to check NSAttributedString.

NSTextView syntax highlighting

I'm working on a Cocoa text editor which uses an NSTextView. Is it possible to change the color of certain portions of the text?
You should add your controller as the delegate of the NSTextStorage object of the NSTextView ([textView textStorage]) and then implement the delegate method ‑textStorageDidProcessEditing:. This is called whenever the text changes.
In the delegate method you need to get the current NSTextStorage object from the text view using the -textStorage method of NSTextView. NSTextStorage is a subclass of NSAttributedString and contains the attributed contents of the view.
Your code must then parse the string and apply coloring to whatever ranges of text are interesting to you. You apply color to a range using something like this, which will apply a yellow color to the whole string:
//get the range of the entire run of text
NSRange area = NSMakeRange(0, [textStorage length]);
//remove existing coloring
[textStorage removeAttribute:NSForegroundColorAttributeName range:area];
//add new coloring
[textStorage addAttribute:NSForegroundColorAttributeName
value:[NSColor yellowColor]
range:area];
How you parse the text is up to you. NSScanner is a useful class to use when parsing text.
Note that this method is by no means the most efficient way of handling syntax coloring. If the documents you are editing are very large you will most likely want to consider offloading the parsing to a separate thread and/or being clever about which sections of text are reparsed.
Rob Keniger's answer is good, but for someone looking for a more concrete example, here's a short syntax highlighter I wrote that should highlight RegEx template syntax. I want \ to be gray, with the character immediately following them to be black. I want $ to be red, with a digit character immediately following the $ to also be red. Everything else should be black. Here's my solution:
I made a template highlighter class, with a header that looks like this:
#interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate>
#end
I initialize it in the nib file as an object and hook it up to my view controller with an outlet. In awakeFromNib of the view controller, I have this (where replacer is my NSTextView outlet and templateHighlighter is the outlet for the class above):
self.replacer.textStorage.delegate = self.templateHighlighter;
And my implementation looks like this:
- (void)textStorageDidProcessEditing:(NSNotification *)notification {
NSTextStorage *textStorage = notification.object;
NSString *string = textStorage.string;
NSUInteger n = string.length;
[textStorage removeAttribute:NSForegroundColorAttributeName range:NSMakeRange(0, n)];
for (NSUInteger i = 0; i < n; i++) {
unichar c = [string characterAtIndex:i];
if (c == '\\') {
[textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor lightGrayColor] range:NSMakeRange(i, 1)];
i++;
} else if (c == '$') {
NSUInteger l = ((i < n - 1) && isdigit([string characterAtIndex:i+1])) ? 2 : 1;
[textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(i, l)];
i++;
}
}
}
So there you go, a fully working example. There were a few details that had me tripped up for ~10 minutes, like the fact that you have to take the string out of textStorage to access the individual characters... maybe this save other people a few minutes.
I recommend you to start by reading the CocoaDev page about Syntax Highlighing. A lot of people have come with solutions for various goals.
If you want to perform source code syntax highlighting, I suggest you to take a look at the UKSyntaxColoredTextDocument from Uli Kusterer.
Sure. You can give the NSTextView an NSAttributedString, and some of the stuff you can do with the attributed string is apply colors to certain subranges of the string.
Or you can search on Google and see that a lot of people have done stuff with this before.
I'd probably recommend using OkudaKit.
If you are ok with WebView you can use https://github.com/ACENative/ACEView
It loads ACE editor in WebView