EGong

An UDP Multicast messaging application
git clone git://xatko.vsos.ethz.ch/EGong.git
Log | Files | Refs

commit a65525ad47984fc98be4f75440755f028a352bc5
parent 4589d703f7b34e0cfe226628c05a86d4741e267c
Author: Dominik Schmidt <das1993@hotmail.com>
Date:   Thu, 11 Sep 2014 16:39:05 +0200

Switched to advanced GUI handling.

It is still incomplete and most likely unstable.

Diffstat:
CMakeLists.txt | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
data/EGong.blend | 0
data/EGong.ico | 0
data/EGong.png | 0
include/CNC.h | 20+++++---------------
include/Interfaces.h | 44+++++++++++++++++++++++++++++++++++++-------
include/Interfaces/Audio.h | 2+-
include/Interfaces/CMD.h | 7+++----
include/Interfaces/GTK.h | 20++++++++++++++------
include/Interfaces/GTK/Message.h | 2--
include/Interfaces/GTK/NewMessage.h | 8--------
include/Interfaces/GTK/TrayIcon.h | 13-------------
include/Interfaces/GUI.h | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/Interfaces/STDIO.h | 4++--
include/Interfaces/Windows.h | 35+++++++++++++++++++++++++++++++----
include/Main.h | 8++++++++
include/Packet.h | 3++-
include/Util/Command.h | 12+++++++++---
include/Util/Config.h | 10++++++++++
include/Util/Config_Compiletime.h | 4----
include/Util/Config_Compiletime.h.in | 3+++
include/Util/Dependencies.h | 17+++++++++++++++++
include/Util/Misc.h | 8++++++++
include/Util/Socket.h | 2+-
include/Util/Waiter.h | 4++--
src/CNC.c | 59+++++++++--------------------------------------------------
src/EGong.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
src/Interfaces.c | 228+++++++++++++++++++++++++++++++++----------------------------------------------
src/Interfaces/Audio.c | 2+-
src/Interfaces/CMD.c | 48+++++++++++++-----------------------------------
src/Interfaces/GTK.c | 280++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
src/Interfaces/GTK/Message.c | 19-------------------
src/Interfaces/GTK/NewMessage.c | 47-----------------------------------------------
src/Interfaces/GTK/TrayIcon.c | 51---------------------------------------------------
src/Interfaces/GUI.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/Interfaces/STDIO.c | 11+++++------
src/Interfaces/Windows.c | 608+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
src/Interfaces/Windows.rc | 1+
src/Main.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
src/Packet.c | 11++++++-----
src/Util/Command.c | 27+++++++++++++++++++++++++++
src/Util/Config.c | 9++++++---
src/Util/Dependencies.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
src/Util/Log.c | 40+++++++++++++++++++++++-----------------
src/Util/Socket.c | 20+++++++++++++++-----
src/Util/Waiter.c | 16++--------------
46 files changed, 1646 insertions(+), 590 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -18,43 +18,48 @@ macro(absolute_libs dest libs) endforeach(lib) endmacro(absolute_libs) -macro(include_pkgconfig) -include(/mnt/Share/Programme/SelfBuilt/C/EGong/utils/CMakeModules/FindPkgConfig.cmake) -endmacro(include_pkgconfig) - macro(EGong_link_libs libs) set(EGONG_EXT_LIBS "${EGONG_EXT_LIBS}${libs};") endmacro(EGong_link_libs) -project(EGong) +project(EGong C) set(EGong_VERSION_MAJOR 0) set(EGong_VERSION_MINOR 1) set(EGONG_SRCDIR src/) -set(EGONG_LIBS Interfaces/CMD Util/Command Interfaces Interfaces/STDIO CNC Util/Config Util/Socket Packet Util/Waiter Util/Log Util/Misc Util/Hash) +set(EGONG_DATADIR data/) set(EGONG_EXT_LIBS) include_directories("${PROJECT_SOURCE_DIR}/include") configure_file( "${PROJECT_SOURCE_DIR}/include/Util/Config_Compiletime.h.in" "${PROJECT_SOURCE_DIR}/include/Util/Config_Compiletime.h" ) -add_definitions(-std=gnu99) +set(CMAKE_CFLAGS, ${CMAKE_CFLAGS} -std=gnu99) if(CMAKE_FIND_ROOT_PATH) link_directories(${CMAKE_FIND_ROOT_PATH}/usr/lib) endif(CMAKE_FIND_ROOT_PATH) option(USE_GTK "Compile an interface for GTK" OFF) +option(USE_LIBNOTIFY "Compile an interface for linux libnotify" OFF) option(USE_AO "Compile an interface for Audio" OFF) option(USE_WINGUI "Compile an interface for the Windows GUI-Shell" OFF) -add_executable(EGong src/EGong.c) - if(USE_GTK) find_package(GTK2) if(GTK2_FOUND) - set(EGONG_LIBS ${EGONG_LIBS} Interfaces/GTK Interfaces/GTK/Message Interfaces/GTK/TrayIcon Interfaces/GTK/NewMessage) include_directories(${GTK2_INCLUDE_DIRS}) EGong_link_libs("${GTK2_LIBRARIES}") - Message("${GTK2_LIBRARIES} vs ${EGONG_EXT_LIBS}") + if(USE_LIBNOTIFY) + find_package(PkgConfig) + if(PKGCONFIG_FOUND) + pkg_check_modules(LIBNOTIFY libnotify) + if(LIBNOTIFY_FOUND) + include_directories(${LIBNOTIFY_INCLUDE_DIRS}) + EGong_link_libs("${LIBNOTIFY_LIBRARIES}") + else(NOT LIBNOTIFY_FOUND) + set(USE_LIBNOTIFY OFF) + endif(LIBNOTIFY_FOUND) + endif(PKGCONFIG_FOUND) + endif(USE_LIBNOTIFY) else(NOT GTK2_FOUND) set(USE_GTK OFF) endif(GTK2_FOUND) @@ -65,7 +70,6 @@ if(USE_AO) if(PKGCONFIG_FOUND) pkg_check_modules(LIBAO ao) if(LIBAO_FOUND) - set(EGONG_LIBS ${EGONG_LIBS} Interfaces/Audio) include_directories(${LIBAO_INCLUDE_DIRS}) EGong_link_libs("${LIBAO_LIBRARIES} m") else(NOT LIBAO_FOUND) @@ -75,15 +79,51 @@ if(USE_AO) endif(USE_AO) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + ENABLE_LANGUAGE(RC) EGong_link_libs("ws2_32") if(USE_WINGUI) - set(EGONG_LIBS ${EGONG_LIBS} Interfaces/Windows) - EGong_link_libs("gdi32 wldap32") + set(WIN32_EXECUTABLE ON) + EGong_link_libs("gdi32") +# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mwindows") endif(USE_WINGUI) endif(CMAKE_SYSTEM_NAME STREQUAL "Windows") - - +add_executable(EGong src/EGong.c src/Interfaces/Windows.rc) +macro(addlibs libs) + set(EGONG_LIBS "${EGONG_LIBS}" "${libs}") +endmacro(addlibs) +set(EGONG_LIBS ${EGONG_LIBS} + Main + Util/Waiter + Interfaces + Interfaces/STDIO + Interfaces/CMD) +if(USE_WINGUI) +set(EGONG_LIBS ${EGONG_LIBS} + Interfaces/GUI + Interfaces/Windows +) +endif() +if(USE_GTK) +set(EGONG_LIBS ${EGONG_LIBS} + Interfaces/GUI + Interfaces/GTK +) +endif() +set(EGONG_LIBS ${EGONG_LIBS} + CNC + Packet + Util/Misc + Util/Dependencies + Util/Command + Util/Socket + Util/Hash + Util/Array + Util/SAlloc + Util/Config + Util/Log +) +message(${EGONG_LIBS}) foreach(lib ${EGONG_LIBS}) addlib(${lib}) endforeach(lib) @@ -92,7 +132,9 @@ target_link_libraries(EGong ${EGONG_EXT_LIBS}) #INSTALL install(TARGETS EGong DESTINATION bin) - +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + install(FILES ${EGONG_DATADIR}/EGong.ico DESTINATION share) +endif() #PACKING absolute_libs(ABS_LIBS "${OPENSSL_LIBRARIES};${LIBAO_LIBRARIES}") set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${ABS_LIBS}) diff --git a/data/EGong.blend b/data/EGong.blend Binary files differ. diff --git a/data/EGong.ico b/data/EGong.ico Binary files differ. diff --git a/data/EGong.png b/data/EGong.png Binary files differ. diff --git a/include/CNC.h b/include/CNC.h @@ -1,18 +1,8 @@ #pragma once - - -extern int EGong_cnc_init(unsigned int requirements); -extern int EGong_cnc_sendmessage(const char *msg, const char *dest); -extern int EGong_cnc_getmessage(char **msg); -extern void EGong_cnc_freemessage(char *msg); +#include <EGong/Util/Misc.h> +extern int EGong_cnc_sendmessage(const String *msg, const char *dest); +extern int EGong_cnc_getmessage(String *msg); +extern void EGong_cnc_freemessage(String *msg); extern void EGong_cnc_deinit(void); -extern int EGong_cnc_sendmessage_broad(const char *msg); +extern int EGong_cnc_sendmessage_broad(const String *msg); -enum EGONG_INTERFACE_REQUIREMENTS{ - EGONG_REQUIREMENT_NONE=(0), - EGONG_REQUIREMENT_LISTENER=(1<<0), - EGONG_REQUIREMENT_SOCKETS=(1<<1), - EGONG_REQUIREMENT_TERMINAL=(1<<2), - EGONG_REQUIREMENT_GTK=(1<<3), - EGONG_REQUIREMENT_ALL=(~0) -}; diff --git a/include/Interfaces.h b/include/Interfaces.h @@ -1,33 +1,63 @@ #pragma once #include <EGong/CNC.h> +#include <EGong/Util/Misc.h> enum EGONG_INTERFACE_STATE{ EGONG_INTERFACE_ACTIVE=(1<<0), EGONG_INTERFACE_SETUP=(1<<1) }; - +struct EGong_interface; +struct EGong_if_ptrtbl{ + int (*setup) (struct EGong_interface *interface); + int (*cmd) (char *msg); + int (*cycle) (struct EGong_interface *interface, String *msg, char **dest); + int (*display) (struct EGong_interface *interface, const String *msg); + int (*shutdown) (struct EGong_interface *interface); + + int(*sock_watch)(int socket, unsigned short int type); + int(*loop)(void); +}; struct EGong_interface{ char *name; char identifier; unsigned int requirements; unsigned short int state; - int(*setup)(struct EGong_interface *interface); - int(*shutdown)(struct EGong_interface *interface); - int(*display_message)(struct EGong_interface *interface, const char *msg); - int(*cycle)(struct EGong_interface *interface, char **msg, char **dest); + struct EGong_if_ptrtbl *funcs; }; extern unsigned short int EGong_interfaces_userstreams; extern int EGong_interface_init(unsigned int requirement_mask); extern int EGong_interface_cycle(void); -extern void EGong_interface_deinit(void); +extern int EGong_interface_deinit(void); extern struct EGong_interface EGong_interfaces[]; extern int EGong_interface_setup(struct EGong_interface *interface); extern int EGong_interface_activate(struct EGong_interface *interface); extern int EGong_interface_shutdown(struct EGong_interface *interface); extern int EGong_interface_deactivate(struct EGong_interface *interface); extern struct EGong_interface *EGong_interface_get_from_id(char identifier); - +#define IF_ACTIVE(INTERFACE) (((INTERFACE).state&EGONG_INTERFACE_ACTIVE)>0) +#define IF_SETUP(INTERFACE) (((INTERFACE).state&EGONG_INTERFACE_SETUP)>0) +#define IF_CAN_SHUTDOWN(INTERFACE) ((INTERFACE).funcs->shutdown!=NULL) +#define IF_CAN_CYCLE(INTERFACE) ((INTERFACE).funcs->cycle!=NULL) +#define IF_CAN_DISPLAY(INTERFACE) ((INTERFACE).funcs->display!=NULL) +#define IF_CAN_SETUP(INTERFACE) ((INTERFACE).funcs->setup!=NULL) +#define IF_TRY_SETUP(INTERFACE) ((IF_SETUP(INTERFACE)&&IF_CAN_SETUP(INTERFACE)) ? (INTERFACE).funcs->setup(&INTERFACE) : EGONG_INTERFACE_RETURN_OK) +#define EGONG_INTERFACE_INTERPRET_RET(RET, INTERFACE)\ +if(RET==EGONG_INTERFACE_RETURN_FATAL){\ + do_log("Couldn't run interface function, exiting", LOG_TYPE_NORMAL, LOG_LEVEL_FATAL);\ + return -1;\ +}\ +else if(RET==EGONG_INTERFACE_RETURN_ERROR){\ + do_log("Couldn't run interface function, skipping", LOG_TYPE_NORMAL, LOG_LEVEL_WARNING);\ +}\ +else if(RET==EGONG_INTERFACE_RETURN_EXIT){\ + do_log_call_composite(LOG_COMPOSE_SRC, LOG_TYPE_NORMAL, LOG_LEVEL_INFO, EGong_global_configuration.log.destinations, "Interface ", (INTERFACE).name, " requested exit", NULL);\ + return 1;\ +}\ +else if(RET==EGONG_INTERFACE_RETURN_BREAK){\ + do_log("Interface function requested queueabortion", LOG_TYPE_NORMAL, LOG_LEVEL_INFO);\ + break;\ +} enum EGONG_INTERFACE_RETURN{ EGONG_INTERFACE_RETURN_FATAL=-2, EGONG_INTERFACE_RETURN_ERROR=-1, diff --git a/include/Interfaces/Audio.h b/include/Interfaces/Audio.h @@ -2,5 +2,5 @@ int EGong_if_audio_setup(struct EGong_interface *interface); -int EGong_if_audio_display(struct EGong_interface *interface, const char *msg); +int EGong_if_audio_display(struct EGong_interface *interface, const String *msg); int EGong_if_audio_shutdown(struct EGong_interface *interface); diff --git a/include/Interfaces/CMD.h b/include/Interfaces/CMD.h @@ -16,12 +16,11 @@ struct EGong_command_if_cmd{ extern int EGong_if_cmd_interfaceselect(const char *data); extern struct EGong_command_if_cmd *EGong_if_cmd_get_from_char(const char *commandline); -extern int EGong_if_cmd_exec(unsigned int execution, struct EGong_interface *interface, char **msg, char **dest); +extern int EGong_if_cmd_exec(unsigned int execution, struct EGong_interface *interface, String *msg, char **dest); extern int EGong_if_cmd_setup(struct EGong_interface *interface); -extern int EGong_if_cmd_cycle(struct EGong_interface *interface, char **msg, char **dest); +extern int EGong_if_cmd_cycle(struct EGong_interface *interface, String *msg, char **dest); extern int EGong_if_cmd_shutdown(struct EGong_interface *interface); -extern int EGong_if_cmd_gtk_msg(void); -extern int EGong_if_cmd_windows_msg(void); +extern int EGong_if_cmd_gui_msg(void); extern int EGong_if_cmd_send_message(char *msg); extern int EGong_if_cmd_help(void); diff --git a/include/Interfaces/GTK.h b/include/Interfaces/GTK.h @@ -1,15 +1,23 @@ #pragma once #include <EGong/Interfaces.h> +#include <EGong/Interfaces/GUI.h> #include <gtk/gtk.h> extern GtkWidget *Egong_if_gtk_root; -int EGong_if_gtk_int_setup(unsigned int what); - -int EGong_if_gtk_setup(struct EGong_interface *interface); -int EGong_if_gtk_cycle(struct EGong_interface *interface, char **msg, char **dest); -int EGong_if_gtk_display(struct EGong_interface *interface, const char *msg); -int EGong_if_gtk_shutdown(struct EGong_interface *interface); +extern int EGong_if_gtk_int_setup(unsigned int what); + +extern int EGong_if_gtk_setup(struct EGong_interface *interface); +extern int EGong_if_gtk_cycle(struct EGong_interface *interface, String *msg, char **dest); +extern int EGong_if_gtk_display(struct EGong_interface *interface, const String *msg); +extern int EGong_if_gtk_shutdown(struct EGong_interface *interface); +extern GtkWidget *EGong_if_gtk_create_gui(struct EGong_GUI_item *parent, struct EGong_GUI_item *this); +extern void *EGong_gtk_get_item_value(struct EGong_GUI_item *itm); +extern int EGong_gtk_waiter_add(int sock, unsigned short int type); +extern void EGong_if_gtk_show_element(struct EGong_GUI_item *itm); +extern void EGong_if_gtk_free_item_value(struct EGong_GUI_item *itm, void *element); +extern int EGong_if_gtk_main(void); +extern struct EGong_if_ptrtbl EGong_if_gtk_ptrtbl; enum EGONG_IF_GTK_INIT{ EGONG_IF_GTK_INIT_ROOT=(1<<0), EGONG_IF_GTK_INIT_TRAY=(1<<1), diff --git a/include/Interfaces/GTK/Message.h b/include/Interfaces/GTK/Message.h @@ -1,2 +0,0 @@ -#pragma once -extern void EGong_if_gtk_msg_display(const char *msg); diff --git a/include/Interfaces/GTK/NewMessage.h b/include/Interfaces/GTK/NewMessage.h @@ -1,8 +0,0 @@ -#pragma once -#include <gtk/gtk.h> -extern GtkWidget *EGong_if_gtk_newmsg_dialog; -extern void EGong_if_gtk_newmsg_send_callback(GtkDialog *caller, guint button, gpointer data); - -extern void EGong_if_gtk_newmsg_display_construct(unsigned short int single); -extern void EGong_if_gtk_newmsg_display_single(void); -extern void EGong_if_gtk_newmsg_display(void); diff --git a/include/Interfaces/GTK/TrayIcon.h b/include/Interfaces/GTK/TrayIcon.h @@ -1,13 +0,0 @@ -#pragma once - -#include <gtk/gtk.h> -extern GtkStatusIcon *EGong_if_gtk_tray_root; -extern GtkWidget *EGong_if_gtk_tray_menu; -extern void EGong_if_gtk_tray_popup(GtkStatusIcon *icon, guint button, guint activation_time, gpointer data); -extern int EGong_if_gtk_tray_setup(); - -struct EGong_if_gtk_tray_menu_call{ - char *name; - char *tooltip; - char *message; -}; diff --git a/include/Interfaces/GUI.h b/include/Interfaces/GUI.h @@ -0,0 +1,111 @@ +#pragma once + +#include <EGong/Util/Command.h> +#include <EGong/Util/Config_Compiletime.h> +#include <EGong/Interfaces.h> + +#ifdef USE_WINGUI +typedef wchar_t guichar; +#define GUIT(TEXT) L##TEXT +#else +typedef char guichar; +#define GUIT(TEXT) TEXT +#endif + +enum EGONG_GUI_TYPE{ + EGONG_GUI_TYPE_NONE, + EGONG_GUI_TYPE_GTK, + EGONG_GUI_TYPE_WINGUI, +}; +enum EGONG_GUI_EVSRC{ + EGONG_GUI_EVSRC_ELEMENT, + EGONG_GUI_EVSRC_STATIC, +}; +enum EGONG_GUI_MENUITEM_IMAGES{ + EGUI_MIMG_EXIT, +}; +enum EGONG_GUI_ITEM{ + EGONG_GUI_WINDOW, + EGONG_GUI_BUTTON, + EGONG_GUI_LABEL, + EGONG_GUI_TEXT, + EGONG_GUI_MENU, + EGONG_GUI_MENUITEM, + EGONG_GUI_MENUITEM_IMAGE, + EGONG_GUI_MENUITEM_SEPARATOR, + EGONG_GUI_SYSTRAY, + EGONG_GUI_HBOX, + EGONG_GUI_VBOX, + EGONG_GUI_DIALOG, +}; +struct EGong_GUI_item{ + unsigned short int type; + guichar *text; + guichar *tooltip; + void *extra; + void *itemptr; + void *userdata; + struct EGong_GUI_item **child; + struct EGong_GUI_event **events; +}; + +struct EGong_GUI_event_source{ + unsigned int type; + void *data; +}; +struct EGong_GUI_event{ + guichar *type; + struct EGong_command command; + struct EGong_GUI_event_source **sources; +}; +extern void EGong_GUI_event_hide(void *gui_element); +extern void *EGong_GUI_create(struct EGong_GUI_item *gui); +extern void EGong_GUI_event_callback(struct EGong_GUI_event *event); +extern int EGong_GUI_exit(void); + +#ifdef USE_GTK +static const unsigned int EGong_GUI_type=EGONG_GUI_TYPE_GTK; +#else +#ifdef USE_WINGUI +static const unsigned int EGong_GUI_type=EGONG_GUI_TYPE_WINGUI; +#else +static const unsigned int EGong_GUI_type=EGONG_GUI_TYPE_NONE; +#endif +#endif + +#define EGUI_ARR (struct EGong_GUI_item **)&(struct EGong_GUI_item *[]) +#define EGUI_EL &(struct EGong_GUI_item) +#define EGUI_ELX(ELEMENT) (struct EGong_GUI_item*)&ELEMENT +#define EGUI_FIN (struct EGong_GUI_item*)NULL + +#define EEV_ARR (struct EGong_GUI_event **)&(struct EGong_GUI_event *[]) +#define EEV_EL &(struct EGong_GUI_event) +#define EEV_ELX(ELEMENT) (struct EGong_GUI_event*)&ELEMENT +#define EEV_FIN (struct EGong_GUI_event*)NULL + +#define EES_ARR (struct EGong_GUI_event_source **)&(struct EGong_GUI_event_source *[]) +#define EES_EL &(struct EGong_GUI_event_source) +#define EES_ELX(ELEMENT) (struct EGong_GUI_event_source*)&ELEMENT +#define EES_FIN (struct EGong_GUI_event_source*)NULL + +struct EGong_if_gui_ptrtbl{ + struct EGong_if_ptrtbl *ifptrtbl; + void *(*create)(struct EGong_GUI_item *parent, struct EGong_GUI_item *this); + void *(*get_value)(struct EGong_GUI_item *itm); + void (*free_value)(struct EGong_GUI_item *itm, void *value); + void (*show)(struct EGong_GUI_item *itm); +}; + +extern int EGong_if_gui_setup(struct EGong_interface *interface); +extern int EGong_if_gui_cmd(char *msg); +extern int EGong_if_gui_cycle(struct EGong_interface *interface, String *msg, char **dest); +extern int EGong_if_gui_display(struct EGong_interface *interface, const String *msg); +extern int EGong_if_gui_shutdown(struct EGong_interface *interface); +extern int EGong_if_gui_sockwatch(int sock, unsigned short int type); +extern int EGong_if_gui_loop(void); + + +extern char *EGong_GUI_item_names[]; + +extern struct EGong_GUI_item EGong_GUI_newmessage; +extern struct EGong_GUI_item EGong_GUI_systray; diff --git a/include/Interfaces/STDIO.h b/include/Interfaces/STDIO.h @@ -3,5 +3,5 @@ extern int EGong_if_stdio_setup(struct EGong_interface *interface); -extern int EGong_if_stdio_cycle(struct EGong_interface *interface, char **msg, char **dest); -extern int EGong_if_stdio_display(struct EGong_interface *interface, const char *msg); +extern int EGong_if_stdio_cycle(struct EGong_interface *interface, String *msg, char **dest); +extern int EGong_if_stdio_display(struct EGong_interface *interface, const String *msg); diff --git a/include/Interfaces/Windows.h b/include/Interfaces/Windows.h @@ -1,8 +1,35 @@ #pragma once +#define UNICODE +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <EGong/Interfaces.h> +#include <EGong/Interfaces/GUI.h> +#include <EGong/Util/Misc.h> +#define WM_TRAY_ACTION WM_USER+1 +#define WM_SOCKET WM_USER+2 +extern struct EGong_if_ptrtbl EGong_if_win_ptrtbl; +extern WNDCLASSW EGong_if_win_getmsg; +extern HWND EGong_if_win_getmsg_editfield; +extern struct EGong_GUI_item *EGong_if_win_global_systray; +extern struct Array EGong_if_win_menus; +extern struct Array EGong_if_win_windows; +extern HWND EGong_if_win_create_wrapper(struct EGong_GUI_item *parent, struct EGong_GUI_item *this); +extern HWND EGong_if_win_create(struct EGong_GUI_item *parent, struct EGong_GUI_item *this, unsigned int child); +extern void EGong_if_win_show_element(struct EGong_GUI_item *itm); +extern void EGong_if_win_show_item(HWND item); +extern void EGong_if_win_free_item_value(struct EGong_GUI_item *item, void *value); +extern void *EGong_if_win_get_item_value(struct EGong_GUI_item *item); +extern void EGong_if_win_trayhandler(struct EGong_GUI_item *item, unsigned short int type, int x, int y, HWND hwnd); +extern void EGong_if_win_actionhandler(struct EGong_GUI_item *item); extern int EGong_if_win_setup(struct EGong_interface *interface); -extern int EGong_if_win_cycle(struct EGong_interface *interface, char **msg, char **dest); -extern int EGong_if_win_display(struct EGong_interface *interface, const char *msg); - -extern int EGong_if_win_getmsgdialog(); +extern int EGong_if_win_cmd(char *msg); +extern int EGong_if_win_cycle(struct EGong_interface *interface, String *msg, char **dest); +extern int EGong_if_win_display(struct EGong_interface *interface, const String *msg); +extern void EGong_if_win_destroy(struct EGong_GUI_item *item); +extern int EGong_if_win_waiter_add(int sock, unsigned short int type); +extern void EGong_if_win_destroy_wrapper(struct EGong_GUI_item **item); +extern int EGong_if_win_shutdown(struct EGong_interface *interface); +extern int EGong_if_win_loop(void); +extern HINSTANCE EGong_if_win_instance; diff --git a/include/Main.h b/include/Main.h @@ -0,0 +1,8 @@ +#pragma once +extern int(*Egong_main_loop_ptr)(void); +extern int EGong_main_do(void); +extern int EGong_main_init(void); +extern int EGong_main_loop_default(void); +extern void EGong_main_deinit(void); + +extern int EGong_main_loop(); diff --git a/include/Packet.h b/include/Packet.h @@ -3,6 +3,7 @@ #include <stddef.h> #include <EGong/Util/Hash.h> #include <EGong/Util/Socket.h> +#include <EGong/Util/Misc.h> #define EGONG_PACKET_RAND_LENGTH 10 @@ -23,7 +24,7 @@ struct EGong_packet{ extern int EGong_calculate_package_hash(struct EGong_packet *packet, unsigned char *dest, char *cookie); -extern int EGong_generate_packet(struct EGong_packet *packet, const char *msg, unsigned int msg_length); +extern int EGong_generate_packet(struct EGong_packet *packet, const String *msg); extern int EGong_send_packet(struct EGong_packet *packet, const char *dest); extern void EGong_packet_free(struct EGong_packet *packet); extern int EGong_packet_alloc(struct EGong_packet *packet, char **dest, unsigned int additional); diff --git a/include/Util/Command.h b/include/Util/Command.h @@ -8,16 +8,21 @@ struct EGong_command_type{ }; enum EGONG_COMMAND_TYPE{ + EGONG_COMMAND_ARG0, EGONG_COMMAND_UINT_INC, EGONG_COMMAND_UINT_DEC, - EGONG_COMMAND_UINT_SET, - EGONG_COMMAND_STR_SET, EGONG_COMMAND_BOOL_TRUE, EGONG_COMMAND_BOOL_FALSE, - EGONG_COMMAND_BOOL_SET, EGONG_COMMAND_FUNC_VOID, + EGONG_COMMAND_ARG1, + EGONG_COMMAND_BOOL_SET, + EGONG_COMMAND_UINT_SET, + EGONG_COMMAND_STR_SET, EGONG_COMMAND_FUNC_UINT, EGONG_COMMAND_FUNC_CHAR, + EGONG_COMMAND_FUNC_STRING, + EGONG_COMMAND_FUNC_POINTER, + EGONG_COMMAND_ARG2, EGONG_COMMAND_FUNC_2CHAR }; enum EGONG_COMMAND_MATCH{ @@ -42,3 +47,4 @@ struct EGong_command_array{ extern struct EGong_command *EGong_command_match(struct EGong_command_array *commands, const char *data, unsigned int match_type); extern int EGong_command_exec(struct EGong_command *command, void **data); extern void EGong_command_print_help(struct EGong_command_array *commands, int destination, char *appendix); +extern unsigned int EGong_command_argc(struct EGong_command *command); diff --git a/include/Util/Config.h b/include/Util/Config.h @@ -13,6 +13,9 @@ struct EGong_config_packet{ size_t packet_maxlen; char *cookie; }; +struct EGong_config_gui{ + unsigned int destinations; +}; struct EGong_config_server{ unsigned int port; char *bind_ip; @@ -21,6 +24,7 @@ struct EGong_config{ struct EGong_config_log log; struct EGong_config_server server; struct EGong_config_packet packet; + struct EGong_config_gui gui; }; struct EGong_config_file_entry{ @@ -44,6 +48,12 @@ enum EGONG_CONFIG_FILE_TYPE{ EGONG_CONFIG_TYPE_BITMASK, EGONG_CONFIG_TYPE_BOOL, }; +enum EGONG_CONFIG_GUI_DEST{ + EGONG_CONFIG_GUI_DEST_NONE=0, + EGONG_CONFIG_GUI_DEST_WINDOW=(1<<0), + EGONG_CONFIG_GUI_DEST_NOTIFY=(1<<1), + EGONG_CONFIG_GUI_DEST_ALL=~0, +}; extern struct EGong_config_file_entry EGong_configuration_file_interface[EGONG_CONFIG_FILE_ENTRYCOUNT]; extern struct EGong_config EGong_global_configuration; diff --git a/include/Util/Config_Compiletime.h b/include/Util/Config_Compiletime.h @@ -1,4 +0,0 @@ -/* #undef USE_GTK */ -/* #undef USE_AO */ -/* #undef USE_WINGUI */ - diff --git a/include/Util/Config_Compiletime.h.in b/include/Util/Config_Compiletime.h.in @@ -1,4 +1,7 @@ +#pragma once #cmakedefine USE_GTK +#cmakedefine USE_LIBNOTIFY #cmakedefine USE_AO #cmakedefine USE_WINGUI +#define EGONG_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@" diff --git a/include/Util/Dependencies.h b/include/Util/Dependencies.h @@ -0,0 +1,17 @@ +#pragma once + +#define DEP_REQ(NAME, DEPS) ((NAME&(DEPS)&~EGong_dep_status)>0) +#define DEP_STOP(NAME, DEPS) ((NAME&(DEPS)&EGong_dep_status)>0) +#define DEP_AVAIL(DEPS) ((EGong_dep_status&DEPS)>0) + +enum EGONG_DEPENDENCIES{ + EGONG_DEP_NONE=(0), + EGONG_DEP_LISTENER=(1<<0), + EGONG_DEP_SOCKETS=(1<<1), + EGONG_DEP_ALL=(~0) +}; + +extern int EGong_deps_init(unsigned int dependencies); +extern int EGong_deps_deinit(unsigned int dependencies); + +extern unsigned int EGong_dep_status; diff --git a/include/Util/Misc.h b/include/Util/Misc.h @@ -18,3 +18,11 @@ struct EGong_static_array{ ssize_t element_count; ssize_t element_size; }; + +struct String{ + char *data; + size_t length; +}; +typedef struct String String; +#define STRING_STATIC(STRING, VALUE) STRING.data=VALUE; STRING.length=sizeof(VALUE); +#define STRING_STATIC_INIT(VALUE){.data=VALUE, .length=sizeof(VALUE)} diff --git a/include/Util/Socket.h b/include/Util/Socket.h @@ -3,7 +3,7 @@ #include <EGong/Util/Config.h> #ifdef _WIN32 #include <winsock2.h> - #define MSG_DONTWAIT 0 + #define MSG_DONTWAIT (1<<5) typedef short sa_family_t; #else #include <sys/socket.h> diff --git a/include/Util/Waiter.h b/include/Util/Waiter.h @@ -2,10 +2,10 @@ extern unsigned int EGong_waiter_highest_fd; extern int EGong_waiter_init(void); -extern int EGong_waiter_add(int sock, unsigned short int type); +extern int EGong_waiter_add_default(int sock, unsigned short int type); extern int EGong_waiter_del(int sock); extern int EGong_waiter_wait(void); - +extern int(*EGong_waiter_add)(int, unsigned short int); enum EGONG_WAITER_TYPE{ EGONG_WAITER_FD, diff --git a/src/CNC.c b/src/CNC.c @@ -6,56 +6,20 @@ #include <EGong/Util/Waiter.h> #include <string.h> #include <unistd.h> -#ifdef EGONG_USE_GTK +#ifdef USE_GTK #include <EGong/Interfaces/GTK.h> #endif - -unsigned int EGong_cnc_running=0; - -int EGong_cnc_init(unsigned int requirements){ - if((requirements&(EGONG_REQUIREMENT_SOCKETS|EGONG_REQUIREMENT_LISTENER)&~EGong_cnc_running)>0){ - if(EGong_sockets_setup()<0){ - do_log("Couldn't initialize sockets", LOG_TYPE_NORMAL, LOG_LEVEL_FATAL); - return -1; - } - else{ - EGong_cnc_running|=EGONG_REQUIREMENT_SOCKETS; - } - } - if((requirements&EGONG_REQUIREMENT_LISTENER&~EGong_cnc_running)>0){ - if(EGong_listener_init(NULL,NULL)<0){ - do_log("Couldn't initialize listener", LOG_TYPE_NORMAL, LOG_LEVEL_FATAL); - return -1; - } - else{ - EGong_waiter_add(EGong_listen_sock, EGONG_WAITER_SOCKET); - EGong_cnc_running|=EGONG_REQUIREMENT_LISTENER; - } - } - #ifdef EGONG_USE_GTK - if((requirements&EGONG_REQUIREMENT_GTK&~EGong_cnc_running)>0){ - if(EGong_if_gtk_int_setup(EGONG_IF_GTK_INIT_ROOT)<0){ - do_log("Couldn't initialize GTK", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); - return -2; - } - else{ - EGong_cnc_running|=EGONG_REQUIREMENT_GTK; - } - } - #endif - return 0; -} -int EGong_cnc_sendmessage_broad(const char *msg){ +int EGong_cnc_sendmessage_broad(const String *msg){ return EGong_cnc_sendmessage(msg, NULL); } -int EGong_cnc_sendmessage(const char *msg, const char *dest){ +int EGong_cnc_sendmessage(const String *msg, const char *dest){ if(dest==NULL){ dest="255.255.255.255"; } struct EGong_packet packet; - EGong_generate_packet(&packet, msg, strlen(msg)); + EGong_generate_packet(&packet, msg); if(EGong_send_packet(&packet, dest)<0){ do_log("Couldn't send packet.", LOG_TYPE_NORMAL, LOG_LEVEL_WARNING); } @@ -65,14 +29,15 @@ int EGong_cnc_sendmessage(const char *msg, const char *dest){ return 0; } -int EGong_cnc_getmessage(char **msg){ +int EGong_cnc_getmessage(String *msg){ struct EGong_packet packet; int ret=EGong_get_packet(NULL, &packet); if(ret!=0){ return ret; } if(EGong_packet_verify(&packet, NULL)){ - *msg=packet.message.data; + msg->data=packet.message.data; + msg->length=packet.message.length; } else{ EGong_packet_free(&packet); @@ -81,15 +46,9 @@ int EGong_cnc_getmessage(char **msg){ } return ret; } -void EGong_cnc_freemessage(char *msg){ +void EGong_cnc_freemessage(String *msg){ struct EGong_packet virtpack; - virtpack.message.data=msg; + virtpack.message.data=msg->data; EGong_packet_free(&virtpack); } -void EGong_cnc_deinit(void){ - if((EGong_cnc_running&EGONG_REQUIREMENT_LISTENER)>0){ - EGong_listener_close(NULL); - EGong_sockets_shutdown(); - } -} diff --git a/src/EGong.c b/src/EGong.c @@ -1,32 +1,64 @@ -#include <EGong/Util/Log.h> -#include <EGong/Util/Misc.h> -#include <EGong/Util/Config.h> -#include <EGong/Interfaces.h> -#include <EGong/Util/Waiter.h> -#include <EGong/CNC.h> -#include <EGong/Packet.h> +#include <EGong/Main.h> +#include <EGong/Interfaces/CMD.h> +#include <EGong/Interfaces/GUI.h> +#include <EGong/Util/Config_Compiletime.h> +#ifdef USE_WINGUI +#define WIN32_LEAN_AND_MEAN +#define UNICODE +#include <windows.h> +#include <wchar.h> #include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <unistd.h> -int main(int argc, char **argv){ +#include <EGong/Util/Array.h> +#include <EGong/Util/Log.h> +#include <EGong/Interfaces/Windows.h> +int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR argv, int commands){ + EGong_if_win_instance=instance; - EGong_config_init(NULL); + do_log("Simulating argc and argv", LOG_TYPE_NORMAL, LOG_LEVEL_INFO); + LPTSTR cmdlineW=GetCommandLine(); + size_t length=wcslen(cmdlineW)+1; + char *cmdline=calloc(length, sizeof(char)); + memset(cmdline, '\0', length*sizeof(char)); + wcstombs(cmdline, cmdlineW, length); + struct Array argva; + Array_init(&argva, sizeof(char *), 5); + unsigned int i=0; + unsigned short int blind=0; + char *charptr; + while(i<length){ + charptr=&cmdline[i]; + if(i==0||(*charptr==' '&&*(charptr-sizeof(char))!='\\'&&!blind)){ + if(i>0){ + *charptr='\0'; + i++; + charptr=&cmdline[i]; + } + Array_add(&argva, &charptr); + } + if((*charptr=='"'||*charptr=='\'')&&*(charptr-sizeof(char))!='\\'){ + blind=!blind; + } + if(cmdline[i]=='\0'){ + break; + } + i++; + } + EGong_global_argc=argva.element_count; + EGong_global_argv=argva.memory.data; +#else +int main(int argc, char **argv){ EGong_global_argc=argc; EGong_global_argv=argv; - if(EGong_waiter_init()<0){ - return -1; +#endif + if(EGong_main_init()<0){ + return 0; } - - if(EGong_interface_init(0)<0){ - return -1; - } - - while(EGong_interface_cycle()==0){ - EGong_waiter_wait(); - } - - EGong_cnc_deinit(); + EGong_main_loop(); + EGong_main_deinit(); + #ifdef USE_WINGUI + Array_destroy(&argva); + free(cmdline); + #endif return 0; } diff --git a/src/Interfaces.c b/src/Interfaces.c @@ -1,6 +1,9 @@ #include <EGong/CNC.h> +#include <EGong/Util/Dependencies.h> #include <EGong/Interfaces/STDIO.h> #include <EGong/Interfaces/CMD.h> +#include <EGong/Util/Waiter.h> +#include <EGong/Main.h> #include <EGong/Util/Config.h> #ifdef USE_GTK #include <EGong/Interfaces/GTK.h> @@ -11,6 +14,9 @@ #ifdef USE_WINGUI #include <EGong/Interfaces/Windows.h> #endif +#if defined(USE_GTK) || defined(USE_WINGUI) + #include <EGong/Interfaces/GUI.h> +#endif #include <EGong/Util/Log.h> #include <EGong/Util/Misc.h> #include <stdlib.h> @@ -19,57 +25,61 @@ struct EGong_interface EGong_interfaces[]={ { .name="CMD", .identifier='C', - .requirements=EGONG_REQUIREMENT_NONE, + .requirements=EGONG_DEP_NONE, .state=EGONG_INTERFACE_ACTIVE, - .setup=&EGong_if_cmd_setup, - .cycle=&EGong_if_cmd_cycle, - .display_message=NULL, - .shutdown=NULL + .funcs=&(struct EGong_if_ptrtbl){ + .setup=&EGong_if_cmd_setup, + .cycle=&EGong_if_cmd_cycle, + .display=NULL, + .shutdown=NULL, + .sock_watch=NULL, + .loop=NULL, + } }, + #if defined(USE_GTK) || defined(USE_WINGUI) { - .name="STDIO", - .identifier='S', - .requirements=EGONG_REQUIREMENT_LISTENER|EGONG_REQUIREMENT_TERMINAL, + .name="GUI", + .identifier='G', + .requirements=EGONG_DEP_LISTENER, .state=0, - .setup=&EGong_if_stdio_setup, - .cycle=&EGong_if_stdio_cycle, - .display_message=&EGong_if_stdio_display, - .shutdown=NULL + .funcs=&(struct EGong_if_ptrtbl){ + .setup=&EGong_if_gui_setup, + .cycle=&EGong_if_gui_cycle, + .display=&EGong_if_gui_display, + .shutdown=&EGong_if_gui_shutdown, + .sock_watch=&EGong_if_gui_sockwatch, + .loop=&EGong_if_gui_loop, + } }, - #ifdef USE_GTK + #endif { - .name="GTK", - .identifier='G', - .requirements=EGONG_REQUIREMENT_LISTENER|EGONG_REQUIREMENT_GTK, + .name="STDIO", + .identifier='S', + .requirements=EGONG_DEP_LISTENER, .state=0, - .setup=&EGong_if_gtk_setup, - .cycle=&EGong_if_gtk_cycle, - .display_message=&EGong_if_gtk_display, - .shutdown=&EGong_if_gtk_shutdown + .funcs=&(struct EGong_if_ptrtbl){ + .setup=&EGong_if_stdio_setup, + .cycle=&EGong_if_stdio_cycle, + .display=&EGong_if_stdio_display, + .shutdown=NULL, + .sock_watch=NULL, + .loop=NULL, + } }, - #endif #ifdef USE_AO { .name="Audio", .identifier='A', - .requirements=EGONG_REQUIREMENT_LISTENER, - .state=0, - .setup=&EGong_if_audio_setup, - .cycle=NULL, - .display_message=&EGong_if_audio_display, - .shutdown=&EGong_if_audio_shutdown - } - #endif - #ifdef USE_WINGUI - { - .name="WinGUI", - .identifier='W', - .requirements=EGONG_REQUIREMENT_LISTENER, + .requirements=EGONG_DEP_LISTENER, .state=0, - .setup=&EGong_if_win_setup, - .cycle=NULL, - .display_message=NULL, - .shutdown=NULL + .funcs=&(struct EGong_if_ptrtbl){ + .setup=&EGong_if_audio_setup, + .cycle=NULL, + .display=&EGong_if_audio_display, + .shutdown=&EGong_if_audio_shutdown + .sock_watch=NULL, + .loop=NULL, + } } #endif }; @@ -80,40 +90,42 @@ unsigned int EGong_interfaces_requirement_mask=0; unsigned short int EGong_interface_if_count_ustream(struct EGong_interface *interface){ unsigned short int streams=0; - if(interface->display_message!=NULL){ + if(interface->funcs->display!=NULL){ streams++; } - if(interface->cycle!=NULL){ + if(interface->funcs->cycle!=NULL){ streams++; } return streams; } int EGong_interface_setup(struct EGong_interface *interface){ - if((interface->requirements&EGong_interfaces_requirement_mask)>0){ - do_log_call_composite(LOG_COMPOSE_SRC, LOG_TYPE_NORMAL, LOG_LEVEL_ERROR, EGong_global_configuration.log.destinations, "Couldn't setup interface ", interface->name, " due to unmet dependencies", NULL); + + if(!IF_CAN_SETUP(*interface)||!IF_ACTIVE(*interface)){ + return EGONG_INTERFACE_RETURN_OK; } - else{ - if(EGong_cnc_init(interface->requirements&(~EGong_interfaces_requirements))<0){ - do_log("Couldn't get requirements", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); - return EGONG_INTERFACE_RETURN_ERROR; - } - else{ - EGong_interfaces_requirements|=interface->requirements; - } + if(interface->funcs->sock_watch!=NULL){ + EGong_waiter_add=interface->funcs->sock_watch; + } + if(interface->funcs->loop!=NULL){ + Egong_main_loop_ptr=interface->funcs->loop; } - if(interface->setup!=NULL&&interface->setup(interface)<0){ + if(interface->funcs->setup(interface)<0){ do_log_call_composite(LOG_COMPOSE_SRC, LOG_TYPE_NORMAL, LOG_LEVEL_ERROR, EGong_global_configuration.log.destinations, "Couldn't setup interface ", interface->name, NULL); + interface->state&=~(EGONG_INTERFACE_ACTIVE|EGONG_INTERFACE_SETUP); + return EGONG_INTERFACE_RETURN_ERROR; + } + if(EGong_deps_init(interface->requirements)>0){ + do_log_call_composite(LOG_COMPOSE_SRC, LOG_TYPE_NORMAL, LOG_LEVEL_ERROR, EGong_global_configuration.log.destinations, "Couldn't setup interface ", interface->name, " due to unmet dependencies", NULL); + interface->state&=~(EGONG_INTERFACE_ACTIVE|EGONG_INTERFACE_SETUP); return EGONG_INTERFACE_RETURN_ERROR; } interface->state|=EGONG_INTERFACE_SETUP; EGong_interfaces_userstreams+=EGong_interface_if_count_ustream(interface); - return 0; + return EGONG_INTERFACE_RETURN_OK; } int EGong_interface_activate(struct EGong_interface *interface){ - if((interface->state&EGONG_INTERFACE_SETUP)==0&&EGong_interfaces_global_init_done==1){ - if(EGong_interface_setup(interface)<0){ - return -1; - } + if(EGong_interfaces_global_init_done==1&&!IF_TRY_SETUP(*interface)){ + return -1; } if((interface->state&EGONG_INTERFACE_ACTIVE)>0){ return 1; @@ -127,17 +139,17 @@ int EGong_interface_shutdown(struct EGong_interface *interface){ return 1; } int ret=0; - if(interface->shutdown(interface)<0){ + if(interface->funcs->shutdown(interface)<0){ do_log_call_composite(LOG_COMPOSE_SRC, LOG_TYPE_NORMAL, LOG_LEVEL_ERROR, EGong_global_configuration.log.destinations, "Couldn't shutdown interface ", interface->name, NULL); - ret=-1; + ret=EGONG_INTERFACE_RETURN_ERROR; } interface->state&=~EGONG_INTERFACE_SETUP; EGong_interface_deactivate(interface); return ret; } int EGong_interface_deactivate(struct EGong_interface *interface){ - if((interface->state&EGONG_INTERFACE_ACTIVE)==0){ - return 1; + if(!IF_ACTIVE(*interface)){ + return EGONG_INTERFACE_RETURN_OK; } interface->state&=~EGONG_INTERFACE_ACTIVE; EGong_interfaces_userstreams-=EGong_interface_if_count_ustream(interface); @@ -152,41 +164,13 @@ struct EGong_interface *EGong_interface_get_from_id(char identifier){ } return NULL; } -int EGong_interface_interpret_ret(int ret){ - switch(ret){ - case EGONG_INTERFACE_RETURN_FATAL: - do_log("Couldn't run interface function, exiting", LOG_TYPE_NORMAL, LOG_LEVEL_FATAL); - case EGONG_INTERFACE_RETURN_ERROR: - do_log("Couldn't run interface function, skipping", LOG_TYPE_NORMAL, LOG_LEVEL_WARNING); - break; - case EGONG_INTERFACE_RETURN_EXIT: - do_log("Interface function requested exit", LOG_TYPE_NORMAL, LOG_LEVEL_INFO); - break; - case EGONG_INTERFACE_RETURN_BREAK: - do_log("Interface function requested queueabortion", LOG_TYPE_NORMAL, LOG_LEVEL_INFO); - break; - } - return ret; -} int EGong_interface_init(unsigned int requirement_mask){ + do_log("Initializing interfaces", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); EGong_interfaces_requirement_mask=requirement_mask; int i, ret; for(i=0; i<CSIZEOF(EGong_interfaces); i++){ - if((EGong_interfaces[i].state&(EGONG_INTERFACE_ACTIVE))>0&&EGong_interfaces[i].setup!=NULL){ - ret=EGong_interface_interpret_ret(EGong_interface_setup(&EGong_interfaces[i])); - if(ret>EGONG_INTERFACE_RETURN_OK){ - EGong_interfaces[i].state&=~(EGONG_INTERFACE_ACTIVE|EGONG_INTERFACE_SETUP); - } - if(ret==EGONG_INTERFACE_RETURN_FATAL){ - return -1; - } - else if(ret==EGONG_INTERFACE_RETURN_EXIT){ - return 1; - } - else if(ret==EGONG_INTERFACE_RETURN_BREAK){ - break; - } - } + ret=EGong_interface_setup(&EGong_interfaces[i]); + EGONG_INTERFACE_INTERPRET_RET(ret, EGong_interfaces[i]); } if(EGong_interfaces_userstreams==0){ do_log("No userstreams available", LOG_TYPE_NORMAL, LOG_LEVEL_FATAL); @@ -202,62 +186,42 @@ int EGong_interface_cycle(void){ return 1; } int i, ret; - char* msg; + String msg; char *dest; + do_log("Checking for new input", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); for(i=0; i<CSIZEOF(EGong_interfaces); i++){ - if((EGong_interfaces[i].state&EGONG_INTERFACE_ACTIVE)>0&&EGong_interfaces[i].cycle!=NULL){ - msg=dest=NULL; - ret=EGong_interface_interpret_ret(EGong_interfaces[i].cycle(&EGong_interfaces[i], &msg, &dest)); - if(ret==EGONG_INTERFACE_RETURN_FATAL){ - return -1; - } - else if(ret==EGONG_INTERFACE_RETURN_EXIT){ - return 1; - } - else if(ret==EGONG_INTERFACE_RETURN_BREAK){ - break; - } - else if(msg!=NULL){ - EGong_cnc_sendmessage(msg, NULL); - free(msg); + if(IF_ACTIVE(EGong_interfaces[i]) && IF_CAN_CYCLE(EGong_interfaces[i])){ + msg.data=dest=NULL; msg.length=0; + ret=EGong_interfaces[i].funcs->cycle(&EGong_interfaces[i], &msg, &dest); + EGONG_INTERFACE_INTERPRET_RET(ret, EGong_interfaces[i]); + if(msg.data!=NULL){ + EGong_cnc_sendmessage(&msg, dest); + free(msg.data); } } } - msg=NULL; - if(((EGong_interfaces_requirements&EGONG_REQUIREMENT_LISTENER)>0)&&EGong_cnc_getmessage(&msg)==0){ + do_log("Checking for new message", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + msg.data=NULL; msg.length=0; + if(DEP_AVAIL(EGONG_DEP_LISTENER)&&EGong_cnc_getmessage(&msg)==0){ for(i=0; i<CSIZEOF(EGong_interfaces); i++){ - if((EGong_interfaces[i].state&EGONG_INTERFACE_ACTIVE)>0&&EGong_interfaces[i].display_message!=NULL){ - ret=EGong_interface_interpret_ret(EGong_interfaces[i].display_message(&EGong_interfaces[i],msg)); - if(ret==EGONG_INTERFACE_RETURN_FATAL){ - return -1; - } - else if(ret==EGONG_INTERFACE_RETURN_EXIT){ - return 1; - } - else if(ret==EGONG_INTERFACE_RETURN_BREAK){ - break; - } + if(IF_ACTIVE(EGong_interfaces[i])&&IF_CAN_DISPLAY(EGong_interfaces[i])){ + ret=EGong_interfaces[i].funcs->display(&EGong_interfaces[i],&msg); + EGONG_INTERFACE_INTERPRET_RET(ret, EGong_interfaces[i]); } } } - if(msg!=NULL){ - EGong_cnc_freemessage(msg); + if(msg.data!=NULL){ + EGong_cnc_freemessage(&msg); } return 0; } -void EGong_interface_deinit(void){ - EGong_cnc_deinit(); +int EGong_interface_deinit(void){ int i, ret; for(i=0; i<sizeof(EGong_interfaces)/sizeof(*EGong_interfaces); i++){ - if((EGong_interfaces[i].state&EGONG_INTERFACE_SETUP)>0&&EGong_interfaces[i].shutdown!=NULL){ - ret=EGong_interface_interpret_ret(EGong_interface_shutdown(&EGong_interfaces[i])); - if(ret==EGONG_INTERFACE_RETURN_EXIT){ - return; - } - else if(ret==EGONG_INTERFACE_RETURN_BREAK){ - break; - } + if(IF_SETUP(EGong_interfaces[i])&&IF_CAN_SHUTDOWN(EGong_interfaces[i])){ + ret=EGong_interface_shutdown(&EGong_interfaces[i]); + EGONG_INTERFACE_INTERPRET_RET(ret, EGong_interfaces[i]); } } } diff --git a/src/Interfaces/Audio.c b/src/Interfaces/Audio.c @@ -48,7 +48,7 @@ int EGong_if_audio_setup(struct EGong_interface *interface){ } return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_audio_display(struct EGong_interface *interface, const char *msg){ +int EGong_if_audio_display(struct EGong_interface *interface, const String *msg){ do_log("Playing Audio", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); ao_play(EGong_if_audio_device, EGong_if_audio_buffer, BUFFERSIZE); diff --git a/src/Interfaces/CMD.c b/src/Interfaces/CMD.c @@ -3,15 +3,13 @@ #include <EGong/Interfaces.h> #include <EGong/Util/Log.h> #include <EGong/Util/Misc.h> +#include <EGong/Util/Dependencies.h> #include <EGong/Util/Command.h> #include <EGong/Util/Config.h> #include <stddef.h> #include <stdint.h> -#ifdef USE_GTK - #include <EGong/Interfaces/GTK/NewMessage.h> -#endif -#ifdef USE_WINGUI - #include <EGong/Interfaces/Windows.h> +#if defined(USE_GTK) || defined(USE_WINGUI) + #include <EGong/Interfaces/GUI.h> #endif #ifdef _WIN32 #include <stdio.h> @@ -70,26 +68,14 @@ struct EGong_command_if_cmd EGong_if_cmd_commands[]={ }, .execute=EGONG_IF_CMD_CYCLE }, - #ifdef USE_GTK - { - .command={ - .longname="gtk-message", - .shortname="g", - .description="Opens the GTK-Message dialog", - .type={.type=EGONG_COMMAND_FUNC_VOID, .args=0}, - .pointer=&EGong_if_cmd_gtk_msg - }, - .execute=EGONG_IF_CMD_CYCLE - }, - #endif - #ifdef USE_WINGUI + #if defined(USE_GTK) || defined(USE_WINGUI) { .command={ .longname="windows-message", .shortname="w", .description="Opens the Windows-Message dialog", .type={.type=EGONG_COMMAND_FUNC_VOID, .args=0}, - .pointer=&EGong_if_cmd_windows_msg + .pointer=&EGong_if_cmd_gui_msg }, .execute=EGONG_IF_CMD_CYCLE }, @@ -101,24 +87,16 @@ struct EGong_command_array EGong_if_cmd_commandarray={.array={ .element_count=CSIZEOF(EGong_if_cmd_commands), }}; -#ifdef USE_GTK -int EGong_if_cmd_gtk_msg(void){ - EGong_cnc_init(EGONG_REQUIREMENT_GTK); - EGong_if_gtk_newmsg_display_single(); - gtk_main(); - return EGONG_INTERFACE_RETURN_OK; -} -#endif -#ifdef USE_WINGUI -int EGong_if_cmd_windows_msg(void){ - EGong_cnc_init(EGONG_REQUIREMENT_SOCKETS); - EGong_if_win_getmsgdialog(); +#if defined(USE_GTK) || defined(USE_WINGUI) +int EGong_if_cmd_gui_msg(void){ + do_log("Stub", LOG_TYPE_NORMAL, LOG_LEVEL_WARNING); return EGONG_INTERFACE_RETURN_OK; } #endif int EGong_if_cmd_send_message(char *msg){ - EGong_cnc_init(EGONG_REQUIREMENT_SOCKETS); - EGong_cnc_sendmessage_broad(msg); + EGong_deps_init(EGONG_DEP_SOCKETS); + String mess={.data=msg, .length=strlen(msg)}; + EGong_cnc_sendmessage_broad(&mess); return EGONG_INTERFACE_RETURN_OK; } int EGong_if_cmd_help(void){ @@ -145,7 +123,7 @@ struct EGong_command_if_cmd *EGong_if_cmd_get_from_char(const char *commandline) while(*++valptr=='-'); return (struct EGong_command_if_cmd *)EGong_command_match(&EGong_if_cmd_commandarray,valptr,EGONG_COMMAND_MATCH_ANY); } -int EGong_if_cmd_exec(unsigned int execution, struct EGong_interface *interface, char **msg, char **dest){ +int EGong_if_cmd_exec(unsigned int execution, struct EGong_interface *interface, String *msg, char **dest){ int i; char *arg; struct EGong_command_if_cmd *command=NULL; @@ -169,7 +147,7 @@ int EGong_if_cmd_setup(struct EGong_interface *interface){ return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_cmd_cycle(struct EGong_interface *interface, char **msg, char **dest){ +int EGong_if_cmd_cycle(struct EGong_interface *interface, String *msg, char **dest){ EGong_if_cmd_exec(EGONG_IF_CMD_CYCLE, interface, NULL, NULL); EGong_interface_deactivate(interface); return EGONG_INTERFACE_RETURN_OK; diff --git a/src/Interfaces/GTK.c b/src/Interfaces/GTK.c @@ -1,53 +1,89 @@ -#include <EGong/Interfaces/GTK/TrayIcon.h> -#include <EGong/Interfaces/GTK/Message.h> #include <EGong/Interfaces/GTK.h> #include <EGong/Interfaces.h> #include <EGong/Util/Misc.h> #include <EGong/Util/Log.h> +#include <EGong/Util/Waiter.h> +#include <EGong/Main.h> #include <EGong/Interfaces.h> +#include <EGong/Interfaces/GUI.h> #include <gtk/gtk.h> +#include <EGong/Util/Config_Compiletime.h> +#include <EGong/Util/Config.h> +#ifdef USE_LIBNOTIFY + #include <libnotify/notify.h> +#endif -GtkWidget *Egong_if_gtk_root; +GtkWidget *Egong_if_gtk_root=NULL; +GdkPixbuf *EGong_if_gtk_icon=NULL; +unsigned short int EGong_if_gtk_have_libnotify=0; unsigned int EGong_if_gtk_initialized; -int EGong_if_gtk_int_setup(unsigned int what){ +struct EGong_if_ptrtbl EGong_if_gtk_ptrtbl={ + .setup=&EGong_if_gtk_setup, + .cycle=&EGong_if_gtk_cycle, + .display=&EGong_if_gtk_display, + .shutdown=&EGong_if_gtk_shutdown, + .sock_watch=&EGong_gtk_waiter_add, + .loop=&EGong_if_gtk_main +}; +int EGong_if_gtk_main(void){ + gtk_main(); + return 1; +} +int EGong_if_gtk_setup(struct EGong_interface *interface){ gtk_init(&EGong_global_argc, &EGong_global_argv); - if((what&EGONG_IF_GTK_INIT_ROOT&~EGong_if_gtk_initialized)>0){ - Egong_if_gtk_root=gtk_window_new(GTK_WINDOW_TOPLEVEL); - if(Egong_if_gtk_root!=NULL){ - EGong_if_gtk_initialized|=EGONG_IF_GTK_INIT_ROOT; - } - else{ - do_log("Couldn't initialize rootwindow", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); - return -1; - } + #ifdef USE_LIBNOTIFY + if(!notify_init("EGong")){ + do_log("Couldn't setup libnotify", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); } - if((what&EGONG_IF_GTK_INIT_TRAY&~EGong_if_gtk_initialized)>0){ - if(EGong_if_gtk_tray_setup()<0){ - do_log("Couldn't initialize tray", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); - return -2; - } - else{ - EGong_if_gtk_initialized|=EGONG_IF_GTK_INIT_TRAY; - } + else{ + EGong_if_gtk_have_libnotify=1; } - return 0; -} -int EGong_if_gtk_setup(struct EGong_interface *interface){ - if(EGong_if_gtk_int_setup(EGONG_IF_GTK_INIT_ALL)<0){ + #endif + GError *err=NULL; + EGong_if_gtk_icon=gdk_pixbuf_new_from_file(EGONG_INSTALL_PREFIX"/share/EGong.ico", &err); + if(EGong_if_gtk_icon==NULL){ + do_log("Couldn't open iconfile", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); return EGONG_INTERFACE_RETURN_ERROR; } - return 0; + return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_gtk_cycle(struct EGong_interface *interface, char **msg, char **dest){ - interface->cycle=NULL; //Prevent any further execution +int EGong_if_gtk_cycle(struct EGong_interface *interface, String *msg, char **dest){ + return EGONG_INTERFACE_RETURN_OK; + interface->funcs->cycle=NULL; //Prevent any further execution EGong_interfaces_userstreams--; //GTK takes over the job of cycling the interfaces. gtk_main(); return EGONG_INTERFACE_RETURN_EXIT; } -int EGong_if_gtk_display(struct EGong_interface *interface, const char *msg){ - EGong_if_gtk_msg_display(msg); //Shouldn't acutally be used anyway... +int EGong_if_gtk_display_window(struct EGong_interface *interface, const String *msg){ + do_log("Displaying message in window", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + gtk_dialog_new_with_buttons(msg->data, GTK_WINDOW(Egong_if_gtk_root), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK); +} +int EGong_if_gtk_display_notify(struct EGong_interface *interface, const String *msg){ + do_log("Displaying message with libnotify", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + #ifdef USE_LIBNOTIFY + if(EGong_if_gtk_have_libnotify==0){ + do_log("Libnotify not initialized", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + } + NotifyNotification *notify=notify_notification_new("Egong Nachricht", msg->data, NULL); + notify_notification_set_image_from_pixbuf(notify, EGong_if_gtk_icon); + GError *err=NULL; + if(!notify_notification_show(notify, &err)){ + do_log("Couldn't display notification", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + } + #else + do_log("Libnotify not compiled in...", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + #endif +} +int EGong_if_gtk_display(struct EGong_interface *interface, const String *msg){ + do_log("Displaying message", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_NOTIFY)>0){ + EGong_if_gtk_display_notify(interface, msg); + } + if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_WINDOW)>0){ + EGong_if_gtk_display_window(interface, msg); + } return EGONG_INTERFACE_RETURN_OK; } @@ -55,3 +91,187 @@ int EGong_if_gtk_shutdown(struct EGong_interface *interface){ gtk_main_quit(); return EGONG_INTERFACE_RETURN_OK; } +void EGong_if_gtk_tray_popup(GtkStatusIcon *icon, guint button, guint activation_time, gpointer data){ + gtk_menu_popup(GTK_MENU(data),NULL,NULL,gtk_status_icon_position_menu, icon, button, activation_time); +} +void EGong_if_gtk_widget_toggle(GtkWidget *caller){ + if(gtk_widget_get_visible(caller)){ + gtk_widget_hide_all(caller); + } + else{ + gtk_widget_show_all(caller); + } +} +void EGong_if_gtk_show_element(struct EGong_GUI_item *itm){ + gtk_widget_show(GTK_WIDGET(itm->itemptr)); +} +GtkWidget *EGong_if_gtk_create_gui(struct EGong_GUI_item *parent, struct EGong_GUI_item *this){ + unsigned int i; + GtkWidget *element=NULL; + GtkWidget *submenu; + struct EGong_GUI_item **children=this->child; + char *eventdefault; + switch(this->type){ + case EGONG_GUI_WINDOW: + element=gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_signal_connect_swapped(element, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), (gpointer)element); + if(this->text!=NULL){ + gtk_window_set_title(GTK_WINDOW(element),this->text); + } + gtk_window_set_icon(GTK_WINDOW(element), EGong_if_gtk_icon); + eventdefault="activate-focus"; + break; + case EGONG_GUI_TEXT: + element=gtk_entry_new(); + if(this->text!=NULL){ + gtk_entry_set_text(GTK_ENTRY(element),this->text); + } + eventdefault="activate"; + break; + case EGONG_GUI_BUTTON: + element=(this->text!=NULL) ? gtk_button_new_with_label(this->text) : gtk_button_new(); + eventdefault="clicked"; + break; + case EGONG_GUI_LABEL: + element=gtk_label_new(this->text); + break; + case EGONG_GUI_MENU: + submenu=element=gtk_menu_new(); + break; + case EGONG_GUI_HBOX: + element=gtk_hbox_new(TRUE, 1); + break; + case EGONG_GUI_VBOX: + element=gtk_vbox_new(TRUE, 1); + break; + case EGONG_GUI_MENUITEM_IMAGE: + case EGONG_GUI_MENUITEM: + + if(this->type==EGONG_GUI_MENUITEM_IMAGE){ + gchar *stockid; + switch((unsigned int)this->extra){ + case EGUI_MIMG_EXIT: + stockid=GTK_STOCK_QUIT; + break; + } + element=gtk_image_menu_item_new_with_label(this->text); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(element),gtk_image_new_from_icon_name((const gchar *)stockid,GTK_ICON_SIZE_MENU)); + } + else{ + element=gtk_menu_item_new_with_label(this->text); + } + if(this->child!=NULL){ //Menuitem has submenus + struct EGong_GUI_item subm={ + .type=EGONG_GUI_MENU, .text=NULL, .tooltip=NULL, .child=this->child + }; + submenu=EGong_if_gtk_create_gui(this, &subm); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(element), submenu); + children=NULL; //Children have been processed + } + eventdefault="activate"; + break; + case EGONG_GUI_SYSTRAY: + element=(GtkWidget *)gtk_status_icon_new_from_pixbuf(EGong_if_gtk_icon); + eventdefault="activate"; + break; + default: + do_log("Unknown GUI-Type specified", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return NULL; + } + if(element==NULL){ + do_log("Couldn't initialize element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return NULL; + } + if(this->tooltip!=NULL){ + if(this->type==EGONG_GUI_SYSTRAY) gtk_status_icon_set_tooltip(GTK_STATUS_ICON(element),this->tooltip); + else gtk_widget_set_tooltip_text(element,this->tooltip); + } + if(this->events!=NULL){ + struct EGong_GUI_event *ev; + for(i=0;this->events[i]!=NULL; i++){ + ev=this->events[i]; + g_signal_connect_swapped(element, eventdefault, G_CALLBACK(EGong_GUI_event_callback), (gpointer)ev); + } + } + if(children!=NULL){ + GtkWidget *child_widget; + for(i=0;children[i]!=NULL; i++){ + child_widget=EGong_if_gtk_create_gui(this, children[i]); + if(child_widget!=NULL){ + if(children[i]->type==EGONG_GUI_WINDOW){ + if(this->type==EGONG_GUI_SYSTRAY){ + g_signal_connect_swapped(GTK_STATUS_ICON(element), "activate", G_CALLBACK(EGong_if_gtk_widget_toggle), child_widget); + } + else{ + g_signal_connect_swapped(GTK_STATUS_ICON(element), "activate", G_CALLBACK(gtk_widget_show_all), child_widget); + } + } + else{ + switch(this->type){ + case EGONG_GUI_MENU: + case EGONG_GUI_MENUITEM: + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), child_widget); + break; + case EGONG_GUI_HBOX: + case EGONG_GUI_VBOX: + gtk_box_pack_start(GTK_BOX(element), child_widget, TRUE, TRUE, 1); + break; + case EGONG_GUI_SYSTRAY: + if(children[i]->type==EGONG_GUI_MENU){ + g_signal_connect(GTK_STATUS_ICON(element), "popup-menu", G_CALLBACK(EGong_if_gtk_tray_popup), child_widget); + } + else{ + do_log("Unknown mapping from systray", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + gtk_widget_destroy(GTK_WIDGET(child_widget)); + } + break; + default: + do_log("Assigning default", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + gtk_container_add(GTK_CONTAINER(element), child_widget); + break; + } + gtk_widget_show(child_widget); + } + } + else{ + do_log("Couldn't initialize child Element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + } + } + } + if(parent==NULL&&Egong_if_gtk_root==NULL){ + Egong_if_gtk_root=element; + } + this->itemptr=(void *)element; + return element; +} +void *EGong_gtk_get_item_value(struct EGong_GUI_item *itm){ + void *ret=NULL; + switch(itm->type){ + case EGONG_GUI_TEXT: + ret=(void *)gtk_entry_get_text(itm->itemptr); + break; + case EGONG_GUI_WINDOW: + ret=(void *)itm->itemptr; + break; + default: + do_log("Event datasource specified where no data can be obtained", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + break; + } + return ret; +} +void EGong_if_gtk_free_item_value(struct EGong_GUI_item *itm, void *element){ + return; +} +gboolean Egong_waiter_gtk_callback(GIOChannel *source, GIOCondition condition, gpointer data){ + do_log("Trigger", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + if(EGong_interface_cycle()!=0){ + EGong_if_gtk_shutdown(NULL); + } + return G_SOURCE_CONTINUE; +} +int EGong_gtk_waiter_add(int sock, unsigned short int type){ + do_log("Adding sockwatch", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + GIOChannel *new=g_io_channel_unix_new(sock); + g_io_add_watch(new,G_IO_IN|G_IO_ERR|G_IO_HUP, Egong_waiter_gtk_callback, NULL); + return 0; +} diff --git a/src/Interfaces/GTK/Message.c b/src/Interfaces/GTK/Message.c @@ -1,19 +0,0 @@ -#include <EGong/Interfaces/GTK/Message.h> -#include <EGong/Interfaces/GTK.h> -#include <gtk/gtk.h> - -void EGong_if_gtk_msg_display(const char *msg){ - GtkWidget *dialog = gtk_dialog_new_with_buttons("Nachricht", - GTK_WINDOW(Egong_if_gtk_root), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, - GTK_RESPONSE_OK, - NULL); - GtkWidget *Message; - GtkWidget *content_area=gtk_dialog_get_content_area(GTK_DIALOG (dialog)); - Message=gtk_label_new(msg); - gtk_container_add (GTK_CONTAINER (content_area), Message); - g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), (gpointer)dialog); - - gtk_widget_show_all(dialog); -} diff --git a/src/Interfaces/GTK/NewMessage.c b/src/Interfaces/GTK/NewMessage.c @@ -1,47 +0,0 @@ -#include <gtk/gtk.h> -#include <EGong/Util/Log.h> -#include <EGong/Interfaces/GTK/NewMessage.h> -#include <EGong/Interfaces/GTK/TrayIcon.h> -#include <EGong/Interfaces/GTK.h> -GtkWidget *EGong_if_gtk_newmsg_dialog; -void EGong_if_gtk_newmsg_send_callback(GtkDialog *caller, guint button, gpointer data){ - if(button==GTK_RESPONSE_OK){ - char *message=(char *)gtk_entry_get_text((GtkEntry *)data); - if(message[0]!='\0'){ - EGong_cnc_sendmessage(message,NULL); - } - } - EGong_if_gtk_newmsg_dialog=NULL; - gtk_widget_destroy(GTK_WIDGET(caller)); -} - -void EGong_if_gtk_newmsg_display_construct(unsigned short int single){ - if(EGong_if_gtk_newmsg_dialog==NULL){ - EGong_if_gtk_newmsg_dialog = gtk_dialog_new_with_buttons("Nachricht senden", - GTK_WINDOW(Egong_if_gtk_root), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, - GTK_RESPONSE_OK, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - NULL); - GtkWidget *Message; - GtkWidget *content_area=gtk_dialog_get_content_area(GTK_DIALOG (EGong_if_gtk_newmsg_dialog)); - Message=gtk_entry_new(); - gtk_container_add (GTK_CONTAINER (content_area), Message); - if(single==1){ - g_signal_connect(EGong_if_gtk_newmsg_dialog, "response", G_CALLBACK (gtk_main_quit), NULL); - } - g_signal_connect(EGong_if_gtk_newmsg_dialog, "response", G_CALLBACK (EGong_if_gtk_newmsg_send_callback), (gpointer)Message); - - } - gtk_widget_show_all(EGong_if_gtk_newmsg_dialog); - -} -void EGong_if_gtk_newmsg_display_single(void){ - EGong_if_gtk_newmsg_display_construct(1); -} -void EGong_if_gtk_newmsg_display(void){ - EGong_if_gtk_newmsg_display_construct(0); -} - diff --git a/src/Interfaces/GTK/TrayIcon.c b/src/Interfaces/GTK/TrayIcon.c @@ -1,51 +0,0 @@ -#include <gtk/gtk.h> -#include <EGong/Interfaces/GTK/TrayIcon.h> -#include <EGong/Interfaces/GTK/NewMessage.h> -#include <EGong/Util/Log.h> -#include <EGong/Util/Misc.h> -#include <EGong/CNC.h> - -GtkStatusIcon *EGong_if_gtk_tray_root; -GtkWidget *EGong_if_gtk_tray_menu; - -struct EGong_if_gtk_tray_menu_call EGong_if_gtk_tray_menu_calls[]={ - {.name="Essen", .tooltip="Zum Essen rufen", .message="Essen!"}, -}; - -void EGong_if_gtk_tray_popup(GtkStatusIcon *icon, guint button, guint activation_time, gpointer data){ - gtk_menu_popup(GTK_MENU(EGong_if_gtk_tray_menu),NULL,NULL,gtk_status_icon_position_menu, icon, button, activation_time); -} -void EGong_if_gtk_tray_predef_call(GtkMenuItem *icon, const char *message){ - EGong_cnc_sendmessage_broad(message); -} -int EGong_if_gtk_tray_setup(){ - EGong_if_gtk_tray_root=gtk_status_icon_new_from_stock(GTK_STOCK_NETWORK); - g_signal_connect(GTK_STATUS_ICON(EGong_if_gtk_tray_root), "activate", G_CALLBACK(EGong_if_gtk_newmsg_display), NULL); - g_signal_connect(GTK_STATUS_ICON(EGong_if_gtk_tray_root), "popup-menu", G_CALLBACK(EGong_if_gtk_tray_popup), NULL); - - EGong_if_gtk_tray_menu=gtk_menu_new(); - - GtkWidget *Exit=gtk_image_menu_item_new_with_label("Exit"); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(Exit),gtk_image_new_from_icon_name(GTK_STOCK_QUIT,GTK_ICON_SIZE_MENU)); - g_signal_connect(G_OBJECT(Exit), "activate", G_CALLBACK(gtk_main_quit), NULL); - gtk_menu_shell_append(GTK_MENU_SHELL(EGong_if_gtk_tray_menu), Exit); - - GtkWidget *predef=gtk_menu_item_new_with_label("Rufen"); - GtkWidget *predefM=gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(predef), predefM); - gtk_menu_shell_prepend(GTK_MENU_SHELL(EGong_if_gtk_tray_menu), predef); - int i; - GtkWidget *callitem; - struct EGong_if_gtk_tray_menu_call *call; - for(i=0; i<CSIZEOF(EGong_if_gtk_tray_menu_calls); i++){ - call=&EGong_if_gtk_tray_menu_calls[i]; - callitem=gtk_menu_item_new_with_label(call->name); - gtk_widget_set_tooltip_text(callitem,call->tooltip); - g_signal_connect(G_OBJECT(callitem), "activate", G_CALLBACK(EGong_if_gtk_tray_predef_call), call->message); - gtk_menu_shell_prepend(GTK_MENU_SHELL(predefM), callitem); - } - - gtk_widget_show_all(EGong_if_gtk_tray_menu); - do_log("Tray initialized", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); - return 0; -} diff --git a/src/Interfaces/GUI.c b/src/Interfaces/GUI.c @@ -0,0 +1,167 @@ +#include <EGong/Interfaces/GUI.h> +#include <EGong/Util/Config_Compiletime.h> +#ifdef USE_GTK + #include <EGong/Interfaces/GTK.h> +#endif +#ifdef USE_WINGUI + #include <EGong/Interfaces/Windows.h> + #include <winuser.h> +#endif +#include <EGong/Util/Log.h> +#include <stdlib.h> + + +struct EGong_GUI_item EGong_GUI_systray_sendmsgfield={.type=EGONG_GUI_TEXT, .extra=(void *)20, .text=NULL, .tooltip=GUIT("Nachricht eingeben"), .child=NULL}; +struct EGong_GUI_item EGong_GUI_newmessage={.type=EGONG_GUI_WINDOW, .extra=(void *)10, .text=GUIT("Nachricht senden"), .tooltip=NULL, .child=EGUI_ARR{ + EGUI_EL{.type=EGONG_GUI_HBOX, .extra=(void *)15, .text=NULL, .tooltip=NULL, .child=EGUI_ARR{ + EGUI_ELX(EGong_GUI_systray_sendmsgfield), + EGUI_EL{.type=EGONG_GUI_BUTTON, .text=GUIT("Senden"), .tooltip=GUIT("Nachricht Senden"), .child=NULL, .events=EEV_ARR{ + EEV_EL{.command={.type={.type=EGONG_COMMAND_FUNC_STRING, .args=1}, .pointer=&EGong_cnc_sendmessage_broad}, .sources=EES_ARR{ + EES_EL{.type=EGONG_GUI_EVSRC_ELEMENT, .data=&EGong_GUI_systray_sendmsgfield}, + EES_FIN + }}, + EEV_EL{.command={.type={.type=EGONG_COMMAND_FUNC_POINTER, .args=1}, .pointer=&EGong_GUI_event_hide}, .sources=EES_ARR{ + EES_EL{.type=EGONG_GUI_EVSRC_ELEMENT, .data=&EGong_GUI_newmessage}, + EES_FIN + }}, + EEV_FIN + }}, + EGUI_FIN + }}, + EGUI_FIN + }}; +struct EGong_GUI_item EGong_GUI_systray={ + .type=EGONG_GUI_SYSTRAY, .text=NULL, .tooltip=NULL, .child=EGUI_ARR{ + EGUI_EL{.type=EGONG_GUI_MENU, .text=NULL, .tooltip=NULL, .child=EGUI_ARR{ + EGUI_EL{.type=EGONG_GUI_MENUITEM, .text=GUIT("Rufen"), .tooltip=GUIT("Vordefinierte Ruffunktionen"), .child=EGUI_ARR{ + EGUI_EL{.type=EGONG_GUI_MENUITEM, .text=GUIT("Essen"), .tooltip=GUIT("Zum Essen rufen"), .child=NULL, .events=EEV_ARR{ + EEV_EL{.command={.type={.type=EGONG_COMMAND_FUNC_STRING, .args=1}, .pointer=&EGong_cnc_sendmessage_broad}, .sources=EES_ARR{ + EES_EL{.type=EGONG_GUI_EVSRC_STATIC, .data="Essen"}, + EES_FIN + }}, + EEV_FIN + }}, + EGUI_FIN, + }}, + EGUI_EL{.type=EGONG_GUI_MENUITEM_IMAGE, .extra=(void *)EGUI_MIMG_EXIT, .text=GUIT("Exit"), .tooltip=GUIT("Programm beenden"), .child=NULL, .events=EEV_ARR{ + EEV_EL{.command={.type={.type=EGONG_COMMAND_FUNC_VOID, .args=0}, .pointer=EGong_if_gui_shutdown}}, + EEV_FIN + }}, + EGUI_FIN, + }}, + EGUI_ELX(EGong_GUI_newmessage), + EGUI_FIN, + } +}; +char *EGong_GUI_item_names[]={ + [EGONG_GUI_BUTTON]="Button", + [EGONG_GUI_DIALOG]="Dialog", + [EGONG_GUI_HBOX]="HBox", + [EGONG_GUI_MENU]="Menu", + [EGONG_GUI_MENUITEM]="Menuitem", + [EGONG_GUI_MENUITEM_IMAGE]="Menuitem Image", + [EGONG_GUI_MENUITEM_SEPARATOR]="Menuitem Separator", + [EGONG_GUI_SYSTRAY]="Systray", + [EGONG_GUI_TEXT]="Text", + [EGONG_GUI_WINDOW]="Window" +}; +#ifdef USE_GTK +struct EGong_if_gui_ptrtbl EGong_if_gui_pointers={ + .ifptrtbl=&EGong_if_gtk_ptrtbl, + .create=(void *(*)(struct EGong_GUI_item *, struct EGong_GUI_item *))&EGong_if_gtk_create_gui, + .get_value=&EGong_gtk_get_item_value, + .show=&EGong_if_gtk_show_element, + .free_value=&EGong_if_gtk_free_item_value +}; +#endif +#ifdef USE_WINGUI +struct EGong_if_gui_ptrtbl EGong_if_gui_pointers={ + .ifptrtbl=&EGong_if_win_ptrtbl, + .create=(void *(*)(struct EGong_GUI_item *, struct EGong_GUI_item *))&EGong_if_win_create_wrapper, + .get_value=&EGong_if_win_get_item_value, + .show=&EGong_if_win_show_element, + .free_value=&EGong_if_win_free_item_value +}; +#endif +void *EGong_GUI_create(struct EGong_GUI_item *gui){ + void *newgui=EGong_if_gui_pointers.create(NULL, gui); + return newgui; +} +void EGong_GUI_event_hide(void *gui_element){ + #ifdef USE_GTK + if(EGong_GUI_type==EGONG_GUI_TYPE_GTK){ + gtk_widget_hide_on_delete(gui_element); + } + #endif + #ifdef USE_WINGUI + if(EGong_GUI_type==EGONG_GUI_TYPE_WINGUI){ + ShowWindow(gui_element, SW_HIDE); + } + #endif +} +void EGong_GUI_event_callback(struct EGong_GUI_event *event){ + void *args[event->command.type.args]; + + unsigned int i; + do_log("Constructing argarray", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + for(i=0;i<event->command.type.args;i++){ + if(event->sources[i]->type==EGONG_GUI_EVSRC_ELEMENT){ + args[i]=EGong_if_gui_pointers.get_value(event->sources[i]->data); + } + else if(event->sources[i]->type==EGONG_GUI_EVSRC_STATIC){ + args[i]=event->sources[i]->data; + } + } + do_log("Trying to execute command", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + EGong_command_exec(&event->command, args); + + for(i=0;i<event->command.type.args;i++){ + if(event->sources[i]->type==EGONG_GUI_EVSRC_ELEMENT){ + EGong_if_gui_pointers.free_value(event->sources[i]->data, args[i]); + } + } +} + +int EGong_if_gui_setup(struct EGong_interface *interface){ + do_log("Setting up GUI", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + EGong_if_gui_pointers.ifptrtbl->setup(interface); + EGong_if_gui_pointers.create(NULL, &EGong_GUI_systray); + EGong_if_gui_pointers.show(&EGong_GUI_systray); + return EGONG_INTERFACE_RETURN_OK; +} +unsigned short int EGong_GUI_has_been_shutdown=0; +int EGong_if_gui_cmd(char *msg){ + if(EGong_GUI_has_been_shutdown==1){ + return EGONG_INTERFACE_RETURN_EXIT; + } + return EGong_if_gui_pointers.ifptrtbl->cmd(msg); +} + +int EGong_if_gui_cycle(struct EGong_interface *interface, String *msg, char **dest){ + if(EGong_GUI_has_been_shutdown==1){ + return EGONG_INTERFACE_RETURN_EXIT; + } + return EGong_if_gui_pointers.ifptrtbl->cycle(interface,msg,dest); +} + +int EGong_if_gui_display(struct EGong_interface *interface, const String *msg){ + if(EGong_GUI_has_been_shutdown==1){ + return EGONG_INTERFACE_RETURN_EXIT; + } + return EGong_if_gui_pointers.ifptrtbl->display(interface,msg); +} +int EGong_if_gui_sockwatch(int sock, unsigned short int type){ + do_log("Adding sockwatch", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + return EGong_if_gui_pointers.ifptrtbl->sock_watch(sock, type); +} +int EGong_if_gui_loop(void){ + return EGong_if_gui_pointers.ifptrtbl->loop(); +} +int EGong_if_gui_shutdown(struct EGong_interface *interface){ + if(EGong_GUI_has_been_shutdown==1){ + return EGONG_INTERFACE_RETURN_EXIT; + } + EGong_GUI_has_been_shutdown=1; + do_log("Shutting down GUI", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + return EGong_if_gui_pointers.ifptrtbl->shutdown(interface); +} diff --git a/src/Interfaces/STDIO.c b/src/Interfaces/STDIO.c @@ -46,7 +46,7 @@ int EGong_if_stdio_cmd(char *msg){ return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_stdio_cycle(struct EGong_interface *interface, char **msg, char **dest){ +int EGong_if_stdio_cycle(struct EGong_interface *interface, String *msg, char **dest){ char buffer[50]; int ret=read(STDIN_FILENO, buffer, 50); #ifdef _WIN32 @@ -62,15 +62,14 @@ int EGong_if_stdio_cycle(struct EGong_interface *interface, char **msg, char **d EGong_if_stdio_cmd(&buffer[1]); } else{ - buffer[ret]='\0'; - *msg=malloc(ret); - strncpy(*msg,buffer, ret); + msg->data=malloc(ret); + strncpy(msg->data, buffer, ret); } } return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_stdio_display(struct EGong_interface *interface, const char *msg){ - write(STDOUT_FILENO,msg,strlen(msg)); +int EGong_if_stdio_display(struct EGong_interface *interface, const String *msg){ + write(STDOUT_FILENO,msg->data,msg->length); write(STDOUT_FILENO, "\n", sizeof("\n")); return EGONG_INTERFACE_RETURN_OK; } diff --git a/src/Interfaces/Windows.c b/src/Interfaces/Windows.c @@ -1,91 +1,577 @@ +#define WINVER 0x500 +#define _WIN32_IE WINVER +#define _WIN32_WINNT WINVER +#define NTDDI_VERSION NTDDI_VISTA +#define UNICODE +#define WIN32_LEAN_AND_MEAN +#include <EGong/Util/Config_Compiletime.h> +#include <EGong/Util/Config.h> #include <EGong/Interfaces.h> +#include <EGong/Util/Array.h> #include <EGong/Interfaces/Windows.h> +#include <EGong/Util/Waiter.h> +#include <winsock2.h> +#include <EGong/Interfaces/GUI.h> +#include <EGong/Main.h> #include <EGong/CNC.h> #include <EGong/Util/Log.h> -#define UNICODE -#define WIN32_LEAN_AND_MEAN #include <windows.h> - +#include <windowsx.h> +#include <shellapi.h> +#include <stdlib.h> +struct EGong_if_ptrtbl EGong_if_win_ptrtbl={ + .setup=&EGong_if_win_setup, + .cycle=&EGong_if_win_cycle, + .display=&EGong_if_win_display, + .shutdown=&EGong_if_win_shutdown, + .sock_watch=&EGong_if_win_waiter_add, + .loop=&EGong_if_win_loop +}; +extern struct EGong_GUI_item EGong_if_win_messagegui; +struct EGong_GUI_item EGong_if_win_messagegui_button={.type=EGONG_GUI_BUTTON, .text=GUIT("OK"), .tooltip=NULL, .child=NULL, .events=EEV_ARR{ + EEV_EL{.command={.type={.type=EGONG_COMMAND_FUNC_VOID, .args=1}, .pointer=&EGong_if_win_destroy}, .sources=EES_ARR{ + EES_EL{.type=EGONG_GUI_EVSRC_ELEMENT, .data=&EGong_if_win_messagegui}, + EES_FIN + }}, + EEV_FIN +}}; +struct EGong_GUI_item EGong_if_win_messagegui_text={.type=EGONG_GUI_LABEL, .text=GUIT(""), .tooltip=NULL, .child=NULL}; +struct EGong_GUI_item EGong_if_win_messagegui={.type=EGONG_GUI_WINDOW, .extra=(void *)10, .text=GUIT("EGong Nachricht"), .tooltip=NULL, .child=EGUI_ARR{ + EGUI_EL{.type=EGONG_GUI_VBOX, .extra=(void *)10, .text=NULL, .tooltip=NULL, .child=EGUI_ARR{ + EGUI_ELX(EGong_if_win_messagegui_text), + EGUI_ELX(EGong_if_win_messagegui_button), + EGUI_FIN + }}, + EGUI_FIN +}}; WNDCLASSW EGong_if_win_getmsg = {0}; -HWND EGong_if_win_getmsg_editfield; -LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ - HWND hwndButton; - (void) hwndButton; - switch(msg){ - case WM_CREATE: - - EGong_if_win_getmsg_editfield = CreateWindowW(L"Edit", NULL, - WS_CHILD | WS_VISIBLE | WS_BORDER, - 50, 50, 150, 20, hwnd, (HMENU) 0, - NULL, NULL); - - hwndButton = CreateWindowW(L"button", L"Senden", - WS_VISIBLE | WS_CHILD, 50, 100, 80, 25, - hwnd, (HMENU) 1, NULL, NULL); - +HWND EGong_if_win_root=NULL; +HINSTANCE EGong_if_win_instance=NULL; +struct EGong_GUI_item *EGong_if_win_global_systray=NULL; +struct Array EGong_if_win_menus; +struct Array EGong_if_win_windows; +HWND EGong_if_win_create_wrapper(struct EGong_GUI_item *parent, struct EGong_GUI_item *this){ + EGong_if_win_create(parent, this, 0); +} +RECT EGong_if_win_getsize(struct EGong_GUI_item *this, unsigned short int recurse){ + HDC hdc=GetDC(NULL); + RECT rect={0,0,0,0}; + RECT childr; + unsigned int i; + switch(this->type){ + case EGONG_GUI_WINDOW: + for(i=0; this->child[i]!=NULL&&recurse; i++){ + childr=EGong_if_win_getsize(this->child[i], recurse); + if(childr.right>rect.right){ + rect.right=childr.right; + } + if(childr.bottom>rect.bottom){ + rect.bottom=childr.bottom; + } + } + break; + case EGONG_GUI_TEXT: + DrawText(hdc, GUIT("M"), 1, &rect, DT_CALCRECT); + rect.right*=(unsigned int)this->extra; + rect.right+=5; + rect.bottom+=5; + break; + case EGONG_GUI_LABEL: + DrawText(hdc, this->text, 1, &rect, DT_CALCRECT); + break; + case EGONG_GUI_BUTTON: + DrawText(hdc, this->text, -1, &rect, DT_CALCRECT); + rect.right+=10; + rect.bottom+=10; + break; + case EGONG_GUI_HBOX: + for(i=0; this->child[i]!=NULL&&recurse; i++){ + childr=EGong_if_win_getsize(this->child[i], recurse); + rect.right+=childr.right+(unsigned int)this->extra; + if(childr.bottom>rect.bottom){ + rect.bottom=childr.bottom; + } + } + break; + case EGONG_GUI_VBOX: + for(i=0; this->child[i]!=NULL&&recurse; i++){ + childr=EGong_if_win_getsize(this->child[i], recurse); + rect.bottom+=childr.bottom+(unsigned int)this->extra; + if(childr.right>rect.right){ + rect.right=childr.right; + } + } + break; + default: + do_log("Item has no real size", LOG_TYPE_NORMAL, LOG_LEVEL_WARNING); + break; + } + return rect; +} +HWND EGong_if_win_create(struct EGong_GUI_item *parent, struct EGong_GUI_item *this, unsigned int child){ + HWND element=NULL; + HINSTANCE hInstance; + NOTIFYICONDATA *notify; + MENUITEMINFO *menu; + RECT dimensions, *parentd; + HDC hdc; + unsigned int i; + unsigned int tmp; + struct EGong_GUI_item **children=this->child; + if(parent!=this){ + if(this->type==EGONG_GUI_TEXT||this->type==EGONG_GUI_BUTTON||this->type==EGONG_GUI_HBOX||this->type==EGONG_GUI_VBOX||this->type==EGONG_GUI_LABEL){ + dimensions=EGong_if_win_getsize(this, 1); + if(parent->type==EGONG_GUI_HBOX||parent->type==EGONG_GUI_VBOX){ + parentd=parent->userdata; + dimensions.top=parentd->top; + dimensions.left=parentd->left; + if(parent->type==EGONG_GUI_HBOX){ + dimensions.top+=(parentd->bottom-dimensions.bottom)/2; + parentd->left+=dimensions.right+(unsigned int)parent->extra; + } + else{ + dimensions.left+=(parentd->right-dimensions.right)/2; + parentd->top+=dimensions.bottom+(unsigned int)parent->extra; + } + } + else if(parent->type==EGONG_GUI_WINDOW){ + dimensions.top=dimensions.left=(unsigned int)parent->extra; + } + } + switch(this->type){ + case EGONG_GUI_WINDOW: + hInstance=(HINSTANCE)GetWindowLong( GetForegroundWindow(), GWL_HINSTANCE ); + dimensions=EGong_if_win_getsize(this, 1); + element=CreateWindow(EGong_if_win_getmsg.lpszClassName, this->text, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, dimensions.right+(unsigned int)this->extra, dimensions.bottom+(unsigned int)this->extra, 0, 0, hInstance, 0); break; + case EGONG_GUI_TEXT: + element=CreateWindow(L"Edit", this->text, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, dimensions.left, dimensions.top, dimensions.right, dimensions.bottom, parent->itemptr, (HMENU) child, NULL, NULL); + break; + case EGONG_GUI_BUTTON: + element=CreateWindow(L"Button", this->text, WS_VISIBLE | WS_CHILD, dimensions.left, dimensions.top, dimensions.right, dimensions.bottom, parent->itemptr, (HMENU) child, NULL, NULL); + break; + case EGONG_GUI_MENUITEM: + case EGONG_GUI_MENUITEM_IMAGE: + case EGONG_GUI_MENUITEM_SEPARATOR: + tmp=MF_BYPOSITION; + if(this->type==EGONG_GUI_MENUITEM_SEPARATOR){ + tmp|=MF_SEPARATOR; + } + else{ + tmp|=MF_STRING; + } + if(children!=NULL){ + HMENU submenu=CreatePopupMenu(); + for(i=0; children[i]!=NULL; i++){ + if(children[i]->type==EGONG_GUI_MENUITEM || children[i]->type==EGONG_GUI_MENUITEM_IMAGE || children[i]->type==EGONG_GUI_MENUITEM_SEPARATOR){ + tmp|=MF_POPUP; + } + } + if((tmp&MF_POPUP)>0){ + this->userdata=submenu; + InsertMenu(parent->itemptr, -1, tmp, (UINT) submenu, this->text); + } + else{ + this->userdata=NULL; + DestroyMenu(submenu); + } + } + if((tmp&MF_POPUP)==0){ + if(parent->type==EGONG_GUI_MENUITEM||parent->type==EGONG_GUI_MENUITEM_IMAGE){ + InsertMenu(parent->userdata, -1, tmp, EGong_if_win_menus.element_count+1, this->text); + } + else{ + InsertMenu(parent->itemptr, -1, tmp, EGong_if_win_menus.element_count+1, this->text); + } + Array_add(&EGong_if_win_menus, &this); //Save menus for identification. + } + element=parent->itemptr; + break; + case EGONG_GUI_MENU: + element=(HWND)CreatePopupMenu(); + break; + case EGONG_GUI_LABEL: + element=CreateWindow(L"Static", this->text, WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, dimensions.left, dimensions.top, dimensions.right, dimensions.bottom, parent->itemptr, (HMENU) child, NULL, NULL); + + break; + case EGONG_GUI_HBOX: + case EGONG_GUI_VBOX: + this->userdata=malloc(sizeof(RECT)); + memcpy(this->userdata, &dimensions, sizeof(RECT)); + element=parent->itemptr; + break; + case EGONG_GUI_SYSTRAY: + hInstance=(HINSTANCE)GetWindowLong( GetForegroundWindow(), GWL_HINSTANCE ); + if(EGong_if_win_global_systray!=NULL){ + do_log("Already a systray icon defined!", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return NULL; + } + notify=malloc(sizeof(NOTIFYICONDATA)); + if(parent==NULL){ + //struct EGong_GUI_item virtual_parent={.type=EGONG_GUI_WINDOW, .text=NULL, .tooltip=NULL, .child=NULL}; + //notify->hWnd=EGong_if_win_create(NULL, &virtual_parent, 0); + if(EGong_if_win_root==NULL){ + notify->hWnd=CreateWindow(EGong_if_win_getmsg.lpszClassName, NULL, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0); + EGong_if_win_root=notify->hWnd; + } + else{ + notify->hWnd=EGong_if_win_root; + } + + } + else{ + notify->hWnd=parent->itemptr; + } + element=notify->hWnd; + notify->cbSize = sizeof(NOTIFYICONDATA); + + notify->uID=12+1; + notify->uFlags=NIF_ICON | NIF_MESSAGE; + notify->uCallbackMessage=WM_TRAY_ACTION; + //HMODULE hModule = GetModuleHandle(NULL); + notify->hIcon=LoadImage(GetModuleHandle(NULL), GUIT("Master_icon"), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + if(notify->hIcon==NULL){ + do_log("Couldn't load Icon", LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR); + } + + #if _WIN32_IE >= 0x0500 + notify->uVersion=NOTIFYICON_VERSION; + #endif + if(this->tooltip!=NULL){ + wcscpy(notify->szTip, this->tooltip); + notify->uFlags|=NIF_TIP; + } + Shell_NotifyIcon(NIM_ADD, notify); + #if _WIN32_IE >= 0x0500 + Shell_NotifyIcon(NIM_SETVERSION, notify); + #endif + this->userdata=notify; + EGong_if_win_global_systray=this; + break; + default: + do_log("Unknown GUI-Type specified", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return NULL; + } + } + else{ + element=this->itemptr; + } + if(element==NULL){ + do_log("Could not initialize GUI Element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return NULL; + } + if((parent!=NULL && parent->itemptr!=element) && !(this->type==EGONG_GUI_SYSTRAY || this->type==EGONG_GUI_MENU || this->type==EGONG_GUI_MENUITEM || this->type==EGONG_GUI_MENUITEM_SEPARATOR || this->type==EGONG_GUI_LABEL)){ //if parent->itemptr==element, the item does not exist. + if(SetWindowLongPtr(element, GWLP_USERDATA, (LONG_PTR)this)==(LONG_PTR)NULL&&GetLastError()!=0){ + do_log("Couldn't set userpointer", LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR); + } + } + if(parent==NULL && EGong_if_win_root==NULL){ + EGong_if_win_root=element; + } + this->itemptr=element; + if(parent==NULL){ + Array_add(&EGong_if_win_windows, &this); //Save rootwindows for destruction + } + if(children!=NULL){ + for(i=0; children[i]!=NULL; i++){ + EGong_if_win_create(this, children[i], i); + } + } + return element; +} +void EGong_if_win_show_element(struct EGong_GUI_item *itm){ + switch(itm->type){ + case EGONG_GUI_WINDOW: + case EGONG_GUI_MENU: + EGong_if_win_show_item((HWND) itm->itemptr); + break; + } +} + +void EGong_if_win_show_item(HWND item){ + ShowWindow(item, SW_SHOW); + SetForegroundWindow(item); +} + +void EGong_if_win_free_item_value(struct EGong_GUI_item *item, void *value){ + String *str; + switch(item->type){ + case EGONG_GUI_TEXT: + str=(String *)value; + free(str->data); + free(str); + break; + } +} +void *EGong_if_win_get_item_value(struct EGong_GUI_item *item){ + void *ret=NULL; + size_t len; + + switch(item->type){ + case EGONG_GUI_TEXT: + len=Edit_GetTextLength(item->itemptr)+1; + wchar_t *text=calloc(len, sizeof(wchar_t)); + char *msg=calloc(len, sizeof(char)); - case WM_COMMAND: - - if (HIWORD(wParam) == BN_CLICKED) { - int len = GetWindowTextLengthW(EGong_if_win_getmsg_editfield) + 1; - char text[len]; - char msg[len]; - - GetWindowTextW(EGong_if_win_getmsg_editfield, text, 5+len); - wcstombs(msg,text, len); + Edit_GetText(item->itemptr, text, len); + size_t bytes=wcstombs(msg, text, len); + if(bytes==-1){ + do_log("Couldn't convert widecharstring to multibytestring", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + free(text); + free(msg); + break; + } + msg[bytes]='\0'; + ret=(void *)msg; + free(text); + break; + case EGONG_GUI_WINDOW: + ret=(void *)item->itemptr; + break; + default: + do_log("Event datasource specified where no data can be obtained", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + break; + } + return ret; +} +void EGong_if_win_toggle_item(struct EGong_GUI_item *item){ + if(IsWindowVisible(item->itemptr)){ + ShowWindow(item->itemptr, SW_HIDE); + } + else{ + EGong_if_win_show_element(item); + } +} +void EGong_if_win_trayhandler(struct EGong_GUI_item *item, unsigned short int type, int x, int y, HWND hwnd){ + unsigned int i=0; + for(i=0; item->child[i]!=NULL; i++){ + if(item->child[i]->type==type){ + if(type==EGONG_GUI_MENU){ + SetForegroundWindow(EGong_if_win_root); + int rightaligned=(GetSystemMetrics(SM_MENUDROPALIGNMENT)==0) ? TPM_LEFTALIGN : TPM_RIGHTALIGN; + int menu=TrackPopupMenu(item->child[i]->itemptr, rightaligned | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, x, y, 0, hwnd, NULL); + if(menu==0){ + continue; + } + menu--; + struct EGong_GUI_item *win=*(struct EGong_GUI_item **)Array_get(&EGong_if_win_menus, menu); + EGong_if_win_actionhandler(win); + } + else{ + EGong_if_win_toggle_item(item->child[i]); + } + } + } +} +void EGong_if_win_actionhandler(struct EGong_GUI_item *item){ + if(item->events==NULL) + return; + do_log("We have action!1", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + unsigned int i=0; + for(i=0; item->events[i]!=NULL; i++){ + EGong_GUI_event_callback(item->events[i]); + } + +} + +LRESULT CALLBACK EGong_if_win_callback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ + struct EGong_GUI_item *win=NULL; + POINT pt; + switch(msg){ + case WM_COMMAND: + /* + if(isMenuItem){ + win=Array_get(&EGong_if_win_menus, LOWORD(wParam)); + } + else{ - msg[len]='\0'; - EGong_cnc_sendmessage_broad(msg); - PostQuitMessage(0); } - break; + */ + win=(struct EGong_GUI_item *)GetWindowLongPtr((HWND)lParam, GWLP_USERDATA); + if(win!=NULL){ + EGong_if_win_actionhandler(win); + } + break; - case WM_DESTROY: - PostQuitMessage(0); - break; + case WM_TRAY_ACTION: + switch(lParam){ + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + GetCursorPos(&pt); + if(lParam==WM_LBUTTONDOWN){ + EGong_if_win_trayhandler(EGong_if_win_global_systray, EGONG_GUI_WINDOW, pt.x, pt.y, hwnd); + } + else{ + EGong_if_win_trayhandler(EGong_if_win_global_systray, EGONG_GUI_MENU, pt.x, pt.y, hwnd); + } + break; + } + break; + case WM_CLOSE: + ShowWindow(hwnd, SW_HIDE); + return 0; + break; + case WM_DESTROY: + case WM_QUIT: + EGong_main_deinit(); + exit(LOWORD(wParam)); + break; } return DefWindowProcW(hwnd, msg, wParam, lParam); } -int EGong_if_win_getmsgdialog(){ + + +int EGong_if_win_setup(struct EGong_interface *interface){ + do_log("Initializing WinGUI", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + HINSTANCE hInstance = (HINSTANCE)GetWindowLong( GetForegroundWindow(), GWL_HINSTANCE ); - MSG msg; - EGong_if_win_getmsg.lpszClassName = L"EGong Message"; + EGong_if_win_getmsg.lpszClassName = L"EGong"; EGong_if_win_getmsg.hInstance = hInstance; EGong_if_win_getmsg.hbrBackground = GetSysColorBrush(COLOR_3DFACE); - EGong_if_win_getmsg.lpfnWndProc = WndProc; + EGong_if_win_getmsg.lpfnWndProc = EGong_if_win_callback; EGong_if_win_getmsg.hCursor = LoadCursor(0,IDC_ARROW); RegisterClassW(&EGong_if_win_getmsg); - CreateWindowW(EGong_if_win_getmsg.lpszClassName, L"EGong Message", - WS_OVERLAPPEDWINDOW | WS_VISIBLE, - 220, 220, 280, 200, 0, 0, hInstance, 0); - while(GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return 0; + Array_init(&EGong_if_win_menus, sizeof(struct EGong_GUI_item *), 0); + Array_init(&EGong_if_win_windows, sizeof(struct EGong_GUI_item *), 2); + + return EGONG_INTERFACE_RETURN_OK; } -void EGong_if_win_react(){ - do_log("Windowsinterface is a stub", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); +int EGong_if_win_cmd(char *msg){ + return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_win_setup(struct EGong_interface *interface){ - EGong_if_win_react(); - return EGONG_INTERFACE_RETURN_ERROR; + +int EGong_if_win_cycle(struct EGong_interface *interface, String *msg, char **dest){ + MSG loopmsg; + while(PeekMessage(&loopmsg, NULL, 0, 0, PM_REMOVE)!=0){ + TranslateMessage(&loopmsg); + DispatchMessage(&loopmsg); + } + return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_win_cmd(char *msg){ - EGong_if_win_react(); - return EGONG_INTERFACE_RETURN_ERROR; +int EGong_if_win_display_notify(struct EGong_interface *interface, const String *msg){ + NOTIFYICONDATA *nid=EGong_if_win_global_systray->userdata; + mbstowcs(nid->szInfo, msg->data, msg->length); + nid->szInfo[msg->length]='\0'; + nid->uFlags=NIF_INFO; + #if _WIN32_IE >= 0x0500 + nid->uTimeout=5000; + #endif + wcscpy(nid->szInfoTitle, L"EGong Nachricht"); + #if _WIN32_IE > 0x0500 + //nid->dwInfoFlags=NIIF_USER; + nid->dwInfoFlags=NIIF_NONE; + #else + nid->dwInfoFlags=NIIF_NONE; + #endif + + if(!Shell_NotifyIconW(NIM_MODIFY, nid)){ + do_log("Couldn't notify via Systray", LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR); + return EGONG_INTERFACE_RETURN_ERROR; + } + + return EGONG_INTERFACE_RETURN_OK; +} +int EGong_if_win_display_window(struct EGong_interface *interface, const String *msg){ + /*if((unsigned int)EGong_if_win_messagegui_text.extra==1){ + EGong_if_win_messagegui_text.text=realloc(EGong_if_win_messagegui_text.text, msg->length+1*sizeof(wchar_t)); + } + else{ + EGong_if_win_messagegui_text.text=calloc(msg->length+1, sizeof(wchar_t)); + EGong_if_win_messagegui_text.extra=(void *)(unsigned int)1; + } + mbstowcs(EGong_if_win_messagegui_text.text, msg->data, msg->length+1); + EGong_if_win_create(NULL, &EGong_if_win_messagegui, 0); + EGong_if_win_show_element(&EGong_if_win_messagegui);*/ + wchar_t msgw[msg->length+1]; + mbstowcs(msgw, msg->data, msg->length); + msgw[msg->length]='\0'; + MessageBox(NULL, msgw, GUIT("EGong Nachricht"), MB_OK); + return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_win_cycle(struct EGong_interface *interface, char **msg, char **dest){ - EGong_if_win_react(); - return EGONG_INTERFACE_RETURN_ERROR; +int EGong_if_win_display(struct EGong_interface *interface, const String *msg){ + if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_NOTIFY)>0){ + EGong_if_win_display_notify(interface, msg); + } + if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_WINDOW)>0){ + EGong_if_win_display_window(interface, msg); + } + return EGONG_INTERFACE_RETURN_OK; } -int EGong_if_win_display(struct EGong_interface *interface, const char *msg){ - EGong_if_win_react(); - return EGONG_INTERFACE_RETURN_ERROR; +void EGong_if_win_destroy(struct EGong_GUI_item *item){ + unsigned int i; + switch(item->type){ + case EGONG_GUI_WINDOW: + DestroyWindow(item->itemptr); + break; + case EGONG_GUI_LABEL: + if((unsigned int)item->extra==1){ + free(item->text); + } + break; + case EGONG_GUI_BUTTON: + break; + case EGONG_GUI_MENUITEM: + case EGONG_GUI_MENUITEM_IMAGE: + if(item->userdata!=NULL){ + DestroyMenu(item->userdata); + } + break; + case EGONG_GUI_MENUITEM_SEPARATOR: + break; + case EGONG_GUI_MENU: + DestroyMenu(item->itemptr); + break; + case EGONG_GUI_HBOX: + case EGONG_GUI_VBOX: + case EGONG_GUI_SYSTRAY: + free(item->userdata); + break; + } + + + if(item->child!=NULL){ + for(i=0; item->child[i]!=NULL; i++){ + EGong_if_win_destroy(item->child[i]); + } + } +} +int EGong_if_win_waiter_add(int sock, unsigned short int type){ + if(type==EGONG_WAITER_SOCKET){ + struct EGong_GUI_item *main=*(struct EGong_GUI_item **)Array_get(&EGong_if_win_windows,0); + WSAAsyncSelect(sock,(HWND)main->itemptr,WM_SOCKET,FD_ACCEPT|FD_READ); + } + else{ + do_log("Sorry, only sockets here...", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return -1; + } + return 0; +} +void EGong_if_win_destroy_wrapper(struct EGong_GUI_item **item){ + EGong_if_win_destroy(*item); +} +int EGong_if_win_shutdown(struct EGong_interface *interface){ + Array_foreach(&EGong_if_win_windows, (void(*)(void*))&EGong_if_win_destroy_wrapper); + Array_destroy(&EGong_if_win_menus); + Array_destroy(&EGong_if_win_windows); + + PostQuitMessage(0); + MSG msg; + while(GetMessage(&msg, NULL, 0, 0)!=0){ + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return EGONG_INTERFACE_RETURN_EXIT; +} +int EGong_if_win_loop(void){ + int ret; + while(WaitMessage()){ + if((ret=EGong_interface_cycle())!=EGONG_INTERFACE_RETURN_OK){ + return ret; + } + } } diff --git a/src/Interfaces/Windows.rc b/src/Interfaces/Windows.rc @@ -0,0 +1 @@ +Master_icon ICON "../../data/EGong.ico" diff --git a/src/Main.c b/src/Main.c @@ -0,0 +1,49 @@ +#include <EGong/Main.h> +#include <EGong/Interfaces.h> +#include <EGong/Util/Waiter.h> +#include <EGong/CNC.h> +#include <EGong/Util/Dependencies.h> +#include <EGong/Util/Misc.h> +#include <EGong/Util/Log.h> +#include <EGong/Util/Config.h> + +int(*Egong_main_loop_ptr)(void)=&EGong_main_loop_default; +int EGong_main_do(void){ + return EGong_interface_cycle(); +} +int EGong_main_init(void){ + EGong_config_init(NULL); + EGong_misc_rand_init(); + if(EGong_waiter_init()<0){ + return -1; + } + + if(EGong_interface_init(0)<0){ + return -1; + } + return 0; +} + +int EGong_main_loop(){ + return Egong_main_loop_ptr(); +} + +int EGong_main_loop_default(void){ + int ret; + EGong_main_do(); + do_log("Entering defaultloop", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + while(1){ + if(EGong_waiter_wait()!=0){ + return -1; + } + ret=EGong_main_do(); + if(ret!=0){ + return ret; + } + } + return 0; +} + +void EGong_main_deinit(void){ + EGong_deps_deinit(EGONG_DEP_ALL); +} diff --git a/src/Packet.c b/src/Packet.c @@ -30,11 +30,11 @@ int EGong_calculate_package_hash(struct EGong_packet *packet, unsigned char *des return 0; } -int EGong_generate_packet(struct EGong_packet *packet, const char *msg, unsigned int msg_length){ +int EGong_generate_packet(struct EGong_packet *packet, const String *msg){ EGong_misc_get_rand(packet->rand,EGONG_PACKET_RAND_LENGTH); - packet->message.length=msg_length; - packet->message.data=(char *)msg; + packet->message.length=msg->length; + packet->message.data=(char *)msg->data; EGong_calculate_package_hash(packet,packet->hash, NULL); @@ -122,10 +122,11 @@ void EGong_packetbuffer_to_packet(const char *buf, struct EGong_packet *packet){ packet->message.length=ntohs(*(uint16_t *)buf); buf+=EGONG_PACKET_LENGTH_LENGTH; packet->message.data=(char *)buf; + packet->message.data[packet->message.length]='\0'; } void EGong_drop_packet(SOCKET *sock){ do_log("Dropping packet.", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); - EGong_listener_get(sock,NULL,0, NULL, 0); + EGong_listener_get(sock,NULL,0, NULL, MSG_DONTWAIT); } int EGong_get_packet(SOCKET *sock, struct EGong_packet *packet){ if(sock==NULL){ @@ -149,7 +150,7 @@ int EGong_get_packet(SOCKET *sock, struct EGong_packet *packet){ uint16_t rawsize=*(uint16_t*)(packetbuf+EGONG_PACKET_RAND_LENGTH+EGONG_PACKET_HASH_LENGTH); size_t size=ntohs(rawsize); char *dest; - if(EGong_packetbuf_alloc(size+EGONG_PACKET_MSGHEADLEN,&dest, 1)<0){ + if(EGong_packetbuf_alloc(size+EGONG_PACKET_MSGHEADLEN+1,&dest, 1)<0){ do_log("Couldn't allocate packetbuffer",LOG_TYPE_NORMAL, LOG_LEVEL_WARNING); EGong_drop_packet(sock); return -2; diff --git a/src/Util/Command.c b/src/Util/Command.c @@ -5,6 +5,18 @@ #include <stdint.h> #include <stdio.h> +unsigned int EGong_command_argc(struct EGong_command *command){ + if(command->type.type>EGONG_COMMAND_ARG2){ + return 2; + } + else if(command->type.type>EGONG_COMMAND_ARG1){ + return 1; + } + else if(command->type.type>EGONG_COMMAND_ARG0){ + return 0; + } + return 0; +} struct EGong_command *EGong_command_match(struct EGong_command_array *commands, const char *data, unsigned int match_type){ unsigned int i; struct EGong_command *command=NULL; @@ -37,6 +49,7 @@ void EGong_command_print_help(struct EGong_command_array *commands, int destinat } } int EGong_command_exec(struct EGong_command *command, void **data){ + String str; switch(command->type.type){ case EGONG_COMMAND_BOOL_FALSE: *(unsigned int *)command->pointer=0; @@ -55,12 +68,26 @@ int EGong_command_exec(struct EGong_command *command, void **data){ if(*(unsigned int *)command->pointer>(unsigned int)0) (*(unsigned int *)command->pointer)--; break; + case EGONG_COMMAND_UINT_SET: + (*(unsigned int *)command->pointer)=*(unsigned int *)data; + break; case EGONG_COMMAND_FUNC_VOID: ((int(*)(void))command->pointer)(); break; + case EGONG_COMMAND_FUNC_UINT: + ((int(*)(unsigned int))command->pointer)(*(unsigned int*)data); + break; case EGONG_COMMAND_FUNC_CHAR: ((int(*)(char *))command->pointer)(*(char **)data); break; + case EGONG_COMMAND_FUNC_STRING: + str.data=*(char **)data; + str.length=strlen(str.data); + ((int(*)(String *))command->pointer)(&str); + break; + case EGONG_COMMAND_FUNC_POINTER: + ((void(*)(void *))command->pointer)(*(void **)data); + break; case EGONG_COMMAND_FUNC_2CHAR: ((int(*)(char *, char *))command->pointer)(((char **)data)[0],((char **)data)[1]); break; diff --git a/src/Util/Config.c b/src/Util/Config.c @@ -1,5 +1,6 @@ #include <EGong/Util/Config.h> #include <EGong/Util/Log.h> +#include <EGong/Util/Misc.h> #include <stdlib.h> struct EGong_config EGong_global_configuration; @@ -18,7 +19,7 @@ struct EGong_config_file_entry EGong_configuration_file_interface[EGONG_CONFIG_F [EGONG_CONFIG_FILE_LOG_DEST]={ .type=EGONG_CONFIG_TYPE_BITMASK, .name="Logdestinationsbitmaske", - .data_offset=offsetof(struct EGong_config,log.level) + .data_offset=offsetof(struct EGong_config,log.destinations) }, [EGONG_CONFIG_FILE_PACKET_COOKIE]={ .type=EGONG_CONFIG_TYPE_STRING, @@ -43,7 +44,7 @@ struct EGong_config_file_entry EGong_configuration_file_interface[EGONG_CONFIG_F }; void EGong_config_set_defaults(struct EGong_config *conf){ conf->log.color=0; - conf->log.level=LOG_LEVEL_DEBUG; + conf->log.level=LOG_LEVEL_INFO; conf->log.destinations=LOG_DEST_STDIO; conf->server.port=4242; @@ -51,11 +52,13 @@ void EGong_config_set_defaults(struct EGong_config *conf){ conf->packet.packet_maxlen=1000; conf->packet.cookie="Derpaherp"; + + conf->gui.destinations=EGONG_CONFIG_GUI_DEST_NOTIFY; } int EGong_config_write(struct EGong_config *conf, int file){ unsigned int i; - for(i=0;i<EGONG_CONFIG_FILE_ENTRYCOUNT; i++){ + for(i=0;i<CSIZEOF(EGong_configuration_file_interface); i++){ } return 0; diff --git a/src/Util/Dependencies.c b/src/Util/Dependencies.c @@ -0,0 +1,50 @@ +#include <EGong/Util/Dependencies.h> +#include <EGong/Util/Log.h> +#include <stdlib.h> +#include <EGong/Util/Socket.h> +#include <EGong/Util/Waiter.h> + +unsigned int EGong_dep_status=0; + + +int EGong_deps_init(unsigned int dependencies){ + if(DEP_REQ(dependencies, EGONG_DEP_SOCKETS)){ + do_log("Initializing sockets", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + if(EGong_sockets_setup()<0){ + do_log("Couldn't initialize sockets", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return -1; + } + else{ + EGong_dep_status|=EGONG_DEP_SOCKETS; + } + } + if(DEP_REQ(dependencies, EGONG_DEP_LISTENER)){ + do_log("Initializing Listener", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + if(EGong_deps_init(EGONG_DEP_SOCKETS)<0){ + return -1; + } + if(EGong_listener_init(NULL,NULL)<0){ + do_log("Couldn't initialize listener", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); + return -1; + } + else{ + EGong_waiter_add(EGong_listen_sock, EGONG_WAITER_SOCKET); + EGong_dep_status|=EGONG_DEP_LISTENER; + } + } + return 0; +} + +int EGong_deps_deinit(unsigned int dependencies){ + if(DEP_STOP(dependencies, EGONG_DEP_SOCKETS)){ + do_log("Deinitializing sockets", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + EGong_sockets_shutdown(); + EGong_dep_status&=~EGONG_DEP_SOCKETS; + dependencies|=EGONG_DEP_LISTENER; + } + if(DEP_STOP(dependencies, EGONG_DEP_LISTENER)){ + do_log("Deinitializing Listener", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); + EGong_listener_close(NULL); + EGong_dep_status&=~EGONG_DEP_LISTENER; + } +} diff --git a/src/Util/Log.c b/src/Util/Log.c @@ -85,28 +85,27 @@ void do_log_call(const struct log_source src, const char *msg, unsigned int msgl STRCAT(msgbuf,": "); STRNCAT(msgbuf, msg, msglength); - if(type==LOG_TYPE_SIGNAL){ - char *err=strerror(error); - STRCAT(msgbuf,"("); - STRNCAT(msgbuf, err,strlen(err)); - STRCAT(msgbuf,")"); - } #ifdef _WIN32 - else if(type==LOG_TYPE_SOCKET){ - STRCAT(msgbuf,"("); - LPVOID lpMsgBuf; - int e; - - lpMsgBuf = (LPVOID)"Unknown error"; - e = WSAGetLastError(); - if (FormatMessage( + if(type==LOG_TYPE_SIGNAL||type==LOG_TYPE_SOCKET){ + STRCAT(msgbuf,"("); + DWORD error; + if(type==LOG_TYPE_SIGNAL){ + error=GetLastError(); + } + else{ + error = WSAGetLastError(); + } + LPTSTR lpMsgBuf = (LPTSTR)"Unknown error"; + size_t ret=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, e, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, 0, NULL)) { - STRNCAT(msgbuf, lpMsgBuf,strlen(lpMsgBuf)); + (LPTSTR)&lpMsgBuf, 0, NULL); + if(ret){ + lpMsgBuf[ret-2]='\0'; + STRNCAT(msgbuf, lpMsgBuf,ret); LocalFree(lpMsgBuf); } else{ @@ -114,6 +113,13 @@ void do_log_call(const struct log_source src, const char *msg, unsigned int msgl } STRCAT(msgbuf,")"); } + #else + if(type==LOG_TYPE_SIGNAL){ + char *err=strerror(error); + STRCAT(msgbuf,"("); + STRNCAT(msgbuf, err,strlen(err)); + STRCAT(msgbuf,")"); + } #endif STRCAT(msgbuf,"\n\0"); length=(unsigned int)(msgbuf-msgptr); diff --git a/src/Util/Socket.c b/src/Util/Socket.c @@ -36,6 +36,7 @@ int inet_aton(const char *cp, struct in_addr *inp){ #endif int EGong_sockets_setup(void){ + do_log("Setting up sockets...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); #ifdef _WIN32 int res=WSAStartup(MAKEWORD(2,2), &wsaData); if(res!=0) { @@ -46,6 +47,7 @@ int EGong_sockets_setup(void){ return 0; } int EGong_sockets_shutdown(void){ + do_log("Shutting down sockets...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); #ifdef _WIN32 WSACleanup(); #endif @@ -60,9 +62,14 @@ void EGong_socket_close(SOCKET *sock){ #endif } int EGong_socket_open(SOCKET *sock){ + do_log("Opening UDP-Socket...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); *sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + #ifdef _WIN32 + if(*sock==INVALID_SOCKET){ + #else if(*sock<0){ - do_log("Couldn't initialize socket",LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR); + #endif + do_log("Couldn't initialize socket",LOG_TYPE_SOCKET, LOG_LEVEL_ERROR); EGong_socket_close(sock); return -1; } @@ -86,12 +93,14 @@ int EGong_listener_init(SOCKET *sock, struct EGong_config_server *config){ if(sock==NULL) sock=&EGong_listen_sock; + do_log("Initializing listener...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); if(EGong_socket_open(sock)<0){ do_log("Couldn't open socket",LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); return -1; } #ifdef _WIN32 unsigned long nonblocking_long=1; + do_log("Setting socket nonblocking...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); if (ioctlsocket(*sock, FIONBIO, &nonblocking_long)==SOCKET_ERROR){ do_log("Couldn't set listensocket nonblocking",LOG_TYPE_SIGNAL, LOG_LEVEL_ERROR); } @@ -101,7 +110,7 @@ int EGong_listener_init(SOCKET *sock, struct EGong_config_server *config){ EGong_socket_close(sock); return -2; } - + do_log("Binding socket...", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); if(bind(*sock, (struct sockaddr *) &listen_server, sizeof(listen_server))<0){ do_log("Couldn't bind to sock", LOG_TYPE_SOCKET, LOG_LEVEL_ERROR); EGong_socket_close(sock); @@ -120,13 +129,14 @@ int EGong_listener_get(SOCKET *sock, char *dest, int length, struct sockaddr *so source=&test; } do_log("Receiving on socket...",LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); - ret=recvfrom(*sock,dest,length, flags, source, &size); #ifdef _WIN32 - if((flags&MSG_PEEK)>0&&ret==-1&&WSAGetLastError()==WSAEMSGSIZE){ + ret=recvfrom(*sock,dest,length, flags&(~MSG_DONTWAIT), source, &size); + if((flags&MSG_PEEK)>0&&ret==SOCKET_ERROR&&WSAGetLastError()==WSAEMSGSIZE){ return length; } - else if((flags&MSG_DONTWAIT)>0&&ret==-1&&(WSAGetLastError()==WSAEWOULDBLOCK)) { + else if((flags&MSG_DONTWAIT)>0&&ret==SOCKET_ERROR&&(WSAGetLastError()==WSAEWOULDBLOCK)) { #else + ret=recvfrom(*sock,dest,length, flags, source, &size); if((flags&MSG_DONTWAIT)>0&&ret==-1&&(errno==EAGAIN||errno==EWOULDBLOCK)) { #endif return 0; diff --git a/src/Util/Waiter.c b/src/Util/Waiter.c @@ -8,16 +8,8 @@ #ifdef _WIN32 #include <winsock2.h> #endif -#ifdef USE_GTK - #include <gtk/gtk.h> - - gboolean Egong_waiter_gtk_callback(GIOChannel *source, GIOCondition condition, gpointer data){ - EGong_interface_cycle(); - return G_SOURCE_CONTINUE; - } -#endif - +int(*EGong_waiter_add)(int, unsigned short int)=&EGong_waiter_add_default; fd_set EGong_waiter_fds; unsigned int EGong_waiter_highest_fd; unsigned int EGong_waiter_cnt=0; @@ -25,7 +17,7 @@ int EGong_waiter_init(void){ FD_ZERO(&EGong_waiter_fds); return 0; } -int EGong_waiter_add(int sock, unsigned short int type){ +int EGong_waiter_add_default(int sock, unsigned short int type){ EGong_waiter_cnt++; #ifdef _WIN32 if(type==EGONG_WAITER_FD){ @@ -38,10 +30,6 @@ int EGong_waiter_add(int sock, unsigned short int type){ if(EGong_waiter_highest_fd<sock){ EGong_waiter_highest_fd=sock; } - #ifdef USE_GTK - GIOChannel *new=g_io_channel_unix_new(sock); - g_io_add_watch(new,G_IO_IN|G_IO_ERR|G_IO_HUP, Egong_waiter_gtk_callback, NULL); - #endif return 0; } int EGong_waiter_del(int sock){