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, " \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, " ");
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