1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
15  *
16  *  Copyright (C) 2006-2016 XNeur Team
17  *
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <X11/XKBlib.h>
25 
26 #include <pthread.h>
27 #include <sys/stat.h>
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <time.h>
34 #include <assert.h>
35 
36 #include "xnconfig.h"
37 #include "xnconfig_files.h"
38 
39 #include "event.h"
40 #include "window.h"
41 #include "keymap.h"
42 #include "utils.h"
43 
44 #include "types.h"
45 #include "text.h"
46 #include "conversion.h"
47 #include "log.h"
48 #include "mail.h"
49 #include "archiver.h"
50 
51 #include "buffer.h"
52 
53 #define INIT_STRING_LENGTH 64
54 
55 static const int keyboard_groups[]	= {0x00000000, 0x00002000, 0x00004000, 0x00006000};
56 
57 extern struct _xneur_config *xconfig;
58 
59 Window last_log_window = 0;
60 time_t last_log_time = 0;
61 
62 // Private
set_new_size(struct _buffer * p,int new_size)63 static void set_new_size(struct _buffer *p, int new_size)
64 {
65 	char *tmp_char = (char *) realloc(p->content, new_size * sizeof(char));
66 	if (tmp_char == NULL)
67 		return;
68 	p->content = tmp_char;
69 	KeyCode *tmp_kc = (KeyCode *) realloc(p->keycode, new_size * sizeof(KeyCode));
70 	if (tmp_kc == NULL)
71 		return;
72 	p->keycode = tmp_kc;
73 	int *tmp_int = (int *) realloc(p->keycode_modifiers, new_size * sizeof(int));
74 	if (tmp_int == NULL)
75 		return;
76 	p->keycode_modifiers = tmp_int;
77 	p->cur_size		= new_size;
78 }
79 
buffer_set_lang_mask(struct _buffer * p,int lang)80 static void buffer_set_lang_mask(struct _buffer *p, int lang)
81 {
82 	int keycode_mod		= get_keycode_mod(lang);
83 	int languages_mask	= get_languages_mask();
84 
85 	// Set new language bit
86 	for (int i = 0; i < p->cur_pos; i++)
87 	{
88 		p->keycode_modifiers[i] = p->keycode_modifiers[i] & (~languages_mask);
89 		p->keycode_modifiers[i] = p->keycode_modifiers[i] | keycode_mod;
90 	}
91 }
92 
buffer_set_uncaps_mask(struct _buffer * p)93 static void buffer_set_uncaps_mask(struct _buffer *p)
94 {
95 	// Set uncaps bit
96 	for (int i = 0; i < p->cur_pos; i++)
97 		p->keycode_modifiers[i] = p->keycode_modifiers[i] & (~LockMask);
98 }
99 
buffer_set_caps_mask(struct _buffer * p)100 static void buffer_set_caps_mask(struct _buffer *p)
101 {
102 	// Set uncaps bit
103 	for (int i = 0; i < p->cur_pos; i++)
104 		p->keycode_modifiers[i] = p->keycode_modifiers[i] | (LockMask);
105 }
106 
buffer_mail_and_archive(char * file_path_name)107 static void buffer_mail_and_archive(char *file_path_name)
108 {
109 	if (file_path_name == NULL)
110 		return;
111 
112 	time_t curtime = time(NULL);
113 	struct tm *loctime = localtime(&curtime);
114 	if (loctime == NULL)
115 		return;
116 
117 	char *date = malloc(256 * sizeof(char));
118 	if (date == NULL)
119 		return;
120 	char *time = malloc(256 * sizeof(char));
121 	if (time == NULL)
122 	{
123 		free(date);
124 		return;
125 	}
126 	strftime(date, 256, "%x", loctime);
127 	strftime(time, 256, "%X", loctime);
128 
129 	int len = strlen(file_path_name) + strlen(date) + strlen(time) + 4;
130 	char *arch_file_path_name = malloc(len * sizeof (char));
131 	if (arch_file_path_name == NULL)
132 	{
133 		free(date);
134 		free(time);
135 		return;
136 	}
137 	snprintf(arch_file_path_name, len, "%s %s %s", file_path_name, date, time);
138 
139 	if (rename(file_path_name, arch_file_path_name) == 0)
140 	{
141 		// Compress the file
142 		char *gz_arch_file_path_name = malloc(len+3 * sizeof (char));
143 		if (gz_arch_file_path_name == NULL)
144 		{
145 			free(date);
146 			free(time);
147 			free(arch_file_path_name);
148 			return;
149 		}
150 		snprintf(gz_arch_file_path_name, len+3, "%s%s", arch_file_path_name, ".gz");
151 
152 		FILE *source = fopen(arch_file_path_name, "r");
153 		FILE *dest = fopen(gz_arch_file_path_name, "w");
154 		if ((source != NULL) && (dest != NULL))
155 			file_compress (source, dest);
156 		if (source != NULL)
157 			fclose (source);
158 		if (dest != NULL)
159 			fclose (dest);
160 
161 		// Remove uncompressed file
162 		if (remove(arch_file_path_name) == -1)
163 		{
164 			free(file_path_name);
165 			free(time);
166 			free(date);
167 			free(arch_file_path_name);
168 			free(gz_arch_file_path_name);
169 			return;
170 		}
171 
172 		log_message(DEBUG, _("Compressed old log file to %s"), gz_arch_file_path_name);
173 
174 		// Send to e-mail
175 		send_mail_with_attach(gz_arch_file_path_name, xconfig->host_keyboard_log, xconfig->port_keyboard_log, xconfig->mail_keyboard_log);
176 		log_message(DEBUG, _("Sended log to e-mail %s via %s:%d host"), xconfig->mail_keyboard_log, xconfig->host_keyboard_log, xconfig->port_keyboard_log);
177 
178 		free(gz_arch_file_path_name);
179 	}
180 	else
181 		log_message (ERROR, _("Error rename file \"%s\" to \"%s\""), file_path_name, arch_file_path_name);
182 
183 	free(file_path_name);
184 	free(time);
185 	free(date);
186 	free(arch_file_path_name);
187 }
188 
buffer_save(struct _buffer * p,char * file_name,Window window)189 static void buffer_save(struct _buffer *p, char *file_name, Window window)
190 {
191 #ifdef WITH_KEYLOGGER
192 	if (!xconfig->save_keyboard_log || p->cur_pos == 0 || file_name == NULL)
193 #endif
194 		return;
195 
196 	if (strlen (p->content) < 4)
197 		return;
198 
199 	int save = FALSE;
200 	for (int i = 0; i < p->cur_pos; i++)
201 		if (isgraph (p->content[i]))
202 		{
203 			save = TRUE;
204 			break;
205 		}
206 	if (!save)
207 		return;
208 
209 	char *file_path_name = get_home_file_path_name(NULL, file_name);
210 	if (file_path_name == NULL)
211 		return;
212 
213 	time_t curtime = time(NULL);
214 	struct tm *loctime = localtime(&curtime);
215 	if (loctime == NULL)
216 	{
217 		free(file_path_name);
218 		return;
219 	}
220 
221 	char *buffer = malloc(256 * sizeof(char));
222 	if (buffer == NULL)
223 	{
224 		free(file_path_name);
225 		return;
226 	}
227 
228 	// Check existing log file
229 	FILE *stream = fopen(file_path_name, "r");
230 	if (stream == NULL) // File not exist
231 	{
232 		stream = fopen(file_path_name, "a");
233 		if (stream == NULL)
234 		{
235 			free(file_path_name);
236 			free(buffer);
237 			return;
238 		}
239 		fprintf(stream, "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"><title>X Neural Switcher Log</title></head><body>\n");
240 		fprintf(stream, "<ul></ul></body></html>\n");
241 	}
242 	else
243 	{
244 		// Check file size
245 		struct stat sb;
246 		if (stat(file_path_name, &sb) == 0)
247 		{
248 			if (sb.st_size > xconfig->size_keyboard_log)
249 			{
250 				pthread_attr_t mail_and_archive_thread_attr;
251 				pthread_attr_init(&mail_and_archive_thread_attr);
252 				pthread_attr_setdetachstate(&mail_and_archive_thread_attr, PTHREAD_CREATE_DETACHED);
253 
254 				pthread_t mail_and_archive_thread;
255 				char *thread_file = strdup (file_path_name);
256 				pthread_create(&mail_and_archive_thread, &mail_and_archive_thread_attr, (void*) &buffer_mail_and_archive, thread_file);
257 
258 				pthread_attr_destroy(&mail_and_archive_thread_attr);
259 			}
260 		}
261 	}
262 	//
263 	fclose (stream);
264 
265 
266 	stream = fopen(file_path_name, "r+");
267 	free(file_path_name);
268 	if (stream == NULL)
269 	{
270 		free(buffer);
271 		return;
272 	}
273 
274 	if (fseek(stream, -20, SEEK_END) == -1)
275 	{
276 		free(buffer);
277 		fclose(stream);
278 		return;
279 	}
280 
281 	bzero(buffer, 256 * sizeof(char));
282 	strftime(buffer, 256, "%x", loctime);
283 
284 	if (window != last_log_window)
285 	{
286 		last_log_window = window;
287 		last_log_time = 0;
288 		char *app_name = get_wm_class_name(window);
289 		fprintf(stream, "</ul>\n<br><font color=\"#FF0000\"><b>%s <font size=\"2\">[%s]</font></font></b><br><ul>\n", app_name, buffer);
290 		if (app_name != NULL)
291 			free(app_name);
292 	}
293 
294 	if (difftime(curtime, last_log_time) > 300)
295 	{
296 		last_log_time = curtime;
297 		bzero(buffer, 256 * sizeof(char));
298 		strftime(buffer, 256, "%X", loctime);
299 		fprintf(stream, "</ul><ul>\n<font color=\"#0000FF\" size=\"2\">(%s): </font>", buffer);
300 	}
301 	if (buffer != NULL)
302 		free(buffer);
303 
304 	for (int i = 0; i < p->cur_pos; i++)
305 	{
306 		if (p->keycode[i] == 36)			// Return
307 		{
308 			fprintf(stream, "<br>\n");
309 			continue;
310 		}
311 		if (p->keycode[i] == 23)			// Tab
312 		{
313 			fprintf(stream, "&nbsp;&nbsp;&nbsp;&nbsp;\t");
314 			continue;
315 		}
316 
317 		char *symbol = p->keymap->keycode_to_symbol(p->keymap, p->keycode[i], -1, p->keycode_modifiers[i]);
318 		if (symbol == NULL)
319 		{
320 			fprintf(stream, "<?>");
321 			continue;
322 		}
323 
324 		if (symbol[0] == ' ')
325 			fprintf(stream, "&nbsp;");
326 		else
327 			fprintf(stream, "%s", symbol);
328 
329 		free(symbol);
330 	}
331 
332 	fprintf(stream, "\n</body></html>\n");
333 	fclose(stream);
334 }
335 
buffer_clear(struct _buffer * p)336 static void buffer_clear(struct _buffer *p)
337 {
338 	for (int i = 0; i < p->cur_pos; i++)
339 	{
340 		p->keycode[i] = 0;
341 		p->keycode_modifiers[i] = 0;
342 	}
343 
344 	p->cur_pos = 0;
345 	p->content[0] = NULLSYM;
346 
347 	for (int i=0; i<p->handle->total_languages; i++)
348 	{
349 		char *tmp = realloc(p->i18n_content[i].content, sizeof(char));
350 		if (tmp != NULL)
351 			p->i18n_content[i].content = tmp;
352 		p->i18n_content[i].content[0] = NULLSYM;
353 		tmp = realloc(p->i18n_content[i].content_unchanged, sizeof(char));
354 		if (tmp != NULL)
355 			p->i18n_content[i].content_unchanged = tmp;
356 		p->i18n_content[i].content_unchanged[0] = NULLSYM;
357 	}
358 }
359 
buffer_is_space_last(struct _buffer * p)360 static int buffer_is_space_last(struct _buffer *p)
361 {
362 	if (p->cur_pos <= 0)
363 		return FALSE;
364 
365 	if (isspace(p->content[p->cur_pos - 1]))
366 		return TRUE;
367 
368 	return FALSE;
369 }
370 
buffer_set_i18n_content(struct _buffer * p)371 static void buffer_set_i18n_content(struct _buffer *p)
372 {
373 	// i18n_content
374 	/*for (int i = 0; i < p->handle->total_languages; i++)
375 	{
376 		p->i18n_content[i].content = (char *) realloc(p->i18n_content[i].content, 1);
377 		p->i18n_content[i].content[0] = NULLSYM;
378 		p->i18n_content[i].symbol_len = (int *) realloc(p->i18n_content[i].symbol_len, 1);
379 		p->i18n_content[i].content_unchanged = (char *) realloc(p->i18n_content[i].content_unchanged, 1);
380 		p->i18n_content[i].content_unchanged[0] = NULLSYM;
381 		p->i18n_content[i].symbol_len_unchanged = (int *) realloc(p->i18n_content[i].symbol_len_unchanged, 1);
382 	}*/
383 
384 	int languages_mask = get_languages_mask();
385 	for (int k = 0; k < p->cur_size-1; k++)
386 	{
387 		int modifier = p->keycode_modifiers[k] & (~languages_mask);
388 
389 		for (int i = 0; i < p->handle->total_languages; i++)
390 		{
391 
392 			char *symbol = p->keymap->keycode_to_symbol(p->keymap, p->keycode[k], i, modifier & (~ShiftMask));
393 			if (symbol == NULL)
394 				continue;
395 
396 			char *symbol_unchanged = p->keymap->keycode_to_symbol(p->keymap, p->keycode[k], i, modifier);
397 			if (symbol_unchanged == NULL)
398 			{
399 				free(symbol);
400 				continue;
401 			}
402 
403 			char *tmp = (char *) realloc(p->i18n_content[i].content, (strlen(p->i18n_content[i].content) + strlen(symbol) + 1) * sizeof(char));
404 			assert(tmp != NULL);
405 			p->i18n_content[i].content = tmp;
406 			p->i18n_content[i].content = strcat(p->i18n_content[i].content, symbol);
407 
408 			tmp = (char *) realloc(p->i18n_content[i].content_unchanged, (strlen(p->i18n_content[i].content_unchanged) + strlen(symbol_unchanged) + 1) * sizeof(char));
409 			assert(tmp != NULL);
410 			p->i18n_content[i].content_unchanged = tmp;
411 			p->i18n_content[i].content_unchanged = strcat(p->i18n_content[i].content_unchanged, symbol_unchanged);
412 
413 			tmp = (char *)realloc(p->i18n_content[i].symbol_len, (k + 1) * sizeof(int));
414 			assert(tmp != NULL);
415 			p->i18n_content[i].symbol_len = (int *) tmp;
416 			p->i18n_content[i].symbol_len[k] = strlen(symbol);
417 
418 			tmp = (char *)realloc(p->i18n_content[i].symbol_len_unchanged, (k + 1) * sizeof(int));
419 			assert(tmp != NULL);
420 			p->i18n_content[i].symbol_len_unchanged = (int *)tmp;
421 			p->i18n_content[i].symbol_len_unchanged[k] = strlen(symbol_unchanged);
422 
423 			free(symbol);
424 			free(symbol_unchanged);
425 		}
426 	}
427 }
428 
buffer_set_content(struct _buffer * p,const char * new_content)429 static void buffer_set_content(struct _buffer *p, const char *new_content)
430 {
431 	if (new_content == NULL)
432 		return;
433 	char *content = strdup(new_content);
434 	if (content == NULL)
435 		return;
436 
437 	p->clear(p);
438 
439 	p->cur_pos = strlen(content);
440 	if (p->cur_pos >= p->cur_size)
441 		set_new_size(p, p->cur_pos + 1);
442 
443 	p->content[p->cur_pos] = NULLSYM;
444 	if (!p->cur_pos)
445 	{
446 		free(content);
447 		return;
448 	}
449 
450 	memcpy(p->content, content, p->cur_pos);
451 	free(content);
452 
453 	p->keymap->convert_text_to_ascii(p->keymap, p->content, p->keycode, p->keycode_modifiers);
454 
455 	p->cur_pos = strlen(p->content);
456 	set_new_size(p, p->cur_pos + 1);
457 
458 	buffer_set_i18n_content(p);
459 }
460 
buffer_change_case(struct _buffer * p)461 static void buffer_change_case(struct _buffer *p)
462 {
463 	char *symbol = (char *) malloc((256 + 1) * sizeof(char));
464 
465 	Display *display = XOpenDisplay(NULL);
466 	XEvent event;
467 	event.type		= KeyPress;
468 	event.xkey.type		= KeyPress;
469 	event.xkey.root		= RootWindow(display, DefaultScreen(display));
470 	event.xkey.subwindow	= None;
471 	event.xkey.same_screen	= True;
472 	event.xkey.display	= display;
473 	event.xkey.state	= 0;
474 	event.xkey.keycode	= XKeysymToKeycode(display, XK_space);
475 	event.xkey.time		= CurrentTime;
476 
477 	for (int i = 0; i < p->cur_pos; i++)
478 	{
479 		event.xkey.keycode	= p->keycode[i];
480 		event.xkey.state	= p->keycode_modifiers[i];
481 
482 		int nbytes = XLookupString((XKeyEvent *) &event, symbol, 256, NULL, NULL);
483 		if (nbytes <= 0)
484 			continue;
485 		if (symbol == NULL)
486 			continue;
487 
488 		symbol[nbytes] = NULLSYM;
489 
490 		if (ispunct(symbol[0]) || isdigit(symbol[0]))
491 			continue;
492 
493 		if (p->keycode_modifiers[i] & ShiftMask)
494 			p->keycode_modifiers[i] = (p->keycode_modifiers[i] & ~ShiftMask);
495 		else
496 			p->keycode_modifiers[i] = (p->keycode_modifiers[i] | ShiftMask);
497 	}
498 
499 	if (symbol != NULL)
500 		free(symbol);
501 	XCloseDisplay(display);
502 }
503 
buffer_rotate_layout(struct _buffer * p)504 static void buffer_rotate_layout(struct _buffer *p)
505 {
506 	int languages_mask = get_languages_mask();
507 
508 	for (int i = 0; i < p->cur_pos; i++)
509 	{
510 		// Get current lang. modifier
511 		int km = p->keycode_modifiers[i] & (~languages_mask);
512 		for (int lang = 0; lang < p->handle->total_languages; lang++)
513 		{
514 			if (p->keycode_modifiers[i] == (get_keycode_mod(lang) | km))
515 			{
516 				lang++;
517 				if (lang == p->handle->total_languages)
518 					lang = 0;
519 				int keycode_mod	= get_keycode_mod(lang);
520 				p->keycode_modifiers[i] = p->keycode_modifiers[i] & (~languages_mask);
521 				p->keycode_modifiers[i] = p->keycode_modifiers[i] | keycode_mod;
522 				break;
523 			}
524 		}
525 	}
526 }
527 
buffer_add_symbol(struct _buffer * p,char sym,KeyCode keycode,int modifier)528 static void buffer_add_symbol(struct _buffer *p, char sym, KeyCode keycode, int modifier)
529 {
530 	if (p->cur_pos == p->cur_size - 1)
531 		set_new_size(p, p->cur_size * 2);
532 
533 	if (p->content == NULL || p->keycode == NULL || p->keycode_modifiers == NULL)
534 		return;
535 
536 	p->content[p->cur_pos] = sym;
537 	p->keycode[p->cur_pos] = keycode;
538 	p->keycode_modifiers[p->cur_pos] = modifier;
539 
540 	// i18n_content
541 	int languages_mask = get_languages_mask();
542 	modifier = modifier & (~languages_mask);
543 
544 	for (int i = 0; i < p->handle->total_languages; i++)
545 	{
546 		char *symbol = p->keymap->keycode_to_symbol(p->keymap, keycode, i, modifier & (~ShiftMask));
547 		if (symbol == NULL)
548 			continue;
549 
550 		char *symbol_unchanged = p->keymap->keycode_to_symbol(p->keymap, keycode, i, modifier);
551 		if (symbol_unchanged == NULL)
552 		{
553 			free(symbol);
554 			continue;
555 		}
556 
557 		//log_message (ERROR, _("'%c' - '%c' - '%c'"), sym, symbol, symbol_unchanged);
558 		char *tmp = realloc(p->i18n_content[i].content, (strlen(p->i18n_content[i].content) + strlen(symbol) + 1) * sizeof(char));
559 		assert(tmp != NULL);
560 		p->i18n_content[i].content = tmp;
561 		p->i18n_content[i].content = strcat(p->i18n_content[i].content, symbol);
562 
563 		tmp = realloc(p->i18n_content[i].content_unchanged, (strlen(p->i18n_content[i].content_unchanged) + strlen(symbol_unchanged) + 1) * sizeof(char));
564 		assert(tmp != NULL);
565 		p->i18n_content[i].content_unchanged = tmp;
566 		p->i18n_content[i].content_unchanged = strcat(p->i18n_content[i].content_unchanged, symbol_unchanged);
567 
568 		tmp = realloc(p->i18n_content[i].symbol_len, (p->cur_pos + 1) * sizeof(int));
569 		assert(tmp != NULL);
570 		p->i18n_content[i].symbol_len = (int *)tmp;
571 		p->i18n_content[i].symbol_len[p->cur_pos] = strlen(symbol);
572 
573 		tmp = realloc(p->i18n_content[i].symbol_len_unchanged, (p->cur_pos + 1) * sizeof(int));
574 		assert(tmp != NULL);
575 		p->i18n_content[i].symbol_len_unchanged = (int *)tmp;
576 		p->i18n_content[i].symbol_len_unchanged[p->cur_pos] = strlen(symbol_unchanged);
577 
578 		free(symbol);
579 		free(symbol_unchanged);
580 	}
581 
582 	p->cur_pos++;
583 	p->content[p->cur_pos] = NULLSYM;
584 }
585 
buffer_del_symbol(struct _buffer * p)586 static void buffer_del_symbol(struct _buffer *p)
587 {
588 	if (p->cur_pos == 0)
589 		return;
590 
591 	p->cur_pos--;
592 	p->content[p->cur_pos] = NULLSYM;
593 
594 	for (int i = 0; i < p->handle->total_languages; i++)
595 	{
596 		p->i18n_content[i].content[strlen(p->i18n_content[i].content) - p->i18n_content[i].symbol_len[p->cur_pos]] = NULLSYM;
597 		p->i18n_content[i].content_unchanged[strlen(p->i18n_content[i].content_unchanged) - p->i18n_content[i].symbol_len_unchanged[p->cur_pos]] = NULLSYM;
598 	}
599 }
600 
buffer_get_utf_string(struct _buffer * p)601 static char *buffer_get_utf_string(struct _buffer *p)
602 {
603 	char *symbol = (char *) malloc((256 + 1) * sizeof(char));
604 
605 	char *utf_string = (char *) malloc(1 * sizeof(char));
606 	utf_string[0] = NULLSYM;
607 
608 	Display *display = XOpenDisplay(NULL);
609 	XEvent event;
610 	event.type		= KeyPress;
611 	event.xkey.type		= KeyPress;
612 	event.xkey.root		= RootWindow(display, DefaultScreen(display));
613 	event.xkey.subwindow	= None;
614 	event.xkey.same_screen	= True;
615 	event.xkey.display	= display;
616 	event.xkey.state	= 0;
617 	event.xkey.keycode	= XKeysymToKeycode(display, XK_space);
618 	event.xkey.time		= CurrentTime;
619 
620 	for (int i = 0; i < p->cur_pos; i++)
621 	{
622 		event.xkey.keycode	= p->keycode[i];
623 		event.xkey.state	= p->keycode_modifiers[i];
624 
625 		int nbytes = XLookupString((XKeyEvent *) &event, symbol, 256, NULL, NULL);
626 		if (nbytes <= 0)
627 			continue;
628 		if (symbol == NULL)
629 			continue;
630 
631 		symbol[nbytes] = NULLSYM;
632 
633 		char *tmp = realloc(utf_string, strlen(utf_string) * sizeof(char) + nbytes + 1);
634 		if (tmp != NULL)
635 		{
636 			utf_string = tmp;
637 			strcat(utf_string, symbol);
638 			//free(tmp);
639 		}
640 	}
641 
642 	if (symbol != NULL)
643 		free(symbol);
644 	XCloseDisplay(display);
645 
646 	return utf_string;
647 }
648 
buffer_get_utf_string_on_kbd_group(struct _buffer * p,int group)649 static char *buffer_get_utf_string_on_kbd_group(struct _buffer *p, int group)
650 {
651 	char *utf_string = (char *) malloc(1 * sizeof(char));
652 	utf_string[0] = NULLSYM;
653 
654 	for (int i = 0; i < p->cur_pos; i++)
655 	{
656 		int state = p->keycode_modifiers[i];
657 		for (int j = 0; j < p->handle->total_languages; j++)
658 		{
659 			state = state & (~keyboard_groups[j]);
660 		}
661 		char *symbol = p->keymap->keycode_to_symbol(p->keymap, p->keycode[i], group, state);
662 		if (symbol != NULL)
663 		{
664 			char *tmp = realloc(utf_string, strlen(utf_string) * sizeof(char) + strlen(symbol) + 1);
665 			if (tmp != NULL)
666 			{
667 				utf_string = tmp;
668 				strcat(utf_string, symbol);
669 			}
670 			free(symbol);
671 		}
672 	}
673 
674 	return utf_string;
675 }
676 
buffer_save_and_clear(struct _buffer * p,Window window)677 static void buffer_save_and_clear(struct _buffer *p, Window window)
678 {
679 	p->save(p, LOG_NAME, window);
680 	p->clear(p);
681 }
682 
buffer_set_offset(struct _buffer * p,int offset)683 static void buffer_set_offset(struct _buffer *p, int offset)
684 {
685 	// Shift fields to point to begin of word
686 	p->content		+= offset;
687 	p->keycode		+= offset;
688 	p->keycode_modifiers	+= offset;
689 	p->cur_pos		-= offset;
690 }
691 
buffer_unset_offset(struct _buffer * p,int offset)692 static void buffer_unset_offset(struct _buffer *p, int offset)
693 {
694 	// Revert fields back
695 	p->content		-= offset;
696 	p->keycode		-= offset;
697 	p->keycode_modifiers	-= offset;
698 	p->cur_pos		+= offset;
699 }
700 
buffer_get_last_word_offset(struct _buffer * p,const char * string,int string_len)701 int buffer_get_last_word_offset(struct _buffer *p, const char *string, int string_len)
702 {
703 	// Initial delimeters string concatenation
704 	if (strlen(xconfig->delimeters_string) == 0)
705 	{
706 		for (int i = 0; i < xconfig->delimeters_count; i++)
707 		{
708 			char *symbol = p->keymap->keycode_to_symbol(p->keymap, XKeysymToKeycode(p->keymap->display, xconfig->delimeters[i]), -1, 0);
709 			if (strlen(symbol) == 1)
710 				strcat(xconfig->delimeters_string, symbol);
711 			free(symbol);
712 		}
713 		//log_message (DEBUG,"'%s'", xconfig->delimeters_string);
714 	}
715 	// End of initial delimeters string concatenation
716 
717 	int len = string_len;
718 	while (len != 0 && ((isspace(string[len - 1]) || (strchr(xconfig->delimeters_string, string[len - 1]) != NULL))))
719 		len--;
720 
721 	/*int is_delim;
722 	do
723 	{
724 		log_message (DEBUG, "code 0x%x", p->keycode[len - 1]);
725 		is_delim = FALSE;
726 		for (int i = 0; i < xconfig->delimeters_count; i++)
727 		{
728 			if (xconfig->delimeters[i] == p->keycode[len - 1])
729 			{
730 				is_delim = TRUE;
731 			}
732 		}
733 		if (is_delim)
734 			len--;
735 	} while ((len != 0) && (is_delim));*/
736 
737 	if (len == 0)
738 		return string_len;
739 
740 	while (len != 0 && !isspace(string[len - 1]) && (strchr(xconfig->delimeters_string, string[len - 1]) == NULL))
741 		len--;
742 
743 	/*int is_symbol;
744 	do
745 	{
746 		is_symbol = TRUE;
747 		for (int i = 0; i < xconfig->delimeters_count; i++)
748 		{
749 			if (xconfig->delimeters[i] == p->keycode[len - 1])
750 				is_symbol = FALSE;
751 		}
752 		if (is_symbol)
753 			len--;
754 	} while ((len != 0) && (is_symbol));
755 	log_message (DEBUG, "len2 %d", len);*/
756 
757 	return len;
758 }
759 
buffer_get_last_word(struct _buffer * p,char * string)760 char* buffer_get_last_word(struct _buffer *p, char *string)
761 {
762 	int len = strlen(string);
763 
764 	int offset = buffer_get_last_word_offset(p, string, len);
765 	if (offset == -1)
766 		return NULL;
767 
768 	return string + offset;
769 }
770 
buffer_uninit(struct _buffer * p)771 static void buffer_uninit(struct _buffer *p)
772 {
773 	if (p == NULL)
774 		return;
775 
776 	if (p->keycode_modifiers != NULL)
777 		free(p->keycode_modifiers);
778 	if (p->keycode != NULL)
779 		free(p->keycode);
780 	if (p->content != NULL)
781 		free(p->content);
782 
783 	if (p->i18n_content != NULL)
784 	{
785 		for (int i = 0; i < p->handle->total_languages; i++)
786 		{
787 			if (p->i18n_content[i].content != NULL)
788 				free(p->i18n_content[i].content);
789 			if (p->i18n_content[i].symbol_len != NULL)
790 				free(p->i18n_content[i].symbol_len);
791 			if (p->i18n_content[i].content_unchanged != NULL)
792 				free(p->i18n_content[i].content_unchanged);
793 			if (p->i18n_content[i].symbol_len_unchanged != NULL)
794 				free(p->i18n_content[i].symbol_len_unchanged);
795 		}
796 
797 		free(p->i18n_content);
798 	}
799 	if (p != NULL)
800 		free(p);
801 
802 	log_message(DEBUG, _("String is freed"));
803 }
804 
buffer_init(struct _xneur_handle * handle,struct _keymap * keymap)805 struct _buffer* buffer_init(struct _xneur_handle *handle, struct _keymap *keymap)
806 {
807 	struct _buffer *p = (struct _buffer *) malloc(sizeof(struct _buffer));
808 	bzero(p, sizeof(struct _buffer));
809 
810 	p->handle = handle;
811 
812 	p->keymap = keymap;
813 
814 	p->cur_size		= INIT_STRING_LENGTH;
815 
816 	p->content		= (char *) malloc(p->cur_size * sizeof(char));
817 	p->keycode		= (KeyCode *) malloc(p->cur_size * sizeof(KeyCode));
818 	p->keycode_modifiers	= (int *) malloc(p->cur_size * sizeof(int));
819 
820 	bzero(p->content, p->cur_size * sizeof(char));
821 	bzero(p->keycode, p->cur_size * sizeof(KeyCode));
822 	bzero(p->keycode_modifiers, p->cur_size * sizeof(int));
823 
824 	p->i18n_content = (struct _buffer_content *) malloc((handle->total_languages) * sizeof(struct _buffer_content));
825 	for (int i=0; i<p->handle->total_languages; i++)
826 	{
827 		p->i18n_content[i].content = malloc(sizeof(char));
828 		p->i18n_content[i].content[0] = NULLSYM;
829 		p->i18n_content[i].symbol_len = malloc(sizeof(int));
830 		p->i18n_content[i].content_unchanged = malloc(sizeof(char));
831 		p->i18n_content[i].content_unchanged[0] = NULLSYM;
832 		p->i18n_content[i].symbol_len_unchanged = malloc(sizeof(int));
833 	}
834 
835 	// Functions mapping
836 	p->clear		= buffer_clear;
837 	p->save			= buffer_save;
838 	p->save_and_clear	= buffer_save_and_clear;
839 	p->is_space_last	= buffer_is_space_last;
840 	p->set_lang_mask	= buffer_set_lang_mask;
841 	p->set_uncaps_mask	= buffer_set_uncaps_mask;
842 	p->set_caps_mask	= buffer_set_caps_mask;
843 	p->set_content		= buffer_set_content;
844 	p->change_case		= buffer_change_case;
845 	p->rotate_layout	= buffer_rotate_layout;
846 	p->add_symbol		= buffer_add_symbol;
847 	p->del_symbol		= buffer_del_symbol;
848 	p->get_utf_string	= buffer_get_utf_string;
849 	p->get_utf_string_on_kbd_group	= buffer_get_utf_string_on_kbd_group;
850 	p->set_offset		= buffer_set_offset;
851 	p->unset_offset		= buffer_unset_offset;
852 	p->get_last_word	= buffer_get_last_word;
853 	p->get_last_word_offset	= buffer_get_last_word_offset;
854 	p->uninit		= buffer_uninit;
855 
856 	return p;
857 }
858