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 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <pthread.h>
33
34 #include "toolkit.h"
35 #include "toolbar.h"
36 #include "container.h"
37 #include "stock.h"
38 #include "../common/menu.h"
39 #include "../common/toolbar.h"
40 #include "../common/document.h"
41 #include "../common/properties.h"
42 #include <cx/buffer.h>
43
44 #include <X11/Intrinsic.h>
45 #include <Xm/CutPaste.h>
46
47 static XtAppContext app;
48 static Display *display;
49 static Widget active_window;
50 static const char *application_name;
51
52 static ui_callback startup_func;
53 static void *startup_data;
54 static ui_callback open_func;
55 void *open_data;
56 static ui_callback exit_func;
57 void *exit_data;
58
59 static ui_callback appclose_fnc;
60 static void *appclose_udata;
61
62 static int is_toplevel_realized =
0;
63
64 int event_pipe[
2];
65
66
67 static String fallback[] = {
68
69 "*text_area*renderTable: f1",
70 "*f1*fontType: FONT_IS_XFT",
71 "*f1*fontName: Monospace",
72 "*f1*fontSize: 11",
73 "*renderTable: rt",
74 "*rt*fontType: FONT_IS_XFT",
75 "*rt*fontName: Sans",
76 "*rt*fontSize: 11",
77
78 "*window_frame.shadowType: SHADOW_ETCHED_OUT",
79 "*window_frame.shadowThickness: 1",
80 "*togglebutton.shadowThickness: 1",
81 "*togglebutton.highlightThickness: 2",
82 NULL
83 };
84
85 void input_proc(XtPointer data,
int *source, XtInputId *iid) {
86 void *ptr;
87 read(event_pipe[
0], &ptr,
sizeof(
void*));
88 }
89
90 void ui_init(
const char *appname,
int argc,
char **argv) {
91 application_name = appname;
92 uic_init_global_context();
93
94 XtToolkitInitialize();
95 XtSetLanguageProc(
NULL,
NULL,
NULL);
96 app = XtCreateApplicationContext();
97 XtAppSetFallbackResources(app, fallback);
98
99 display = XtOpenDisplay(app,
NULL, appname, appname,
NULL,
0, &argc, argv);
100
101 uic_docmgr_init();
102 uic_menu_init();
103 uic_toolbar_init();
104 uic_load_app_properties();
105
106 if(pipe(event_pipe)) {
107 fprintf(stderr,
"UiError: Cannot create event pipe\n");
108 exit(-
1);
109 }
110 XtAppAddInput(
111 app,
112 event_pipe[
0],
113 (XtPointer)XtInputReadMask,
114 input_proc,
115 NULL);
116 }
117
118 const char* ui_appname() {
119 return application_name;
120 }
121
122 Display* ui_motif_get_display() {
123 return display;
124 }
125
126 void ui_onstartup(ui_callback f,
void *userdata) {
127 startup_func = f;
128 startup_data = userdata;
129 }
130
131 void ui_onopen(ui_callback f,
void *userdata) {
132 open_func = f;
133 open_data = userdata;
134 }
135
136 void ui_onexit(ui_callback f,
void *userdata) {
137 exit_func = f;
138 exit_data = userdata;
139 }
140
141 void ui_main() {
142 if(startup_func) {
143 startup_func(
NULL, startup_data);
144 }
145 XtAppMainLoop(app);
146 if(exit_func) {
147 exit_func(
NULL, exit_data);
148 }
149 uic_store_app_properties();
150 }
151
152 void ui_exit_mainloop() {
153 XtAppSetExitFlag(app);
154 }
155
156 void ui_secondary_event_loop(
int *loop) {
157 while(*loop && !XtAppGetExitFlag(app)) {
158 XEvent event;
159 XtAppNextEvent(app, &event);
160 XtDispatchEvent(&event);
161 }
162 }
163
164 void ui_show(UiObject *obj) {
165 uic_check_group_widgets(obj->ctx);
166 XtRealizeWidget(obj->widget);
167 }
168
169 void ui_close(UiObject *obj) {
170
171 }
172
173
174 void ui_set_enabled(
UIWIDGET widget,
int enabled) {
175 XtSetSensitive(widget, enabled);
176 }
177
178 void ui_set_show_all(
UIWIDGET widget,
int value) {
179 if(!value) {
180 XtUnmanageChild(widget);
181 }
182 }
183
184 void ui_set_visible(
UIWIDGET widget,
int visible) {
185 if(visible) {
186 XtManageChild(widget);
187 }
else {
188 XtUnmanageChild(widget);
189 }
190 }
191
192 static Boolean ui_job_finished(
void *data) {
193 UiJob *job = data;
194 if(job->finish_callback) {
195 UiEvent event;
196 event.obj = job->obj;
197 event.window = job->obj->window;
198 event.document = job->obj->ctx->document;
199 event.intval =
0;
200 event.eventdata =
NULL;
201 job->finish_callback(&event, job->finish_data);
202 }
203 free(job);
204 return TRUE;
205 }
206
207 static void* ui_jobthread(
void *data) {
208 UiJob *job = data;
209 int result = job->job_func(job->job_data);
210 if(!result) {
211 write(event_pipe[
1], &job,
sizeof(
void*));
212 XtAppAddWorkProc(app, ui_job_finished, job);
213
214 }
215 return NULL;
216 }
217
218 void ui_job(UiObject *obj, ui_threadfunc tf,
void *td, ui_callback f,
void *fd) {
219 UiJob *job = malloc(
sizeof(UiJob));
220 job->obj = obj;
221 job->job_func = tf;
222 job->job_data = td;
223 job->finish_callback = f;
224 job->finish_data = fd;
225 pthread_t pid;
226 pthread_create(&pid,
NULL, ui_jobthread, job);
227 }
228
229 void ui_clipboard_set(
char *str) {
230 int length = strlen(str) +
1;
231
232 Display *dp = XtDisplayOfObject(active_window);
233 Window window = XtWindowOfObject(active_window);
234
235 XmString label = XmStringCreateLocalized(
"toolkit_clipboard");
236 long id =
0;
237
238 while(XmClipboardStartCopy(
239 dp,
240 window,
241 label,
242 CurrentTime,
243 NULL,
244 NULL,
245 &id) == ClipboardLocked);
246 XmStringFree(label);
247
248 while(XmClipboardCopy(
249 dp,
250 window,
251 id,
252 "STRING",
253 str,
254 length,
255 1,
256 NULL) == ClipboardLocked);
257
258 while(XmClipboardEndCopy(dp, window, id) == ClipboardLocked);
259 }
260
261 char* ui_clipboard_get() {
262 Display *dp = XtDisplayOfObject(active_window);
263 Window window = XtWindowOfObject(active_window);
264
265 long id;
266 size_t size =
128;
267 char *buf = malloc(size);
268
269 int r;
270 for(;;) {
271 r = XmClipboardRetrieve(dp, window,
"STRING", buf, size,
NULL, &id);
272 if(r == ClipboardSuccess) {
273 break;
274 }
else if(r == ClipboardTruncate) {
275 size *=
2;
276 buf = realloc(buf, size);
277 }
else if(r == ClipboardNoData) {
278 free(buf);
279 buf =
NULL;
280 break;
281 }
282 }
283
284 return buf;
285 }
286
287 void ui_set_active_window(Widget w) {
288 active_window = w;
289 }
290
291 Widget ui_get_active_window() {
292 return active_window;
293 }
294
295
296
297
298 void ui_window_dark_theme(Display *dp, Window window) {
299 Atom atom = XInternAtom(dp,
"_GTK_THEME_VARIANT", False);
300 Atom type = XInternAtom(dp,
"UTF8_STRING", False);
301 XChangeProperty(
302 dp,
303 window,
304 atom,
305 type,
306 8,
307 PropModeReplace,
308 (
const unsigned char*)
"dark",
309 4);
310 }
311
312 void ui_destroy_eventdata(Widget w, XtPointer *data, XtPointer d) {
313 free(data);
314 }
315
316 void ui_set_widget_groups(UiContext *ctx, Widget widget,
const int *groups) {
317 if(!groups) {
318 return;
319 }
320 size_t ngroups = uic_group_array_size(groups);
321 ui_set_widget_ngroups(ctx, widget, groups, ngroups);
322 }
323
324 void ui_set_widget_ngroups(UiContext *ctx, Widget widget,
const int *groups,
size_t ngroups) {
325 if(ngroups >
0) {
326 uic_add_group_widget_i(ctx, widget, (ui_enablefunc)ui_set_enabled, groups, ngroups);
327 ui_set_enabled(widget,
FALSE);
328 }
329 }
330
331