]> git.sesse.net Git - vlc/blob - modules/gui/macosx/StringUtility.m
macosx: adapt module_list_get calls for latest changes in core
[vlc] / modules / gui / macosx / StringUtility.m
1 /*****************************************************************************
2  * StringUtility.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2002-2012 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Derk-Jan Hartman <hartman at videolan dot org>
10  *          Felix Paul Kühne <fkuehne at videolan dot org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 #import <vlc_input.h>
28 #import <vlc_keys.h>
29 #import "StringUtility.h"
30 #import "intf.h"
31
32 @implementation VLCStringUtility
33
34 static VLCStringUtility *_o_sharedInstance = nil;
35
36 + (VLCStringUtility *)sharedInstance
37 {
38     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
39 }
40
41 - (id)init
42 {
43     if (_o_sharedInstance)
44         [self dealloc];
45     else
46         _o_sharedInstance = [super init];
47
48     return _o_sharedInstance;
49 }
50
51 #pragma mark -
52 #pragma mark String utility
53
54 - (NSString *)localizedString:(const char *)psz
55 {
56     NSString * o_str = nil;
57
58     if (psz != NULL) {
59         o_str = [NSString stringWithCString: _(psz) encoding:NSUTF8StringEncoding];
60
61         if (o_str == NULL) {
62             msg_Err(VLCIntf, "could not translate: %s", psz);
63             return(@"");
64         }
65     } else {
66         msg_Warn(VLCIntf, "can't translate empty strings");
67         return(@"");
68     }
69
70     return(o_str);
71 }
72
73
74
75 - (char *)delocalizeString:(NSString *)id
76 {
77     NSData * o_data = [id dataUsingEncoding: NSUTF8StringEncoding
78                        allowLossyConversion: NO];
79     char * psz_string;
80
81     if (o_data == nil) {
82         o_data = [id dataUsingEncoding: NSUTF8StringEncoding
83                   allowLossyConversion: YES];
84         psz_string = malloc([o_data length] + 1);
85         [o_data getBytes: psz_string];
86         psz_string[ [o_data length] ] = '\0';
87         msg_Err(VLCIntf, "cannot convert to the requested encoding: %s",
88                 psz_string);
89     } else {
90         psz_string = malloc([o_data length] + 1);
91         [o_data getBytes: psz_string];
92         psz_string[ [o_data length] ] = '\0';
93     }
94
95     return psz_string;
96 }
97
98 /* i_width is in pixels */
99 - (NSString *)wrapString: (NSString *)o_in_string toWidth: (int) i_width
100 {
101     NSMutableString *o_wrapped;
102     NSString *o_out_string;
103     NSRange glyphRange, effectiveRange, charRange;
104     NSRect lineFragmentRect;
105     unsigned glyphIndex, breaksInserted = 0;
106
107     NSTextStorage *o_storage = [[NSTextStorage alloc] initWithString: o_in_string
108                                                           attributes: [NSDictionary dictionaryWithObjectsAndKeys:
109                                                                        [NSFont labelFontOfSize: 0.0], NSFontAttributeName, nil]];
110     NSLayoutManager *o_layout_manager = [[NSLayoutManager alloc] init];
111     NSTextContainer *o_container = [[NSTextContainer alloc]
112                                     initWithContainerSize: NSMakeSize(i_width, 2000)];
113
114     [o_layout_manager addTextContainer: o_container];
115     [o_container release];
116     [o_storage addLayoutManager: o_layout_manager];
117     [o_layout_manager release];
118
119     o_wrapped = [o_in_string mutableCopy];
120     glyphRange = [o_layout_manager glyphRangeForTextContainer: o_container];
121
122     for (glyphIndex = glyphRange.location ; glyphIndex < NSMaxRange(glyphRange) ;
123         glyphIndex += effectiveRange.length) {
124         lineFragmentRect = [o_layout_manager lineFragmentRectForGlyphAtIndex: glyphIndex
125                                                               effectiveRange: &effectiveRange];
126         charRange = [o_layout_manager characterRangeForGlyphRange: effectiveRange
127                                                  actualGlyphRange: &effectiveRange];
128         if ([o_wrapped lineRangeForRange:
129             NSMakeRange(charRange.location + breaksInserted, charRange.length)].length > charRange.length) {
130             [o_wrapped insertString: @"\n" atIndex: NSMaxRange(charRange) + breaksInserted];
131             breaksInserted++;
132         }
133     }
134     o_out_string = [NSString stringWithString: o_wrapped];
135     [o_wrapped release];
136     [o_storage release];
137
138     return o_out_string;
139 }
140
141 - (NSString *)OSXStringKeyToString:(NSString *)theString
142 {
143     if (![theString isEqualToString:@""]) {
144         /* remove cruft */
145         if ([theString characterAtIndex:([theString length] - 1)] != 0x2b)
146             theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""];
147         else {
148             theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""];
149             theString = [NSString stringWithFormat:@"%@+", theString];
150         }
151         if ([theString characterAtIndex:([theString length] - 1)] != 0x2d)
152             theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""];
153         else {
154             theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""];
155             theString = [NSString stringWithFormat:@"%@-", theString];
156         }
157         /* modifiers */
158         theString = [theString stringByReplacingOccurrencesOfString:@"Command" withString: [NSString stringWithUTF8String: "\xE2\x8C\x98"]];
159         theString = [theString stringByReplacingOccurrencesOfString:@"Alt" withString: [NSString stringWithUTF8String: "\xE2\x8C\xA5"]];
160         theString = [theString stringByReplacingOccurrencesOfString:@"Shift" withString: [NSString stringWithUTF8String: "\xE2\x87\xA7"]];
161         theString = [theString stringByReplacingOccurrencesOfString:@"Ctrl" withString: [NSString stringWithUTF8String: "\xE2\x8C\x83"]];
162         /* show non-character keys correctly */
163         theString = [theString stringByReplacingOccurrencesOfString:@"Right" withString:[NSString stringWithUTF8String:"\xE2\x86\x92"]];
164         theString = [theString stringByReplacingOccurrencesOfString:@"Left" withString:[NSString stringWithUTF8String:"\xE2\x86\x90"]];
165         theString = [theString stringByReplacingOccurrencesOfString:@"Up" withString:[NSString stringWithUTF8String:"\xE2\x86\x91"]];
166         theString = [theString stringByReplacingOccurrencesOfString:@"Down" withString:[NSString stringWithUTF8String:"\xE2\x86\x93"]];
167         theString = [theString stringByReplacingOccurrencesOfString:@"Enter" withString:[NSString stringWithUTF8String:"\xe2\x86\xb5"]];
168         theString = [theString stringByReplacingOccurrencesOfString:@"Tab" withString:[NSString stringWithUTF8String:"\xe2\x87\xa5"]];
169         theString = [theString stringByReplacingOccurrencesOfString:@"Delete" withString:[NSString stringWithUTF8String:"\xe2\x8c\xab"]];        /* capitalize plain characters to suit the menubar's look */
170         theString = [theString capitalizedString];
171     }
172     else
173         theString = [NSString stringWithString:_NS("Not Set")];
174     return theString;
175 }
176
177 - (NSString *)getCurrentTimeAsString:(input_thread_t *)p_input negative:(BOOL)b_negative
178 {
179     assert(p_input != nil);
180     
181     vlc_value_t time;
182     char psz_time[MSTRTIME_MAX_SIZE];
183     
184     var_Get(p_input, "time", &time);
185     
186     mtime_t dur = input_item_GetDuration(input_GetItem(p_input));
187     if (b_negative && dur > 0) {
188         mtime_t remaining = 0;
189         if (dur > time.i_time)
190             remaining = dur - time.i_time;
191         return [NSString stringWithFormat: @"-%s", secstotimestr(psz_time, (remaining / 1000000))];
192     } else
193         return [NSString stringWithUTF8String: secstotimestr(psz_time, (time.i_time / 1000000))];
194 }
195
196 #pragma mark -
197 #pragma mark Key Shortcuts
198
199 static struct
200 {
201     unichar i_nskey;
202     unsigned int i_vlckey;
203 } nskeys_to_vlckeys[] =
204 {
205     { NSUpArrowFunctionKey, KEY_UP },
206     { NSDownArrowFunctionKey, KEY_DOWN },
207     { NSLeftArrowFunctionKey, KEY_LEFT },
208     { NSRightArrowFunctionKey, KEY_RIGHT },
209     { NSF1FunctionKey, KEY_F1 },
210     { NSF2FunctionKey, KEY_F2 },
211     { NSF3FunctionKey, KEY_F3 },
212     { NSF4FunctionKey, KEY_F4 },
213     { NSF5FunctionKey, KEY_F5 },
214     { NSF6FunctionKey, KEY_F6 },
215     { NSF7FunctionKey, KEY_F7 },
216     { NSF8FunctionKey, KEY_F8 },
217     { NSF9FunctionKey, KEY_F9 },
218     { NSF10FunctionKey, KEY_F10 },
219     { NSF11FunctionKey, KEY_F11 },
220     { NSF12FunctionKey, KEY_F12 },
221     { NSInsertFunctionKey, KEY_INSERT },
222     { NSHomeFunctionKey, KEY_HOME },
223     { NSEndFunctionKey, KEY_END },
224     { NSPageUpFunctionKey, KEY_PAGEUP },
225     { NSPageDownFunctionKey, KEY_PAGEDOWN },
226     { NSMenuFunctionKey, KEY_MENU },
227     { NSTabCharacter, KEY_TAB },
228     { NSCarriageReturnCharacter, KEY_ENTER },
229     { NSEnterCharacter, KEY_ENTER },
230     { NSBackspaceCharacter, KEY_BACKSPACE },
231     { NSDeleteCharacter, KEY_DELETE },
232     {0,0}
233 };
234
235 unsigned int CocoaKeyToVLC(unichar i_key)
236 {
237     unsigned int i;
238
239     for (i = 0; nskeys_to_vlckeys[i].i_nskey != 0; i++) {
240         if (nskeys_to_vlckeys[i].i_nskey == i_key) {
241             return nskeys_to_vlckeys[i].i_vlckey;
242         }
243     }
244     return (unsigned int)i_key;
245 }
246
247 - (unsigned int)VLCModifiersToCocoa:(NSString *)theString
248 {
249     unsigned int new = 0;
250
251     if ([theString rangeOfString:@"Command"].location != NSNotFound)
252         new |= NSCommandKeyMask;
253     if ([theString rangeOfString:@"Alt"].location != NSNotFound)
254         new |= NSAlternateKeyMask;
255     if ([theString rangeOfString:@"Shift"].location != NSNotFound)
256         new |= NSShiftKeyMask;
257     if ([theString rangeOfString:@"Ctrl"].location != NSNotFound)
258         new |= NSControlKeyMask;
259     return new;
260 }
261
262 - (NSString *)VLCKeyToString:(NSString *)theString
263 {
264     if (![theString isEqualToString:@""]) {
265         if ([theString characterAtIndex:([theString length] - 1)] != 0x2b)
266             theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""];
267         else {
268             theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""];
269             theString = [NSString stringWithFormat:@"%@+", theString];
270         }
271         if ([theString characterAtIndex:([theString length] - 1)] != 0x2d)
272             theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""];
273         else {
274             theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""];
275             theString = [NSString stringWithFormat:@"%@-", theString];
276         }
277         theString = [theString stringByReplacingOccurrencesOfString:@"Command" withString:@""];
278         theString = [theString stringByReplacingOccurrencesOfString:@"Alt" withString:@""];
279         theString = [theString stringByReplacingOccurrencesOfString:@"Shift" withString:@""];
280         theString = [theString stringByReplacingOccurrencesOfString:@"Ctrl" withString:@""];
281     }
282
283 #pragma GCC diagnostic ignored "-Wformat"
284     if ([theString length] > 1) {
285         if ([theString rangeOfString:@"Up"].location != NSNotFound)
286             return [NSString stringWithFormat:@"%C", NSUpArrowFunctionKey];
287         else if ([theString rangeOfString:@"Down"].location != NSNotFound)
288             return [NSString stringWithFormat:@"%C", NSDownArrowFunctionKey];
289         else if ([theString rangeOfString:@"Right"].location != NSNotFound)
290             return [NSString stringWithFormat:@"%C", NSRightArrowFunctionKey];
291         else if ([theString rangeOfString:@"Left"].location != NSNotFound)
292             return [NSString stringWithFormat:@"%C", NSLeftArrowFunctionKey];
293         else if ([theString rangeOfString:@"Enter"].location != NSNotFound)
294             return [NSString stringWithFormat:@"%C", NSEnterCharacter]; // we treat NSCarriageReturnCharacter as aquivalent
295         else if ([theString rangeOfString:@"Insert"].location != NSNotFound)
296             return [NSString stringWithFormat:@"%C", NSInsertFunctionKey];
297         else if ([theString rangeOfString:@"Home"].location != NSNotFound)
298             return [NSString stringWithFormat:@"%C", NSHomeFunctionKey];
299         else if ([theString rangeOfString:@"End"].location != NSNotFound)
300             return [NSString stringWithFormat:@"%C", NSEndFunctionKey];
301         else if ([theString rangeOfString:@"Pageup"].location != NSNotFound)
302             return [NSString stringWithFormat:@"%C", NSPageUpFunctionKey];
303         else if ([theString rangeOfString:@"Pagedown"].location != NSNotFound)
304             return [NSString stringWithFormat:@"%C", NSPageDownFunctionKey];
305         else if ([theString rangeOfString:@"Menu"].location != NSNotFound)
306             return [NSString stringWithFormat:@"%C", NSMenuFunctionKey];
307         else if ([theString rangeOfString:@"Tab"].location != NSNotFound)
308             return [NSString stringWithFormat:@"%C", NSTabCharacter];
309         else if ([theString rangeOfString:@"Backspace"].location != NSNotFound)
310             return [NSString stringWithFormat:@"%C", NSBackspaceCharacter];
311         else if ([theString rangeOfString:@"Delete"].location != NSNotFound)
312             return [NSString stringWithFormat:@"%C", NSDeleteCharacter];
313         else if ([theString rangeOfString:@"F12"].location != NSNotFound)
314             return [NSString stringWithFormat:@"%C", NSF12FunctionKey];
315         else if ([theString rangeOfString:@"F11"].location != NSNotFound)
316             return [NSString stringWithFormat:@"%C", NSF11FunctionKey];
317         else if ([theString rangeOfString:@"F10"].location != NSNotFound)
318             return [NSString stringWithFormat:@"%C", NSF10FunctionKey];
319         else if ([theString rangeOfString:@"F9"].location != NSNotFound)
320             return [NSString stringWithFormat:@"%C", NSF9FunctionKey];
321         else if ([theString rangeOfString:@"F8"].location != NSNotFound)
322             return [NSString stringWithFormat:@"%C", NSF8FunctionKey];
323         else if ([theString rangeOfString:@"F7"].location != NSNotFound)
324             return [NSString stringWithFormat:@"%C", NSF7FunctionKey];
325         else if ([theString rangeOfString:@"F6"].location != NSNotFound)
326             return [NSString stringWithFormat:@"%C", NSF6FunctionKey];
327         else if ([theString rangeOfString:@"F5"].location != NSNotFound)
328             return [NSString stringWithFormat:@"%C", NSF5FunctionKey];
329         else if ([theString rangeOfString:@"F4"].location != NSNotFound)
330             return [NSString stringWithFormat:@"%C", NSF4FunctionKey];
331         else if ([theString rangeOfString:@"F3"].location != NSNotFound)
332             return [NSString stringWithFormat:@"%C", NSF3FunctionKey];
333         else if ([theString rangeOfString:@"F2"].location != NSNotFound)
334             return [NSString stringWithFormat:@"%C", NSF2FunctionKey];
335         else if ([theString rangeOfString:@"F1"].location != NSNotFound)
336             return [NSString stringWithFormat:@"%C", NSF1FunctionKey];
337         /* note that we don't support esc here, since it is reserved for leaving fullscreen */
338     }
339 #pragma GCC diagnostic warning "-Wformat"
340
341     return theString;
342 }
343
344 @end