"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libsn/sn-xmessages.c" between
xfe-1.42.tar.gz and xfe-1.43.tar.gz

About: Xfe (X File Explorer) is a file manager and browser (using the FOX toolkit).

sn-xmessages.c  (xfe-1.42):sn-xmessages.c  (xfe-1.43)
skipping to change at line 34 skipping to change at line 34
*/ */
#include <config.h> #include <config.h>
#include "sn-xmessages.h" #include "sn-xmessages.h"
#include "sn-list.h" #include "sn-list.h"
#include "sn-internals.h" #include "sn-internals.h"
typedef struct typedef struct
{ {
void *xid; void *xid;
Window root; xcb_window_t root;
Atom type_atom; xcb_atom_t type_atom;
Atom type_atom_begin; xcb_atom_t type_atom_begin;
char *message_type; char *message_type;
SnXmessageFunc func; SnXmessageFunc func;
void *func_data; void *func_data;
SnFreeFunc free_data_func; SnFreeFunc free_data_func;
} SnXmessageHandler; } SnXmessageHandler;
typedef struct typedef struct
{ {
Atom type_atom_begin; xcb_atom_t type_atom_begin;
Window xwindow; xcb_window_t xwindow;
char *message; char *message;
int allocated; int allocated;
} SnXmessage; } SnXmessage;
void void
sn_internal_add_xmessage_func (SnDisplay *display, sn_internal_add_xmessage_func (SnDisplay *display,
int screen, int screen,
const char *message_type, const char *message_type,
const char *message_type_begin, const char *message_type_begin,
SnXmessageFunc func, SnXmessageFunc func,
void *func_data, void *func_data,
SnFreeFunc free_data_func) SnFreeFunc free_data_func)
{ {
SnXmessageHandler *handler; SnXmessageHandler *handler;
SnList *xmessage_funcs; SnList *xmessage_funcs;
sn_internal_display_get_xmessage_data (display, &xmessage_funcs, xcb_connection_t *c = sn_display_get_x_connection(display);
NULL);
handler = sn_new0 (SnXmessageHandler, 1); /* Send atom requests ASAP */
xcb_intern_atom_cookie_t message_type_c =
xcb_intern_atom(c, FALSE, strlen(message_type), message_type);
xcb_intern_atom_cookie_t message_type_begin_c =
xcb_intern_atom(c, FALSE, strlen(message_type_begin), message_type_begin);
sn_internal_display_get_xmessage_data (display, &xmessage_funcs,
NULL);
handler = sn_new0 (SnXmessageHandler, 1);
handler->xid = sn_internal_display_get_id (display);
handler->root = sn_internal_display_get_root_window (display, screen);
handler->message_type = sn_internal_strdup (message_type);
handler->func = func;
handler->func_data = func_data;
handler->free_data_func = free_data_func;
xcb_intern_atom_reply_t *atom_reply;
atom_reply = xcb_intern_atom_reply(c, message_type_c, NULL);
handler->type_atom = atom_reply->atom;
free(atom_reply);
atom_reply = xcb_intern_atom_reply(c, message_type_begin_c, NULL);
handler->type_atom_begin = atom_reply->atom;
free(atom_reply);
handler->xid = sn_internal_display_get_id (display); sn_list_prepend (xmessage_funcs, handler);
handler->root = sn_internal_display_get_root_window (display, screen);
handler->type_atom = sn_internal_atom_get (display, message_type);
handler->type_atom_begin = sn_internal_atom_get (display, message_type_begin
);
handler->message_type = sn_internal_strdup (message_type);
handler->func = func;
handler->func_data = func_data;
handler->free_data_func = free_data_func;
sn_list_prepend (xmessage_funcs, handler);
} }
typedef struct typedef struct
{ {
const char *message_type; const char *message_type;
SnXmessageFunc func; SnXmessageFunc func;
void *func_data; void *func_data;
Window root; xcb_window_t root;
SnXmessageHandler *handler; SnXmessageHandler *handler;
} FindHandlerData; } FindHandlerData;
static sn_bool_t static sn_bool_t
find_handler_foreach (void *value, find_handler_foreach (void *value,
void *data) void *data)
{ {
FindHandlerData *fhd = data; FindHandlerData *fhd = data;
SnXmessageHandler *handler = value; SnXmessageHandler *handler = value;
if (handler->func == fhd->func && if (handler->func == fhd->func &&
handler->func_data == fhd->func_data && handler->func_data == fhd->func_data &&
handler->root == fhd->root && handler->root == fhd->root &&
strcmp (fhd->message_type, handler->message_type) == 0) strcmp (fhd->message_type, handler->message_type) == 0)
{ {
fhd->handler = handler; fhd->handler = handler;
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
void void
sn_internal_remove_xmessage_func (SnDisplay *display, sn_internal_remove_xmessage_func (SnDisplay *display,
int screen, int screen,
const char *message_type, const char *message_type,
SnXmessageFunc func, SnXmessageFunc func,
void *func_data) void *func_data)
{ {
FindHandlerData fhd; FindHandlerData fhd;
SnList *xmessage_funcs; SnList *xmessage_funcs;
sn_internal_display_get_xmessage_data (display, &xmessage_funcs, sn_internal_display_get_xmessage_data (display, &xmessage_funcs,
NULL); NULL);
fhd.message_type = message_type; fhd.message_type = message_type;
fhd.func = func; fhd.func = func;
fhd.func_data = func_data; fhd.func_data = func_data;
fhd.handler = NULL; fhd.handler = NULL;
fhd.root = sn_internal_display_get_root_window (display, screen); fhd.root = sn_internal_display_get_root_window (display, screen);
if (xmessage_funcs != NULL) if (xmessage_funcs != NULL)
sn_list_foreach (xmessage_funcs, find_handler_foreach, &fhd); sn_list_foreach (xmessage_funcs, find_handler_foreach, &fhd);
if (fhd.handler != NULL) if (fhd.handler != NULL)
{ {
sn_list_remove (xmessage_funcs, fhd.handler); sn_list_remove (xmessage_funcs, fhd.handler);
sn_free (fhd.handler->message_type); sn_free (fhd.handler->message_type);
if (fhd.handler->free_data_func) if (fhd.handler->free_data_func)
(* fhd.handler->free_data_func) (fhd.handler->func_data); (* fhd.handler->free_data_func) (fhd.handler->func_data);
sn_free (fhd.handler); sn_free (fhd.handler);
} }
} }
void void
sn_internal_broadcast_xmessage (SnDisplay *display, sn_internal_broadcast_xmessage (SnDisplay *display,
int screen, int screen,
const char *message_type, xcb_atom_t message_type,
const char *message_type_begin, xcb_atom_t message_type_begin,
const char *message) const char *message)
{ {
if (!sn_internal_utf8_validate (message, -1)) if (!sn_internal_utf8_validate (message, -1))
{ {
fprintf (stderr, fprintf (stderr,
"Attempted to send non-UTF-8 X message: %s\n", "Attempted to send non-UTF-8 X message: %s\n",
message); message);
return; return;
} }
switch (sn_internal_display_get_type (display)) xcb_connection_t *xconnection = sn_display_get_x_connection (display);
{
case SN_DISPLAY_TYPE_XLIB: uint32_t attrs[] = { 1, XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCT
{ URE_NOTIFY };
Atom type_atom; xcb_screen_t *s = sn_internal_display_get_x_screen (display, screen);
Atom type_atom_begin;
Window xwindow; xcb_window_t xwindow = xcb_generate_id(xconnection);
XSetWindowAttributes attrs; xcb_create_window(xconnection, s->root_depth, xwindow, s->root,
Display *xdisplay = sn_display_get_x_display (display); -100, -100, 1, 1, 0, XCB_COPY_FROM_PARENT, s->root_visual,
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
attrs.override_redirect = True; attrs);
attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
{
xwindow = xcb_client_message_event_t xevent;
XCreateWindow (xdisplay, const char *src;
RootWindow (xdisplay, 0), const char *src_end;
-100, -100, 1, 1, unsigned char *dest;
0, unsigned char *dest_end;
CopyFromParent,
CopyFromParent, xevent.response_type = XCB_CLIENT_MESSAGE;
CopyFromParent, xevent.window = xwindow;
CWOverrideRedirect | CWEventMask, xevent.format = 8;
&attrs); xevent.type = message_type_begin;
type_atom = sn_internal_atom_get (display, message_type);
type_atom_begin = sn_internal_atom_get (display, message_type_begin); src = message;
src_end = message + strlen (message) + 1; /* +1 to include nul byte */
{
XEvent xevent; while (src != src_end)
const char *src; {
const char *src_end; dest = &xevent.data.data8[0];
char *dest; dest_end = dest + 20;
char *dest_end;
while (dest != dest_end &&
xevent.xclient.type = ClientMessage; src != src_end)
xevent.xclient.message_type = type_atom_begin; {
xevent.xclient.display = xdisplay; *dest = *src;
xevent.xclient.window = xwindow; ++dest;
xevent.xclient.format = 8; ++src;
}
src = message;
src_end = message + strlen (message) + 1; /* +1 to include nul byte xcb_send_event (xconnection, 0, s->root, XCB_EVENT_MASK_PROPERTY_CHANG
*/ E,
(char *) &xevent);
while (src != src_end)
{ xevent.type = message_type;
dest = &xevent.xclient.data.b[0]; }
dest_end = dest + 20; }
while (dest != dest_end &&
src != src_end)
{
*dest = *src;
++dest;
++src;
}
XSendEvent (xdisplay,
RootWindow (xdisplay, screen),
False,
PropertyChangeMask,
&xevent);
xevent.xclient.message_type = type_atom;
}
}
XDestroyWindow (xdisplay, xwindow); xcb_destroy_window (xconnection, xwindow);
XFlush (xdisplay); xcb_flush(xconnection);
}
break;
}
} }
typedef struct typedef struct
{ {
void *xid; void *xid;
Atom atom; xcb_atom_t atom;
Window xwindow; xcb_window_t xwindow;
sn_bool_t found_handler; sn_bool_t found_handler;
} HandlerForAtomData; } HandlerForAtomData;
static sn_bool_t static sn_bool_t
handler_for_atom_foreach (void *value, handler_for_atom_foreach (void *value,
void *data) void *data)
{ {
SnXmessageHandler *handler = value; SnXmessageHandler *handler = value;
HandlerForAtomData *hfad = data; HandlerForAtomData *hfad = data;
if (handler->xid == hfad->xid && if (handler->xid == hfad->xid &&
(handler->type_atom == hfad->atom || (handler->type_atom == hfad->atom ||
handler->type_atom_begin == hfad->atom)) handler->type_atom_begin == hfad->atom))
{ {
hfad->found_handler = TRUE; hfad->found_handler = TRUE;
return FALSE; return FALSE;
} }
else else
return TRUE; return TRUE;
} }
static sn_bool_t static sn_bool_t
some_handler_handles_event (SnDisplay *display, some_handler_handles_event (SnDisplay *display,
Atom atom, xcb_atom_t atom,
Window win) xcb_window_t win)
{ {
HandlerForAtomData hfad; HandlerForAtomData hfad;
SnList *xmessage_funcs; SnList *xmessage_funcs;
sn_internal_display_get_xmessage_data (display, &xmessage_funcs, sn_internal_display_get_xmessage_data (display, &xmessage_funcs,
NULL); NULL);
hfad.atom = atom; hfad.atom = atom;
hfad.xid = sn_internal_display_get_id (display); hfad.xid = sn_internal_display_get_id (display);
hfad.xwindow = win; hfad.xwindow = win;
hfad.found_handler = FALSE; hfad.found_handler = FALSE;
if (xmessage_funcs) if (xmessage_funcs)
sn_list_foreach (xmessage_funcs, sn_list_foreach (xmessage_funcs,
handler_for_atom_foreach, handler_for_atom_foreach,
&hfad); &hfad);
return hfad.found_handler; return hfad.found_handler;
} }
typedef struct typedef struct
{ {
Window window; xcb_window_t window;
SnXmessage *message; SnXmessage *message;
} FindMessageData; } FindMessageData;
static sn_bool_t static sn_bool_t
find_message_foreach (void *value, find_message_foreach (void *value,
void *data) void *data)
{ {
SnXmessage *message = value; SnXmessage *message = value;
FindMessageData *fmd = data; FindMessageData *fmd = data;
if (fmd->window == message->xwindow) if (fmd->window == message->xwindow)
{ {
fmd->message = message; fmd->message = message;
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
static SnXmessage* static SnXmessage*
message_new(Atom type_atom_begin, Window win) message_new(xcb_atom_t type_atom_begin, xcb_window_t win)
{ {
SnXmessage *message = sn_new0 (SnXmessage, 1); SnXmessage *message = sn_new0 (SnXmessage, 1);
message->type_atom_begin = type_atom_begin; message->type_atom_begin = type_atom_begin;
message->xwindow = win; message->xwindow = win;
message->message = NULL; message->message = NULL;
message->allocated = 0; message->allocated = 0;
return message; return message;
} }
static sn_bool_t static sn_bool_t
message_set_message(SnXmessage *message, const char *src) message_set_message(SnXmessage *message, const char *src)
{ {
const char *src_end; const char *src_end;
char *dest; char *dest;
sn_bool_t completed = FALSE; sn_bool_t completed = FALSE;
src_end = src + 20; src_end = src + 20;
message->message = sn_realloc (message->message, message->message = sn_realloc (message->message,
message->allocated + (src_end - src)); message->allocated + (src_end - src));
dest = message->message + message->allocated; dest = message->message + message->allocated;
message->allocated += (src_end - src); message->allocated += (src_end - src);
/* Copy bytes, be sure we get nul byte also */ /* Copy bytes, be sure we get nul byte also */
while (src != src_end) while (src != src_end)
{ {
*dest = *src; *dest = *src;
if (*src == '\0') if (*src == '\0')
{ {
completed = TRUE; completed = TRUE;
break; break;
} }
++dest; ++dest;
++src; ++src;
} }
return completed; return completed;
} }
static SnXmessage* static SnXmessage*
get_or_add_message(SnList *pending_messages, get_or_add_message(SnList *pending_messages,
Window win, xcb_window_t win,
Atom type_atom_begin) xcb_atom_t type_atom_begin)
{ {
FindMessageData fmd; FindMessageData fmd;
SnXmessage *message; SnXmessage *message;
fmd.window = win; fmd.window = win;
fmd.message = NULL; fmd.message = NULL;
if (pending_messages) if (pending_messages)
sn_list_foreach (pending_messages, find_message_foreach, &fmd); sn_list_foreach (pending_messages, find_message_foreach, &fmd);
message = fmd.message; message = fmd.message;
if (message == NULL) if (message == NULL)
{ {
message = message_new(type_atom_begin, win); message = message_new(type_atom_begin, win);
sn_list_prepend (pending_messages, message); sn_list_prepend (pending_messages, message);
} }
return message; return message;
} }
static SnXmessage* static SnXmessage*
add_event_to_messages (SnDisplay *display, add_event_to_messages (SnDisplay *display,
Window win, xcb_window_t win,
Atom message_type, xcb_atom_t message_type,
const char *data) const char *data)
{ {
SnXmessage *message; SnXmessage *message;
SnList *pending_messages; SnList *pending_messages;
sn_internal_display_get_xmessage_data (display, NULL, sn_internal_display_get_xmessage_data (display, NULL,
&pending_messages); &pending_messages);
message = get_or_add_message(pending_messages, message = get_or_add_message(pending_messages,
win, message_type); win, message_type);
/* We don't want screwy situations to end up causing us to allocate /* We don't want screwy situations to end up causing us to allocate
* infinite memory. Cap the length of a message. * infinite memory. Cap the length of a message.
*/ */
#define MAX_MESSAGE_LENGTH 4096 #define MAX_MESSAGE_LENGTH 4096
if (message->allocated > MAX_MESSAGE_LENGTH) if (message->allocated > MAX_MESSAGE_LENGTH)
{ {
/* This message is some kind of crap - just dump it. */ /* This message is some kind of crap - just dump it. */
sn_free (message->message); sn_free (message->message);
sn_list_remove (pending_messages, message); sn_list_remove (pending_messages, message);
sn_free (message); sn_free (message);
return NULL; return NULL;
} }
if (message_set_message (message, data)) if (message_set_message (message, data))
{ {
/* Pull message out of the pending queue and return it */ /* Pull message out of the pending queue and return it */
sn_list_remove (pending_messages, message); sn_list_remove (pending_messages, message);
return message; return message;
} }
else else
return NULL; return NULL;
} }
typedef struct typedef struct
{ {
SnDisplay *display; SnDisplay *display;
SnXmessage *message; SnXmessage *message;
} MessageDispatchData; } MessageDispatchData;
static sn_bool_t static sn_bool_t
dispatch_message_foreach (void *value, dispatch_message_foreach (void *value,
void *data) void *data)
{ {
SnXmessageHandler *handler = value; SnXmessageHandler *handler = value;
MessageDispatchData *mdd = data; MessageDispatchData *mdd = data;
if (handler->type_atom_begin == mdd->message->type_atom_begin && if (handler->type_atom_begin == mdd->message->type_atom_begin &&
sn_internal_display_get_id (mdd->display) == handler->xid) sn_internal_display_get_id (mdd->display) == handler->xid)
(* handler->func) (mdd->display, (* handler->func) (mdd->display,
handler->message_type, handler->message_type,
mdd->message->message, mdd->message->message,
handler->func_data); handler->func_data);
return TRUE; return TRUE;
} }
static void static void
xmessage_process_message (SnDisplay *display, SnXmessage *message) xmessage_process_message (SnDisplay *display, SnXmessage *message)
{ {
if (message) if (message)
{ {
/* We need to dispatch and free this message; ignore /* We need to dispatch and free this message; ignore
* messages containing invalid UTF-8 * messages containing invalid UTF-8
*/ */
if (sn_internal_utf8_validate (message->message, -1)) if (sn_internal_utf8_validate (message->message, -1))
{ {
MessageDispatchData mdd; MessageDispatchData mdd;
SnList *xmessage_funcs; SnList *xmessage_funcs;
sn_internal_display_get_xmessage_data (display, &xmessage_funcs, sn_internal_display_get_xmessage_data (display, &xmessage_funcs,
NULL); NULL);
mdd.display = display; mdd.display = display;
mdd.message = message; mdd.message = message;
/* We could stand to be more reentrant here; it will /* We could stand to be more reentrant here; it will
* barf if you add/remove a handler from inside the * barf if you add/remove a handler from inside the
* dispatch * dispatch
*/ */
if (xmessage_funcs != NULL) if (xmessage_funcs != NULL)
sn_list_foreach (xmessage_funcs, sn_list_foreach (xmessage_funcs,
dispatch_message_foreach, dispatch_message_foreach,
&mdd); &mdd);
} }
else else
{ {
/* FIXME don't use fprintf, use something pluggable */ /* FIXME don't use fprintf, use something pluggable */
fprintf (stderr, "Bad UTF-8 in startup notification message\n"); fprintf (stderr, "Bad UTF-8 in startup notification message\n");
} }
sn_free (message->message); sn_free (message->message);
sn_free (message); sn_free (message);
} }
} }
sn_bool_t sn_bool_t
sn_internal_xmessage_process_event (SnDisplay *display, sn_internal_xmessage_process_client_message (SnDisplay *display,
XEvent *xevent) xcb_window_t window,
xcb_atom_t type,
const char *data)
{ {
sn_bool_t retval = FALSE; sn_bool_t retval = FALSE;
SnXmessage *message = NULL; SnXmessage *message = NULL;
switch (xevent->xany.type) if (some_handler_handles_event (display, type, window))
{ {
case ClientMessage: retval = TRUE;
if (some_handler_handles_event (display,
xevent->xclient.message_type,
xevent->xclient.window))
{
retval = TRUE;
message = add_event_to_messages (display, message = add_event_to_messages (display, window, type, data);
xevent->xclient.window, }
xevent->xclient.message_type,
xevent->xclient.data.b);
}
break;
}
xmessage_process_message (display, message); xmessage_process_message (display, message);
return retval; return retval;
} }
static void static void
sn_internal_append_to_string_escaped (char **append_to, sn_internal_append_to_string_escaped (char **append_to,
int *current_len, int *current_len,
const char *append) const char *append)
{ {
char *escaped; char *escaped;
int len; int len;
char buf[2]; char buf[2];
const char *p; const char *p;
buf[1] = '\0'; buf[1] = '\0';
len = 0; len = 0;
escaped = NULL; escaped = NULL;
/* We are the most inefficient algorithm ever! woot! */ /* We are the most inefficient algorithm ever! woot! */
/* really need GString here */ /* really need GString here */
p = append; p = append;
while (*p) while (*p)
{ {
if (*p == '\\' || *p == '"' || *p == ' ') if (*p == '\\' || *p == '"' || *p == ' ')
{ {
buf[0] = '\\'; buf[0] = '\\';
sn_internal_append_to_string (&escaped, &len, buf); sn_internal_append_to_string (&escaped, &len, buf);
} }
buf[0] = *p; buf[0] = *p;
sn_internal_append_to_string (&escaped, &len, buf); sn_internal_append_to_string (&escaped, &len, buf);
++p; ++p;
} }
if (escaped != NULL) if (escaped != NULL)
{ {
sn_internal_append_to_string (append_to, current_len, escaped); sn_internal_append_to_string (append_to, current_len, escaped);
sn_free (escaped); sn_free (escaped);
} }
} }
char* char*
sn_internal_serialize_message (const char *prefix, sn_internal_serialize_message (const char *prefix,
const char **property_names, const char **property_names,
const char **property_values) const char **property_values)
{ {
int len; int len;
char *retval; char *retval;
int i; int i;
/* GLib would simplify this a lot... */
len = 0;
retval = NULL;
sn_internal_append_to_string (&retval, &len, prefix);
sn_internal_append_to_string (&retval, &len, ":");
i = 0;
while (property_names[i])
{
sn_internal_append_to_string (&retval, &len, " ");
sn_internal_append_to_string (&retval, &len, property_names[i]);
sn_internal_append_to_string (&retval, &len, "=");
sn_internal_append_to_string_escaped (&retval, &len, property_values[i])
;
++i; /* GLib would simplify this a lot... */
len = 0;
retval = NULL;
sn_internal_append_to_string (&retval, &len, prefix);
sn_internal_append_to_string (&retval, &len, ":");
i = 0;
while (property_names[i])
{
sn_internal_append_to_string (&retval, &len, " ");
sn_internal_append_to_string (&retval, &len, property_names[i]);
sn_internal_append_to_string (&retval, &len, "=");
sn_internal_append_to_string_escaped (&retval, &len, property_values[i]);
++i;
} }
return retval; return retval;
} }
/* Takes ownership of @append /* Takes ownership of @append
*/ */
static void static void
append_string_to_list (char ***list, append_string_to_list (char ***list,
char *append) char *append)
{ {
if (*list == NULL) if (*list == NULL)
{ {
*list = sn_new0 (char*, 2); *list = sn_new0 (char*, 2);
(*list)[0] = append; (*list)[0] = append;
} }
else else
{ {
int i; int i;
i = 0; i = 0;
while ((*list)[i] != NULL) while ((*list)[i] != NULL)
++i; ++i;
*list = sn_renew (char*, *list, i + 2); *list = sn_renew (char*, *list, i + 2);
(*list)[i] = append; (*list)[i] = append;
(*list)[i+1] = NULL; (*list)[i+1] = NULL;
} }
} }
static char* static char*
parse_prefix_up_to (const char *str, parse_prefix_up_to (const char *str,
int up_to, int up_to,
const char **end) const char **end)
{ {
char *prefix; char *prefix;
const char *p; const char *p;
int len; int len;
prefix = NULL; prefix = NULL;
*end = NULL; *end = NULL;
p = str; p = str;
while (*p && *p != up_to) while (*p && *p != up_to)
++p; ++p;
if (*p == '\0') if (*p == '\0')
return NULL; return NULL;
len = p - str; len = p - str;
prefix = sn_internal_strndup (str, len); prefix = sn_internal_strndup (str, len);
*end = str + len; *end = str + len;
return prefix; return prefix;
} }
/* Single quotes preserve the literal string exactly. escape /* Single quotes preserve the literal string exactly. escape
* sequences are not allowed; not even \' - if you want a ' * sequences are not allowed; not even \' - if you want a '
* in the quoted text, you have to do something like 'foo'\''bar' * in the quoted text, you have to do something like 'foo'\''bar'
* *
* Double quotes allow $ ` " \ and newline to be escaped with backslash. * Double quotes allow $ ` " \ and newline to be escaped with backslash.
* Otherwise double quotes preserve things literally. * Otherwise double quotes preserve things literally.
* *
* (This is overkill for X messages, copied from GLib shell code, * (This is overkill for X messages, copied from GLib shell code,
* copyright Red Hat Inc. also) * copyright Red Hat Inc. also)
*/ */
static sn_bool_t static sn_bool_t
unescape_string_inplace (char *str, unescape_string_inplace (char *str,
char **end) char **end)
{ {
char* dest; char* dest;
char* s; char* s;
sn_bool_t escaped; sn_bool_t escaped;
sn_bool_t quoted; sn_bool_t quoted;
dest = s = str; dest = s = str;
escaped = FALSE; escaped = FALSE;
quoted = FALSE; quoted = FALSE;
while (*s) while (*s)
{ {
if (escaped) if (escaped)
{ {
escaped = FALSE; escaped = FALSE;
*dest = *s; *dest = *s;
++dest; ++dest;
} }
else if (quoted) else if (quoted)
{ {
if (*s == '"') if (*s == '"')
quoted = FALSE; quoted = FALSE;
else if (*s == '\\') else if (*s == '\\')
escaped = TRUE; escaped = TRUE;
else else
{ {
*dest = *s; *dest = *s;
++dest; ++dest;
} }
} }
else else
{ {
if (*s == ' ') if (*s == ' ')
break; break;
else if (*s == '\\') else if (*s == '\\')
escaped = TRUE; escaped = TRUE;
else if (*s == '"') else if (*s == '"')
quoted = TRUE; quoted = TRUE;
else else
{ {
*dest = *s; *dest = *s;
++dest; ++dest;
} }
} }
++s; ++s;
} }
*dest = '\0'; *dest = '\0';
*end = s; *end = s;
return TRUE; return TRUE;
} }
static sn_bool_t static sn_bool_t
parse_property (const char *str, parse_property (const char *str,
char **name_p, char **name_p,
char **val_p, char **val_p,
const char **end_p) const char **end_p)
{ {
char *val; char *val;
char *name; char *name;
char *copy; char *copy;
char *p; char *p;
*end_p = NULL; *end_p = NULL;
copy = sn_internal_strdup (str); copy = sn_internal_strdup (str);
p = copy; p = copy;
while (*p == ' ') while (*p == ' ')
++p; ++p;
name = parse_prefix_up_to (p, '=', (const char**) &p); name = parse_prefix_up_to (p, '=', (const char**) &p);
if (name == NULL) if (name == NULL)
{ {
sn_free (copy); sn_free (copy);
return FALSE; return FALSE;
} }
++p; /* skip '=' */ ++p; /* skip '=' */
while (*p == ' ') while (*p == ' ')
++p; ++p;
{ {
char *end; char *end;
end = NULL; end = NULL;
if (!unescape_string_inplace (p, &end)) if (!unescape_string_inplace (p, &end))
{ {
sn_free (copy); sn_free (copy);
sn_free (name); sn_free (name);
return FALSE; return FALSE;
} }
val = sn_internal_strndup (p, end - p); val = sn_internal_strndup (p, end - p);
p = end; p = end;
} }
while (*p == ' ') while (*p == ' ')
++p; ++p;
*end_p = str + (p - copy); *end_p = str + (p - copy);
sn_free (copy); sn_free (copy);
*name_p = name; *name_p = name;
*val_p = val; *val_p = val;
return TRUE; return TRUE;
} }
sn_bool_t sn_bool_t
sn_internal_unserialize_message (const char *message, sn_internal_unserialize_message (const char *message,
char **prefix_p, char **prefix_p,
char ***property_names, char ***property_names,
char ***property_values) char ***property_values)
{ {
/* GLib would simplify this a lot... */ /* GLib would simplify this a lot... */
char *prefix; char *prefix;
char **names; char **names;
char **values; char **values;
const char *p; const char *p;
char *name; char *name;
char *value; char *value;
*prefix_p = NULL;
*property_names = NULL;
*property_values = NULL;
prefix = NULL;
names = NULL;
values = NULL;
prefix = parse_prefix_up_to (message, ':', &p); *prefix_p = NULL;
if (prefix == NULL) *property_names = NULL;
return FALSE; *property_values = NULL;
prefix = NULL;
names = NULL;
values = NULL;
++p; /* skip ':' */ prefix = parse_prefix_up_to (message, ':', &p);
if (prefix == NULL)
return FALSE;
name = NULL; ++p; /* skip ':' */
value = NULL;
while (parse_property (p, &name, &value, &p)) name = NULL;
value = NULL;
while (parse_property (p, &name, &value, &p))
{ {
append_string_to_list (&names, name); append_string_to_list (&names, name);
append_string_to_list (&values, value); append_string_to_list (&values, value);
} }
*prefix_p = prefix; *prefix_p = prefix;
*property_names = names; *property_names = names;
*property_values = values; *property_values = values;
return TRUE; return TRUE;
} }
 End of changes. 150 change blocks. 
458 lines changed or deleted 442 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)