2012-11-10 07:41:39 -05:00
|
|
|
/*
|
|
|
|
* vim:ts=4:sw=4:expandtab
|
|
|
|
*
|
|
|
|
* i3bar - an xcb-based status- and ws-bar for i3
|
|
|
|
* © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
|
|
|
|
*
|
2015-03-23 15:56:49 -04:00
|
|
|
* mode.c: Handle mode event and show current binding mode in the bar
|
2012-11-10 07:41:39 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <yajl/yajl_parse.h>
|
|
|
|
#include <yajl/yajl_version.h>
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
/* A datatype to pass through the callbacks to save the state */
|
|
|
|
struct mode_json_params {
|
2014-06-15 13:07:02 -04:00
|
|
|
char *json;
|
|
|
|
char *cur_key;
|
|
|
|
mode *mode;
|
2012-11-10 07:41:39 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse a string (change)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
|
2014-06-15 13:07:02 -04:00
|
|
|
struct mode_json_params *params = (struct mode_json_params *)params_;
|
2012-11-10 07:41:39 -05:00
|
|
|
|
2014-06-15 13:07:02 -04:00
|
|
|
if (!strcmp(params->cur_key, "change")) {
|
|
|
|
/* Save the name */
|
|
|
|
params->mode->name = i3string_from_utf8_with_length((const char *)val, len);
|
|
|
|
/* Save its rendered width */
|
|
|
|
params->mode->width = predict_text_width(params->mode->name);
|
2012-11-10 07:41:39 -05:00
|
|
|
|
2014-06-15 13:07:02 -04:00
|
|
|
DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
|
|
|
|
FREE(params->cur_key);
|
2012-11-10 07:41:39 -05:00
|
|
|
|
2014-06-15 13:07:02 -04:00
|
|
|
return 1;
|
|
|
|
}
|
2012-11-10 07:41:39 -05:00
|
|
|
|
2014-06-15 13:07:02 -04:00
|
|
|
return 0;
|
2012-11-10 07:41:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse a key.
|
|
|
|
*
|
2015-03-23 15:56:49 -04:00
|
|
|
* Essentially we just save it in the parsing state
|
2012-11-10 07:41:39 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
2014-06-15 13:07:02 -04:00
|
|
|
struct mode_json_params *params = (struct mode_json_params *)params_;
|
2012-11-10 07:41:39 -05:00
|
|
|
FREE(params->cur_key);
|
|
|
|
|
|
|
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
2014-06-15 13:07:02 -04:00
|
|
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
2012-11-10 07:41:39 -05:00
|
|
|
params->cur_key[keyLen] = '\0';
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* A datastructure to pass all these callbacks to yajl */
|
2014-01-01 11:19:55 -05:00
|
|
|
static yajl_callbacks mode_callbacks = {
|
|
|
|
.yajl_string = mode_string_cb,
|
|
|
|
.yajl_map_key = mode_map_key_cb,
|
2012-11-10 07:41:39 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2015-03-23 15:56:49 -04:00
|
|
|
* Start parsing the received JSON string
|
2012-11-10 07:41:39 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
void parse_mode_json(char *json) {
|
2015-03-23 15:56:49 -04:00
|
|
|
/* FIXME: Fasciliate stream processing, i.e. allow starting to interpret
|
2012-11-10 07:41:39 -05:00
|
|
|
* JSON in chunks */
|
|
|
|
struct mode_json_params params;
|
|
|
|
|
|
|
|
mode binding;
|
|
|
|
|
|
|
|
params.cur_key = NULL;
|
|
|
|
params.json = json;
|
|
|
|
params.mode = &binding;
|
|
|
|
|
|
|
|
yajl_handle handle;
|
|
|
|
yajl_status state;
|
|
|
|
|
2014-06-15 13:07:02 -04:00
|
|
|
handle = yajl_alloc(&mode_callbacks, NULL, (void *)¶ms);
|
2012-11-10 07:41:39 -05:00
|
|
|
|
2014-06-15 13:07:02 -04:00
|
|
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
2012-11-10 07:41:39 -05:00
|
|
|
|
2015-03-24 08:41:16 -04:00
|
|
|
/* FIXME: Propper error handling for JSON parsing */
|
2012-11-10 07:41:39 -05:00
|
|
|
switch (state) {
|
|
|
|
case yajl_status_ok:
|
|
|
|
break;
|
|
|
|
case yajl_status_client_canceled:
|
|
|
|
case yajl_status_error:
|
2015-03-23 15:56:49 -04:00
|
|
|
ELOG("Could not parse mode event!\n");
|
2012-11-10 07:41:39 -05:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We don't want to indicate default binding mode */
|
|
|
|
if (strcmp("default", i3string_as_utf8(params.mode->name)) == 0)
|
|
|
|
I3STRING_FREE(params.mode->name);
|
|
|
|
|
|
|
|
/* Set the new binding mode */
|
|
|
|
set_current_mode(&binding);
|
|
|
|
|
|
|
|
yajl_free(handle);
|
|
|
|
|
|
|
|
FREE(params.cur_key);
|
|
|
|
}
|