#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "toolkit.h"
#include "toolbar.h"
#include "container.h"
#include "stock.h"
#include "../common/menu.h"
#include "../common/toolbar.h"
#include "../common/document.h"
#include "../common/properties.h"
#include <cx/buffer.h>
#include <X11/Intrinsic.h>
#include <Xm/CutPaste.h>
static XtAppContext app;
static Display *display;
static Widget active_window;
static const char *application_name;
static ui_callback startup_func;
static void *startup_data;
static ui_callback open_func;
void *open_data;
static ui_callback exit_func;
void *exit_data;
static ui_callback appclose_fnc;
static void *appclose_udata;
static int is_toplevel_realized =
0;
int event_pipe[
2];
static String fallback[] = {
"*text_area*renderTable: f1",
"*f1*fontType: FONT_IS_XFT",
"*f1*fontName: Monospace",
"*f1*fontSize: 11",
"*renderTable: rt",
"*rt*fontType: FONT_IS_XFT",
"*rt*fontName: Sans",
"*rt*fontSize: 11",
"*window_frame.shadowType: SHADOW_ETCHED_OUT",
"*window_frame.shadowThickness: 1",
"*togglebutton.shadowThickness: 1",
"*togglebutton.highlightThickness: 2",
NULL
};
void input_proc(XtPointer data,
int *source, XtInputId *iid) {
void *ptr;
read(event_pipe[
0], &ptr,
sizeof(
void*));
}
void ui_init(
const char *appname,
int argc,
char **argv) {
application_name = appname;
uic_init_global_context();
XtToolkitInitialize();
XtSetLanguageProc(
NULL,
NULL,
NULL);
app = XtCreateApplicationContext();
XtAppSetFallbackResources(app, fallback);
display = XtOpenDisplay(app,
NULL, appname, appname,
NULL,
0, &argc, argv);
uic_docmgr_init();
uic_menu_init();
uic_toolbar_init();
uic_load_app_properties();
if(pipe(event_pipe)) {
fprintf(stderr,
"UiError: Cannot create event pipe\n");
exit(-
1);
}
XtAppAddInput(
app,
event_pipe[
0],
(XtPointer)XtInputReadMask,
input_proc,
NULL);
}
const char* ui_appname() {
return application_name;
}
Display* ui_motif_get_display() {
return display;
}
void ui_onstartup(ui_callback f,
void *userdata) {
startup_func = f;
startup_data = userdata;
}
void ui_onopen(ui_callback f,
void *userdata) {
open_func = f;
open_data = userdata;
}
void ui_onexit(ui_callback f,
void *userdata) {
exit_func = f;
exit_data = userdata;
}
void ui_main() {
if(startup_func) {
startup_func(
NULL, startup_data);
}
XtAppMainLoop(app);
if(exit_func) {
exit_func(
NULL, exit_data);
}
uic_store_app_properties();
}
void ui_exit_mainloop() {
XtAppSetExitFlag(app);
}
void ui_secondary_event_loop(
int *loop) {
while(*loop && !XtAppGetExitFlag(app)) {
XEvent event;
XtAppNextEvent(app, &event);
XtDispatchEvent(&event);
}
}
void ui_show(UiObject *obj) {
uic_check_group_widgets(obj->ctx);
XtRealizeWidget(obj->widget);
}
void ui_close(UiObject *obj) {
}
void ui_set_enabled(
UIWIDGET widget,
int enabled) {
XtSetSensitive(widget, enabled);
}
void ui_set_show_all(
UIWIDGET widget,
int value) {
if(!value) {
XtUnmanageChild(widget);
}
}
void ui_set_visible(
UIWIDGET widget,
int visible) {
if(visible) {
XtManageChild(widget);
}
else {
XtUnmanageChild(widget);
}
}
static Boolean ui_job_finished(
void *data) {
UiJob *job = data;
if(job->finish_callback) {
UiEvent event;
event.obj = job->obj;
event.window = job->obj->window;
event.document = job->obj->ctx->document;
event.intval =
0;
event.eventdata =
NULL;
job->finish_callback(&event, job->finish_data);
}
free(job);
return TRUE;
}
static void* ui_jobthread(
void *data) {
UiJob *job = data;
int result = job->job_func(job->job_data);
if(!result) {
write(event_pipe[
1], &job,
sizeof(
void*));
XtAppAddWorkProc(app, ui_job_finished, job);
}
return NULL;
}
void ui_job(UiObject *obj, ui_threadfunc tf,
void *td, ui_callback f,
void *fd) {
UiJob *job = malloc(
sizeof(UiJob));
job->obj = obj;
job->job_func = tf;
job->job_data = td;
job->finish_callback = f;
job->finish_data = fd;
pthread_t pid;
pthread_create(&pid,
NULL, ui_jobthread, job);
}
void ui_clipboard_set(
char *str) {
int length = strlen(str) +
1;
Display *dp = XtDisplayOfObject(active_window);
Window window = XtWindowOfObject(active_window);
XmString label = XmStringCreateLocalized(
"toolkit_clipboard");
long id =
0;
while(XmClipboardStartCopy(
dp,
window,
label,
CurrentTime,
NULL,
NULL,
&id) == ClipboardLocked);
XmStringFree(label);
while(XmClipboardCopy(
dp,
window,
id,
"STRING",
str,
length,
1,
NULL) == ClipboardLocked);
while(XmClipboardEndCopy(dp, window, id) == ClipboardLocked);
}
char* ui_clipboard_get() {
Display *dp = XtDisplayOfObject(active_window);
Window window = XtWindowOfObject(active_window);
long id;
size_t size =
128;
char *buf = malloc(size);
int r;
for(;;) {
r = XmClipboardRetrieve(dp, window,
"STRING", buf, size,
NULL, &id);
if(r == ClipboardSuccess) {
break;
}
else if(r == ClipboardTruncate) {
size *=
2;
buf = realloc(buf, size);
}
else if(r == ClipboardNoData) {
free(buf);
buf =
NULL;
break;
}
}
return buf;
}
void ui_set_active_window(Widget w) {
active_window = w;
}
Widget ui_get_active_window() {
return active_window;
}
void ui_window_dark_theme(Display *dp, Window window) {
Atom atom = XInternAtom(dp,
"_GTK_THEME_VARIANT", False);
Atom type = XInternAtom(dp,
"UTF8_STRING", False);
XChangeProperty(
dp,
window,
atom,
type,
8,
PropModeReplace,
(
const unsigned char*)
"dark",
4);
}
void ui_destroy_eventdata(Widget w, XtPointer *data, XtPointer d) {
free(data);
}
void ui_set_widget_groups(UiContext *ctx, Widget widget,
const int *groups) {
if(!groups) {
return;
}
size_t ngroups = uic_group_array_size(groups);
ui_set_widget_ngroups(ctx, widget, groups, ngroups);
}
void ui_set_widget_ngroups(UiContext *ctx, Widget widget,
const int *groups,
size_t ngroups) {
if(ngroups >
0) {
uic_add_group_widget_i(ctx, widget, (ui_enablefunc)ui_set_enabled, groups, ngroups);
ui_set_enabled(widget,
FALSE);
}
}