Exemplo n.º 1
0
Arquivo: ekg.c Projeto: pawelz/ekg2
void ekg_debug_handler(int level, const char *format, va_list ap) {
	static GString *line = NULL;
	char *tmp = NULL;

	char *theme_format;
	int is_UI = 0;

	if (!config_debug)
		return;

	if (line) {
		g_string_append_vprintf(line, format, ap);

		if (line->len == 0 || line->str[line->len - 1] != '\n')
			return;

		line->str[line->len - 1] = '\0';	/* remove '\n' */
		tmp = g_string_free(line, FALSE);
		line = NULL;
	} else {
		int tmplen = g_vasprintf(&tmp, format, ap);

		if (tmplen < 0 || !tmp)	/* OutOfMemory? */
			return;

		if (tmplen == 0 || tmp[tmplen - 1] != '\n') {
			line = g_string_new_len(tmp, tmplen);
			g_free(tmp);
			return;
		}
		tmp[tmplen - 1] = 0;			/* remove '\n' */
	}

	switch(level) {
		case 0:				theme_format = "debug";		break;
		case DEBUG_IO:			theme_format = "iodebug";	break;
		case DEBUG_IORECV:		theme_format = "iorecvdebug";	break;
		case DEBUG_FUNCTION:		theme_format = "fdebug";	break;
		case DEBUG_ERROR:		theme_format = "edebug";	break;
		case DEBUG_WHITE:		theme_format = "wdebug";	break;
		case DEBUG_WARN:		theme_format = "warndebug";	break;
		case DEBUG_OK:			theme_format = "okdebug";	break;
		default:			theme_format = "debug";		break;
	}

	ekg_fix_utf8(tmp); /* debug message can contain random data */
	buffer_add(&buffer_debug, theme_format, tmp);

	query_emit(NULL, "ui-is-initialized", &is_UI);

	if (is_UI && window_debug) {
		print_window_w(window_debug, EKG_WINACT_NONE, theme_format, tmp);
	}
#ifdef STDERR_DEBUG	/* STDERR debug */
	else
		fprintf(stderr, "%s\n", tmp);
#endif
	xfree(tmp);
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: hiciu/ekg2
static int logs_print_window(session_t *s, window_t *w, const char *line, time_t ts) {
	static plugin_t *ui_plugin = NULL;

	fstring_t *fstr;

	/* it's enough to look for ui_plugin once */
	if (!ui_plugin) ui_plugin = plugin_find(("ncurses"));
	if (!ui_plugin) ui_plugin = plugin_find(("gtk"));
	if (!ui_plugin) {
		debug_error("WARN logs_print_window() called but neither ncurses plugin nor gtk found\n");
		return -1;
	}

	fstr = fstring_new_format(line);
	fstr->ts = ts;

	query_emit(ui_plugin, "ui-window-print", &w, &fstr);
	fstring_free(fstr);
	return 0;
}
Exemplo n.º 3
0
Arquivo: main.c Projeto: hiciu/ekg2
static void logs_buffer_raw_display(window_t *w) {
	char *line, **lines;
	logs_log_t *ll;
	int i, j, n, all = (config_logs_remind_number <= 0);

	if (!w || !w->session)
		return;

	if ((WINDOW_STATUS_ID == w->id) || (WINDOW_CONTACTS_ID == w->id) || (WINDOW_LASTLOG_ID ==w->id ))
		return;

	if (!(ll = logs_log_open(session_uid_get(w->session), w->target, TRUE)))
		return;

	if (!all)
		lines = g_new0(char *, config_logs_remind_number + 1);

	// read log
	n = 0;
	fseek(ll->file, 0, SEEK_SET);
	while ((line = read_file(ll->file, 0))) {
		ekg_fix_utf8(line);
		if (all) {
			time_t t = g_ascii_strtoll(line, &line, 10);
			if (t>0 && *line == ' ') line++;
			logs_print_window(w->session, w, line, t);
		} else {
			j = n % config_logs_remind_number;
			g_free(lines[j]);
			lines[j] = g_strdup(line);
			n++;
		}
	}

	if (all) {
		query_emit(NULL, "ui-window-refresh");
		return;
	}

	ftruncate(fileno(ll->file), 0);

	// display and rewrite log
	w->lock++;
	for (i=0; i < config_logs_remind_number; i++, n++) {
		time_t t;
		j = n % config_logs_remind_number;
		if (!lines[j])
			continue;
		fputs(lines[j], ll->file);
		fputc('\n', ll->file);

		t = g_ascii_strtoll(lines[j], &line, 10);
		if (t>0 && *line == ' ') line++;
		logs_print_window(w->session, w, line, t);
	}
	w->lock--;

	g_strfreev(lines);

	query_emit(NULL, "ui-window-refresh");

}
Exemplo n.º 4
0
Arquivo: main.c Projeto: 11mariom/ekg2
	/* items == -1 display all */
static int logs_buffer_raw_display(const char *file, int items) {
	struct buffer **bs = NULL;
	struct buffer *b;
	char *beg = NULL, *profile = NULL, *sesja = NULL, *target = NULL;

	int item = 0;
	int i;

	session_t *s;
	window_t *w;

	if (!file) return -1;
	if (!items) return 0;

	/* i'm weird, let's search for logs/__internal__ than check if there are smth after it... & check if there are two '/'	*/
	if ((beg = xstrstr(file, "logs/__internal__")) && xstrlen(beg) > 19 && xstrchr(beg+18, '/') && xstrchr(beg+18, '/') != xstrrchr(beg+18, '/')) {
		profile = beg + 18;
		sesja	= xstrchr(profile, '/')+1;
		target	= xstrchr(sesja, '/')+1;
	}
	debug("[logs_buffer_raw_display()] profile: 0x%x sesja: 0x%x target: 0x%x\n", profile, sesja, target);

	if (!profile || !sesja || !target) return -1;

	profile = (xstrcmp(target, "_default_"))	? xstrndup(profile, sesja-profile-1) : NULL;
	sesja	= (xstrcmp(target, "_null_"))		? xstrndup(sesja, target-sesja-1) : NULL;
	target	= xstrdup(target);
	debug("[logs_buffer_raw_display()] profile: %s sesja: %s target: %s\n", __(profile), __(sesja), __(target));

	/* search for session+window */
	s = session_find(sesja);
	w = window_find_s(s, target);


	debug("[logs_buffer_raw_display()] s:0x%x; w:0x%x;\n", s, w);

	if (!w)
		w = window_current;

	if (w) w->lock++;

	for (b = buffer_lograw.data; b; b = b->next) {
		if (!xstrcmp(b->target, file)) {
			/* we asume that (b->ts < (b->next)->ts, it's quite correct unless other plugin do this trick... */
			if (items == -1) { 
				logs_print_window(s, w, b->line, b->ts);
			} else {
				bs		= (struct buffer **) xrealloc(bs, (item+2) * sizeof(struct buffer *));
				bs[item + 1]	= NULL;
				bs[item]	= b;
			}
			item++;
		}
	}
	if (bs) for (i = item < items ? 0 : item-items; i < item; i++) 
		logs_print_window(s, w, bs[i]->line, bs[i]->ts);

	if (w) {
		w->lock--;
		query_emit(NULL, "ui-window-refresh");
	}

	xfree(bs);

	xfree(profile);
	xfree(sesja);
	xfree(target);
	return item;
}
Exemplo n.º 5
0
Arquivo: ekg.c Projeto: pawelz/ekg2
static void handle_sigusr2()
{
	debug("sigusr2 received\n");
	query_emit(NULL, "ekg-sigusr2");
	signal(SIGUSR2, handle_sigusr2);
}
Exemplo n.º 6
0
Arquivo: ekg.c Projeto: pawelz/ekg2
static void handle_sigusr1()
{
	debug("sigusr1 received\n");
	query_emit(NULL, "ekg-sigusr1");
	signal(SIGUSR1, handle_sigusr1);
}
Exemplo n.º 7
0
Arquivo: misc.c Projeto: hiciu/ekg2
static void irc_access_parse(session_t *s, channel_t *chan, people_t *p, int flags) {
	userlist_t *ul;

	if (!s || !chan || !p)
		return;

#define dchar(x) debug("%c", x);

	for (ul = s->userlist; ul; ul = ul->next) {
		userlist_t *u = ul;
		ekg_resource_t *r = NULL, *rl;

		int i, j;

		if (!p->ident || !p->host) continue;

		if (xstrncmp(u->uid, "irc:", 4)) continue;	/* check for irc: */

		for (rl = u->resources; rl; rl = rl->next) {
			r = rl;

			if (r->priv_data == p) {
				const char *tmp = &(u->uid[4]);

				/* fast forward move.. */
				if (!(tmp = xstrchr(tmp, '!')) || !(tmp = xstrchr(tmp, '@')) || !(tmp = xstrchr(tmp, ':'))) {
					debug_error("%s:%d INTERNAL ERROR\n", __FILE__, __LINE__);
					goto next3;
				}
				tmp++;
				i = (tmp - u->uid);
				debug("irc, checkchan: %s\n", tmp);
				goto skip_identhost_check;
				break;	/* never here */
			}
		}
		r = NULL;
/* parse nick! */
		for (i = 4, j = 0; (u->uid[i] != '\0' && u->uid[i] != '!'); i++, j++) {
			dchar(u->uid[i]);

			if (u->uid[i] != p->ident[j]) {
				if (u->uid[i] == '*') j += do_sample_wildcard_match(&u->uid[i+1], &p->ident[j], '!');
				else if (u->uid[i] == '?') continue;
				else goto next;
			}
		} if (!u->uid[i]) goto next;
		dchar('!');
		i++;

/* parse ident@ */
		for (j = 0; (u->uid[i] != '\0' && u->uid[i] != '@'); i++, j++) {
			dchar(u->uid[i]);

			if (u->uid[i] != p->nick[j]) {
				if (u->uid[i] == '*') j += do_sample_wildcard_match(&u->uid[i+1], &p->ident[j], '@');
				else if (u->uid[i] == '?') continue;
				else goto next;
			}
		} if (!u->uid[i]) goto next;
		dchar('@');
		i++;

/* parse host: */
		for (j = 0; (u->uid[i] != '\0' && u->uid[i] != ':'); i++, j++) {
			dchar(u->uid[i]);

			if (u->uid[i] != p->host[j]) {
				if (u->uid[i] == '*') j += do_sample_wildcard_match(&u->uid[i+1], &p->ident[j], ':');
				else if (u->uid[i] == '?') continue;
				else goto next;
			}
		} if (!u->uid[i]) goto next;
		dchar('\n');
		i++;

		debug_error("irc_access_parse() %s!%s@%s MATCH with %s\n", p->ident, p->nick, p->host, u->uid+4);

skip_identhost_check:
/* let's rock with channels */
		{
			char **arr = array_make(&u->uid[i], ",", 0, 1, 0);

			int ismatch = 0;


			for (i=0; arr[i]; i++) {
				int k;
				debug_error("CHAN%d: %s: ", i, arr[i]);

				for (j = 0, k = 4 /* skip irc: */; arr[i][j]; j++, k++) {
					if (arr[i][j] != chan->name[k]) {
						if (arr[i][j] == '*') k += do_sample_wildcard_match(&arr[i][j+1], &chan->name[k], '\0');
						else if (arr[i][j] == '?') continue;
						else goto next2;
					}
				}
				if (chan->name[k] != '\0')
					goto next2;

				ismatch = 1;
				debug_error("MATCH\n");
				break;
next2:
				debug_error("NOT MATCH\n");
				continue;

			}
			g_strfreev(arr);

			if (!ismatch) continue;
		}
		if (!r) {
			char *tmp = irc_uid(p->nick);
			r = userlist_resource_add(u, tmp, 0);
			g_free(tmp);

			r->status	= EKG_STATUS_AVAIL;
			r->descr	= xstrdup(chan->name+4);
			r->priv_data	= p;

			if (u->status != EKG_STATUS_AVAIL) {
				xfree(u->descr);
				u->status	= EKG_STATUS_AVAIL;
				u->descr	= xstrdup("description... ?");
				query_emit(NULL, "userlist-changed", &(s->uid), &(u->uid));
			}
		} else {
			string_t str = string_init(r->descr);

			string_append_c(str, ',');
			string_append(str, chan->name+4);

			xfree(r->descr); r->descr = string_free(str, 0);
		}

		/* tutaj ladnie by wygladalo jakbysmy wywolali protocol-status.. ale jednak to jest b. kiepski pomysl */
		debug_error("USER: 0x%x PERMISION GRANTED ON CHAN: 0x%x\n", u, chan);
		continue;

next:
		dchar('\n');
		debug_error("irc_access_parse() %s!%s@%s NOT MATCH with %s\n", p->ident, p->nick, p->host, u->uid+4);
next3:
		continue;
	}
#undef dchar
}
Exemplo n.º 8
0
Arquivo: misc.c Projeto: hiciu/ekg2
int irc_parse_line(session_t *s, const char *l)
{
	static GString *strbuf = NULL;
	irc_private_t *j = s->priv;
	int	i, c=0, ecode, n_params;
	char	*p, *cmd, *colon2, **args = NULL, **pfxcmd = NULL;

	gchar *buf;
	int	len;

	if (G_UNLIKELY(!strbuf))
		strbuf = g_string_new(l);
	else
		g_string_assign(strbuf, l);

	irc_convert_in(j, strbuf);
	buf = strbuf->str;
	len = strbuf->len;

	query_emit(NULL, "irc-parse-line", &s->uid, &buf);

	p=buf;
	if(!p)
		return -1;
/*
Each IRC message may consist of up to three main parts: the prefix
(optional), the command, and the command parameters (of which there
may be up to 15).  The prefix, command, and all parameters are
separated by one (or more) ASCII space character(s) (0x20).

The presence of a prefix is indicated with a single leading ASCII
colon character (':', 0x3b), which must be the first character of the
message itself.  There must be no gap (whitespace) between the colon
and the prefix.
*/
	/* GiM: In fact this is probably not needed, but just in case...  */
	for (i=0; i<len; i++) if (buf[i]=='\n' || buf[i]=='\r') buf[i]='\0';

	if ((colon2=xstrstr(p, " :")))
		*colon2 = '\0';

	args = array_make(OMITCOLON(p), " ", 0, 1, 0);

	if (colon2) {
		*colon2 = ' ';
		array_add(&args, xstrdup(colon2+2));
	}

#define prefix pfxcmd[0]
#define pfx_nick pfxcmd[1]
#define pfx_ihost pfxcmd[2]
#define cmdname pfxcmd[3]

	/* prefix is optional... */
	if (':' != *buf) {
		array_add(&pfxcmd, g_strdup(""));	// prefix
		array_add(&pfxcmd, g_strdup(""));	// pfx_nick
		array_add(&pfxcmd, g_strdup(""));	// pfx_ihost
	} else {
		array_add(&pfxcmd, array_shift(&args));						// prefix
		p = xstrchr(pfxcmd[0], '!');
		array_add(&pfxcmd, p ? g_strndup(pfxcmd[0], p-pfxcmd[0]) : g_strdup(""));	// pfx_nick
		array_add(&pfxcmd, p ? g_strdup(p+1) : g_strdup(""));				// pfx_ihost
	}

	cmd = array_shift(&args);
	array_add(&pfxcmd, cmd);		// cmdname

	/* debug only nasty hack ;> */
#ifdef GDEBUG
	/* mg: well, it's not the exact data sent, but color is needed indeed */
	i=0;
	if (*pfxcmd[0]) debug_iorecv("[%s]", pfxcmd[0]);
	debug_iorecv("[%s]", cmd);
	while (args[i] != NULL) debug_iorecv("[%s]",args[i++]);
	debug_iorecv("\n");
#endif

	n_params = g_strv_length(args);
	if (xstrlen(cmd) > 1) {
		if(!gatoi(cmd, &ecode)) {
			/* for scripts */
			char *emitname = saprintf("irc-protocol-numeric %s", cmd);
			if ((query_emit(NULL, "irc-protocol-numeric", &s->uid, &ecode, &args) == -1) ||
			    (query_emit(NULL, emitname, &s->uid, &args) == -1))
			{
				xfree(emitname);
				g_strfreev(pfxcmd);
				g_strfreev(args);
				return -1;
			}
			xfree(emitname);

			c=0;
			while(irccommands[c].type != -1) {
				if (irccommands[c].type == 1 && irccommands[c].num == ecode) {
					if (irccommands[c].min_params > n_params) {
						debug_error("[irc] parse_line() Not enough parameters! cmd=%s, n=%d, min=%d\n",
								cmd, n_params, irccommands[c].min_params);
					} else
					/* I'm sending c not ecode!!!! */
					if ((*(irccommands[c].handler))(s, j, c, pfxcmd, args) == -1 ) {
						debug_error("[irc] parse_line() error while executing handler!\n");
					}
					/* GiM: XXX I don't expect more,
					 * then one handler on list... */
					break;
				}
				c++;
			}
#ifdef GDEBUG
			if (irccommands[c].type == -1) {
				debug("trying default handler\n");
				if ((*(irccommands[0].handler))(s, j, 0, pfxcmd, args) == -1 ) {
					debug("[irc] parse_line() error while executing handler!\n");
				}

			}
#endif
		} else {
			c=0;
			while(irccommands[c].type != -1) {
				if (irccommands[c].type == 0 && !xstrcmp(irccommands[c].comm, cmd)) {
					if (irccommands[c].min_params > n_params) {
						debug_error("[irc] parse_line() Not enough parameters! cmd=%s, n=%d, min=%d\n",
								cmd, n_params, irccommands[c].min_params);
					} else
					/* dj: instead of  ecode,    c; */
					if ((*(irccommands[c].handler))(s, j, c, pfxcmd, args) == -1 ) {
						debug_error("[irc] parse_line() error while executing handler!\n");
					}
					break;
				}
				c++;
			}
		}
	}

	g_strfreev(pfxcmd);
	g_strfreev(args);
	return 0;
}
Exemplo n.º 9
0
/*
 * variable_set()
 *
 * ustawia warto¶æ podanej zmiennej. je¶li to zmienna liczbowa lub boolowska,
 * zmienia ci±g na liczbê. w przypadku boolowskich, rozumie zwroty typu `on',
 * `off', `yes', `no' itp. je¶li dana zmienna jest bitmap±, akceptuje warto¶æ
 * w postaci listy flag oraz konstrukcje `+flaga' i `-flaga'.
 *
 *  - name - nazwa zmiennej,
 *  - value - nowa warto¶æ,
 */
int variable_set(const char *name, const char *value) {
	variable_t *v = variable_find(name);
	char *tmpname;
	int changed = 0;

	if (!v)
		return -1;

	switch (v->type) {
		case VAR_INT:
		case VAR_MAP:
		{
			const char *p = value;
			int hex, tmp;

			if (!value)
				return -2;

			if (v->map && v->type == VAR_INT && !xisdigit(*p)) {
				int i;

				for (i = 0; v->map[i].label; i++)
					if (!xstrcasecmp(v->map[i].label, value))
						value = ekg_itoa(v->map[i].value);
			}

			if (v->map && v->type == VAR_MAP && !xisdigit(*p)) {
				int i, k = *(int*)(v->ptr);
				int mode = 0; /* 0 set, 1 add, 2 remove */
				char **args;

				if (*p == '+') {
					mode = 1;
					p++;
				} else if (*p == '-') {
					mode = 2;
					p++;
				}

				if (!mode)
					k = 0;

				args = array_make(p, ",", 0, 1, 0);

				for (i = 0; args[i]; i++) {
					int j, found = 0;

					for (j = 0; v->map[j].label; j++) {
						if (!xstrcasecmp(args[i], v->map[j].label)) {
							found = 1;

							if (mode == 2)
								k &= ~(v->map[j].value);
							if (mode == 1)
								k &= ~(v->map[j].conflicts);
							if (mode == 1 || !mode)
								k |= v->map[j].value;
						}
					}

					if (!found) {
						g_strfreev(args);
						return -2;
					}
				}

				g_strfreev(args);

				value = ekg_itoa(k);
			}

			p = value;
				
			if ((hex = !xstrncasecmp(p, "0x", 2)))
				p += 2;

			while (*p && *p != ' ') {
				if (hex && !xisxdigit(*p))
					return -2;
				
				if (!hex && !xisdigit(*p))
					return -2;
				p++;
			}

			tmp = strtol(value, NULL, 0);

			if (v->map) {
				int i;

				for (i = 0; v->map[i].label; i++) {
					if ((tmp & v->map[i].value) && (tmp & v->map[i].conflicts))
						return -2;
				}
			}

			changed = (*(int*)(v->ptr) != tmp);
			*(int*)(v->ptr) = tmp;

			break;
		}

		case VAR_BOOL:
		{
			int tmp;
		
			if (!value)
				return -2;
		
			if ((tmp = on_off(value)) == -1)
				return -2;

			changed = (*(int*)(v->ptr) != tmp);
			*(int*)(v->ptr) = tmp;

			break;
		}
		case VAR_THEME:
		case VAR_FILE:
		case VAR_DIR:
		case VAR_STR:
		{
			char **tmp = (char**)(v->ptr);

			char *oldval = *tmp;

			if (value) {
				if (*value == 1)
					*tmp = base64_decode(value + 1);
				else
					*tmp = xstrdup(value);
			} else
				*tmp = NULL;
	
			changed = xstrcmp(oldval, *tmp);
			xfree(oldval);
			break;
		}
		default:
			return -1;
	}

	if (v->notify)
		(v->notify)(v->name);

	if (!changed)
		return 1;

	tmpname = xstrdup(v->name);
	query_emit(NULL, "variable-changed", &tmpname);
	xfree(tmpname);
			
	return 0;
}
Exemplo n.º 10
0
/*
 * ekg_getch()
 *
 * czeka na wci¶niêcie klawisza i je¶li wkompilowano obs³ugê pythona,
 * przekazuje informacjê o zdarzeniu do skryptu.
 *
 *  - meta - przedrostek klawisza.
 *
 * @returns:
 *	-2		- ignore that key
 *	ERR		- error
 *	OK		- report a (wide) character
 *	KEY_CODE_YES	- report the pressing of a function key
 *
 */
static int ekg_getch(int meta, unsigned int *ch) {
	int retcode;
#if USE_UNICODE
	retcode = wget_wch(input, ch);
#else
	*ch = wgetch(input);
	retcode = *ch >= KEY_MIN ? KEY_CODE_YES : OK;
#endif

	if (retcode == ERR) return ERR;
	if ((retcode == KEY_CODE_YES) && (*(int *)ch == -1)) return ERR;		/* Esc (delay) no key */

#ifndef HAVE_USABLE_TERMINFO
	/* Debian screen incomplete terminfo workaround */

	if (mouse_initialized == 2 && *ch == 27) { /* escape */
		int tmp;

		if ((tmp = wgetch(input)) != '[')
			ungetch(tmp);
		else if ((tmp = wgetch(input)) != 'M') {
			ungetch(tmp);
			ungetch('[');
		} else
			*ch = KEY_MOUSE;
	}
#endif

	/*
	 * conception is borrowed from Midnight Commander project
	 *    (www.ibiblio.org/mc/)
	 */
#define GET_TIME(tv)	(g_get_current_time(&tv))
#define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \
			 (t2.tv_usec-t1.tv_usec)/1000)
	if (*ch == KEY_MOUSE) {
		int btn, mouse_state = 0, x, y;
		static GTimeVal tv1 = { 0, 0 };
		static GTimeVal tv2;
		static int clicks;
		static int last_btn = 0;

		btn = wgetch (input) - 32;

		if (btn == 3 && last_btn) {
			last_btn -= 32;

			switch (last_btn) {
				case 0: mouse_state = (clicks) ? EKG_BUTTON1_DOUBLE_CLICKED : EKG_BUTTON1_CLICKED;	break;
				case 1: mouse_state = (clicks) ? EKG_BUTTON2_DOUBLE_CLICKED : EKG_BUTTON2_CLICKED;	break;
				case 2: mouse_state = (clicks) ? EKG_BUTTON3_DOUBLE_CLICKED : EKG_BUTTON3_CLICKED;	break;
				case 64: mouse_state = EKG_SCROLLED_UP;							break;
				case 65: mouse_state = EKG_SCROLLED_DOWN;						break;
				default:										break;
			}

			last_btn = 0;
			GET_TIME (tv1);
			clicks = 0;

		} else if (!last_btn) {
			GET_TIME (tv2);
			if (tv1.tv_sec && (DIF_TIME (tv1,tv2) < 250)){
				clicks++;
				clicks %= 3;
			} else
				clicks = 0;

			switch (btn) {
				case 0:
				case 1:
				case 2:
				case 64:
				case 65:
					btn += 32;
					break;
				default:
					btn = 0;
					break;
			}

			last_btn = btn;
		} else {
			switch (btn) {
				case 64:
					mouse_state = EKG_SCROLLED_UP;
					break;
				case 65:
					mouse_state = EKG_SCROLLED_DOWN;
					break;
			}
		}

		/* 33 based */
		x = wgetch(input) - 32;
		y = wgetch(input) - 32;

		/* XXX query_emit UI_MOUSE ??? */
		if (mouse_state)
			ncurses_mouse_clicked_handler(x, y, mouse_state);

	}
#undef GET_TIME
#undef DIF_TIME
	if (query_emit(NULL, "ui-keypress", ch) == -1)
		return -2; /* -2 - ignore that key */

	return retcode;
}