-
Notifications
You must be signed in to change notification settings - Fork 14
/
main.m
156 lines (126 loc) · 5.24 KB
/
main.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
can also be compiled using
clang -fobjc-arc $OBJCFLAGS $LDFLAGS -framework Foundation -framework Cocoa LauncherGtk3/geany/geany/main.m -o geany
*/
#import <Foundation/Foundation.h>
#include <dlfcn.h>
#include <limits.h>
static NSString *get_locale(NSString *bundle_share) {
NSString *fallback = @"en_US.UTF-8";
BOOL ignore_locale = [[NSFileManager defaultManager] fileExistsAtPath: [@"~/.config/geany/ignore_locale" stringByExpandingTildeInPath]];
if (ignore_locale) {
return fallback;
}
NSArray<NSString *> *langs = [NSLocale preferredLanguages];
for (NSString *lng in langs) {
BOOL found = NO;
NSString *lang;
NSArray<NSString *> *comps = [lng componentsSeparatedByString:@"-"];
if (comps.count > 1) {
lang = [NSString stringWithFormat:@"%@_%@", [comps[0] lowercaseString], [comps[1] uppercaseString]];
NSString *path = [NSString stringWithFormat:@"%@/locale/%@", bundle_share, lang];
found = [[NSFileManager defaultManager] fileExistsAtPath:path];
}
if (!found && comps.count > 0) {
NSString *lng = [comps[0] lowercaseString];
NSString *path = [NSString stringWithFormat:@"%@/locale/%@", bundle_share, lng];
found = [[NSFileManager defaultManager] fileExistsAtPath:path];
if (found && comps.count == 1) {
lang = lng;
}
}
if (found) {
return [lang stringByAppendingString:@".UTF-8"];
}
}
return fallback;
}
static void export_env_array(NSDictionary<NSString *, NSString *> *dict) {
for (NSString *key in dict) {
setenv([key UTF8String], [dict[key] UTF8String], 1);
}
}
static int fill_argv_array(const char *arr[], NSArray<NSString *> *array) {
int i = 0;
for (NSString *value in array) {
arr[i] = [value UTF8String];
i++;
if (i == ARG_MAX - 1) {
break;
}
}
arr[i] = NULL;
return i;
}
static int run_geany() {
NSString *bundle_dir = [[NSBundle mainBundle] bundlePath];
NSString *bundle_resources = [bundle_dir stringByAppendingPathComponent: @"Contents/Resources"];
NSString *bundle_lib = [bundle_resources stringByAppendingPathComponent: @"lib"];
NSString *bundle_share = [bundle_resources stringByAppendingPathComponent: @"share"];
NSString *bundle_etc = [bundle_resources stringByAppendingPathComponent: @"etc"];
NSString *lang = get_locale(bundle_share);
//set environment variables
//see https://developer.gnome.org/gtk3/stable/gtk-running.html
NSDictionary<NSString *, NSString *> *env = @{
@"XDG_CONFIG_DIRS": bundle_etc,
@"XDG_DATA_DIRS": bundle_share,
@"GIO_MODULE_DIR": [bundle_lib stringByAppendingPathComponent: @"gio/modules"],
@"GTK_PATH": bundle_resources,
@"GTK_EXE_PREFIX": bundle_resources,
@"GTK_DATA_PREFIX": bundle_resources,
@"GTK_IM_MODULE": @"quartz",
@"GTK_IM_MODULE_FILE": [bundle_lib stringByAppendingPathComponent: @"gtk-3.0/3.0.0/immodules.cache"],
@"GDK_PIXBUF_MODULE_FILE": [bundle_lib stringByAppendingPathComponent: @"gdk-pixbuf-2.0/2.10.0/loaders.cache"],
@"LANG": lang,
@"LC_MESSAGES": lang,
@"LC_MONETARY": lang,
@"LC_COLLATE": lang,
@"LC_ALL": lang,
//TODO: replace with XDG_DATA_DIRS in Geany
@"GEANY_PLUGINS_SHARE_PATH": [bundle_share stringByAppendingPathComponent: @"geany-plugins"],
//patched in https://gitlab.gnome.org/GNOME/gtk-osx/blob/master/patches/enchant-env.patch
@"ENCHANT_MODULE_PATH": [bundle_lib stringByAppendingPathComponent: @"enchant"],
};
//set binary name and command line arguments
NSMutableArray<NSString *> *args = [NSProcessInfo.processInfo.arguments mutableCopy];
if (args.count > 1 && [args[1] hasPrefix:@"-psn_"]) {
[args removeObjectAtIndex: 1];
}
[args addObject:[NSString stringWithFormat:@"--vte-lib=%@/libvte-2.91.0.dylib", bundle_lib]];
//debugging
NSString *verbose_param = @"--osx-verbose";
if ([args containsObject: verbose_param]) {
[args removeObject:verbose_param];
NSLog(@"env: %@", env);
NSLog(@"argv: %@", args);
}
export_env_array(env);
const char *argv[ARG_MAX];
int argc = fill_argv_array(argv, args);
/*
We need to load libgeany dynamically - if we loaded it statically, it would have
been loaded by now already and the environment variables above would be set
too late (apparently they are read already when some of the libraries are loading)
*/
int ret = 1;
void *lib_handle = dlopen([[bundle_lib stringByAppendingPathComponent:@"libgeany.0.dylib"] UTF8String], RTLD_LAZY|RTLD_GLOBAL);
if (lib_handle) {
int (*main_lib)(int, char**) = dlsym(lib_handle, "main_lib");
if (main_lib) {
ret = main_lib(argc, (char **)argv);
}
else {
NSLog(@"dlsym() failed");
}
dlclose(lib_handle);
}
else {
NSLog(@"dlopen() failed (possibly unsigned libgeany.0.dylib)");
}
return ret;
}
int main(int argc, const char *argv[]) {
@autoreleasepool {
return run_geany();
}
}