#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/select.h> // only for idle_loop variant
+#include <sys/time.h> // only for idle_loop variant
+#include <pthread.h> // only for thread based variant
static GtkBuilder *builder = NULL;
static int chldin[2], chldout[2];
// { GTK_TYPE_TEXT_VIEW, "set", &ca_text_view }
// };
-void app_quit(GtkWidget *wdg, gpointer user_data) {
- exit(0);
+// ====== UI EVENTS ======
+
+void e_si_activate(GtkWidget *wdg, gpointer d) {
+ printf("%s ACTIVATE\n", (char*) d);
}
-void text_content(GtkWidget *wdg, gpointer user_data) {
- GtkEntry *e;
- if (GTK_IS_ENTRY(wdg)) {
- e = GTK_ENTRY( wdg );
- printf( "%s CHANGED %s\n",
- gtk_buildable_get_name(GTK_BUILDABLE(wdg)),
- gtk_entry_buffer_get_text( gtk_entry_get_buffer( e ) )
- );
- }
+void e_button_clicked(GtkWidget *wdg, gpointer d) {
+ printf(
+ "%s CLICKED\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg))
+ );
}
-void button_click(GtkWidget *wdg, gpointer d) {
- printf( "%s CLICKED\n",
- GTK_IS_BUILDABLE(wdg)?gtk_buildable_get_name(GTK_BUILDABLE(wdg)):(char *)d
- );
+// Radio Buttons and Checkboxes are "Toggle Buttons"
+void e_tb_toggled(GtkWidget *wdg, gpointer d) {
+ GtkToggleButton *t = GTK_TOGGLE_BUTTON(wdg);
+ printf(
+ "%s TOGGLED %i\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg)),
+ gtk_toggle_button_get_active(t)
+ );
}
-// ====== CLI ACTIONS =======
+// Radio Buttons and Checkboxes within menus are "Check Menu Items"
+void e_cmi_toggled(GtkWidget *wdg, gpointer d) {
+ GtkCheckMenuItem *c = GTK_CHECK_MENU_ITEM(wdg);
+ printf(
+ "%s TOGGLED %i\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg)),
+ gtk_check_menu_item_get_active(c)
+ );
+}
+
+gboolean s_switch_state_set(GtkWidget *wdg, gboolean state, gpointer d) {
+ GtkSwitch *s = GTK_SWITCH(wdg);
+ printf(
+ "%s STATE-SET %i\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg)),
+ state
+ );
+ return 0;
+}
+
+void e_entry_changed(GtkWidget *wdg, gpointer user_data) {
+ GtkEntry *e = GTK_ENTRY(wdg);
+ printf(
+ "%s CHANGED %s\n",
+ gtk_buildable_get_name(GTK_BUILDABLE(wdg)),
+ gtk_entry_buffer_get_text(gtk_entry_get_buffer(e))
+ );
+}
+
+void app_quit(GtkWidget *wdg, gpointer user_data) {
+ exit(0);
+}
+
+// ====== CLI ACTIONS ======
void a_text_view_set(GtkTextView *v, char *c) {
gtk_text_buffer_set_text(
if ( !wid || !wid[0]
|| !(wdg = GTK_WIDGET(gtk_builder_get_object(builder, wid)))
) return 0;
- else if (
- (GTK_IS_BUTTON(wdg) && a_button(GTK_BUTTON(wdg), cmd, args))
+ else if (0
|| (GTK_IS_ENTRY(wdg) && a_entry(GTK_ENTRY(wdg), cmd, args))
|| (GTK_IS_WINDOW(wdg) && a_window(GTK_WINDOW(wdg), cmd, args))
|| (GTK_IS_TEXT_VIEW(wdg) && a_text_view(GTK_TEXT_VIEW(wdg), cmd, args))
|| (GTK_IS_EDITABLE(wdg) && a_editable(GTK_EDITABLE(wdg), cmd, args))
+ || (GTK_IS_BUTTON(wdg) && a_button(GTK_BUTTON(wdg), cmd, args))
|| (GTK_IS_WIDGET(wdg) && a_widget(GTK_WIDGET(wdg), cmd, args))
) return 1;
else return 0;
static size_t s = 128;
static char *buf = NULL;
static int len = 0; int l;
- if (!buf) buf = malloc(s);
+ static fd_set fds;
+ struct timeval t = { .tv_sec = 0, .tv_usec = 10000 };
+ if (!buf) {
+ buf = malloc(s);
+ fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
+ }
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+ if ( select(STDIN_FILENO + 1, &fds, NULL, NULL, &t) <= 0) return G_SOURCE_CONTINUE;
while ( (l = read(STDIN_FILENO, buf + len, s - len)) > 0) {
len += l;
if ( buf[len - 1] == '\n' && (len < 2 || buf[len - 2] != '\\') ) break;
else if (len >= 2) buf[--len - 1] = '\n';
if ( len == s - 1 ) buf = realloc(buf, s+=128);
- l = read(0, buf + len, s - len);
}
if ( l > 0 ) {
buf[len - 1] = 0;
} else if (l == 0) {
exit(0);
}
- return 1;
+ return G_SOURCE_CONTINUE;
+}
+
+void* thread_readline(void *d) {
+ int l, len = 0;
+ size_t s = 128;
+ char *buf = malloc(s);
+ // if (!buf) buf = malloc(s);
+
+ while ( (l = read(STDIN_FILENO, buf + len, s - len)) > 0 ) {
+ len += l;
+ if ( buf[len - 1] == '\n' && (len < 2 || buf[len - 2] != '\\') ) {
+ buf[len - 1] = 0;
+ action(buf);
+ len = 0;
+ } else if (len >= 2) buf[--len - 1] = '\n';
+ if ( len == s - 1 ) buf = realloc(buf, s+=128);
+ }
+ exit(0); return NULL;
}
void init_widgets(gpointer wp, gpointer data) {
- GtkWidget *wdg;
+ GtkWidget *wdg; const char *name;
if (GTK_IS_BUILDABLE(wp)) {
wdg = GTK_WIDGET(wp);
- printf("%s load\n", gtk_buildable_get_name(GTK_BUILDABLE(wp)));
+ name = gtk_buildable_get_name(GTK_BUILDABLE(wp));
- if (GTK_IS_BUTTON(wdg)) g_signal_connect(wdg, "clicked", G_CALLBACK(button_click), NULL);
- else if (GTK_IS_ENTRY(wdg) ) g_signal_connect(wdg, "changed", G_CALLBACK(text_content), NULL);
- else if (GTK_IS_WINDOW(wdg)) g_signal_connect(wdg, "destroy", G_CALLBACK(app_quit), NULL);
+ if (strncmp(name, "___", 3) == 0 ) return;
+ else if (GTK_IS_TOGGLE_BUTTON(wdg)) g_signal_connect(wdg, "toggled", G_CALLBACK(e_tb_toggled), NULL);
+ else if (GTK_IS_CHECK_MENU_ITEM(wdg)) g_signal_connect(wdg, "toggled", G_CALLBACK(e_cmi_toggled), NULL);
+ else if (GTK_IS_ENTRY(wdg) ) g_signal_connect(wdg, "changed", G_CALLBACK(e_entry_changed), NULL);
+ else if (GTK_IS_WINDOW(wdg)) g_signal_connect(wdg, "destroy", G_CALLBACK(app_quit), NULL);
+ else if (GTK_IS_BUTTON(wdg)) g_signal_connect(wdg, "clicked", G_CALLBACK(e_button_clicked), NULL);
+ else { printf("%s unknown\n", name); return; }
+ printf("%s loaded\n", name);
} else if (GTK_IS_STATUS_ICON(wp)) {
printf("StatusIcon load\n");
- g_signal_connect(wp, "activate", G_CALLBACK(button_click), "StatusIcon");
+ g_signal_connect(wp, "activate", G_CALLBACK(e_si_activate), "StatusIcon");
}
}
g_slist_foreach(widgets, *init_widgets, NULL);
g_slist_free(widgets);
- fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
- g_idle_add(idle_readline, builder);
+ // g_idle_add(idle_readline, builder);
+ pthread_t rl;
+ pthread_create(&rl, NULL, thread_readline, NULL);
gtk_main();
return 0;