PageRenderTime 23ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/gtkterm-0.99.6/src/macros.c

#
C | 533 lines | 417 code | 90 blank | 26 comment | 38 complexity | 3a567735e6e398c790c4b58fccf4d10d MD5 | raw file
Possible License(s): GPL-2.0
  1. /***********************************************************************/
  2. /* macros.c */
  3. /* -------- */
  4. /* GTKTerm Software */
  5. /* (c) Julien Schmitt */
  6. /* julien@jls-info.com */
  7. /* */
  8. /* ------------------------------------------------------------------- */
  9. /* */
  10. /* Purpose */
  11. /* Functions for the management of the macros */
  12. /* */
  13. /* ChangeLog */
  14. /* - 0.99.2 : Internationalization */
  15. /* - 0.99.0 : file creation by Julien */
  16. /* */
  17. /***********************************************************************/
  18. #include <gtk/gtk.h>
  19. #include <gdk/gdk.h>
  20. #include <gdk/gdkkeysyms.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include "gettext.h"
  25. #include "widgets.h"
  26. #include "macros.h"
  27. enum
  28. {
  29. COLUMN_SHORTCUT,
  30. COLUMN_ACTION,
  31. NUM_COLUMNS
  32. };
  33. macro_t *macros = NULL;
  34. static GtkWidget *window = NULL;
  35. macro_t *get_shortcuts(gint *size)
  36. {
  37. gint i = 0;
  38. if(macros != NULL)
  39. {
  40. while(macros[i].shortcut != NULL)
  41. i++;
  42. }
  43. *size = i;
  44. return macros;
  45. }
  46. static void shortcut_callback(gpointer *number)
  47. {
  48. gchar *string;
  49. gchar *str;
  50. gint i, length;
  51. guchar a;
  52. guint val_read;
  53. string = macros[(long)number].action;
  54. length = strlen(string);
  55. for(i = 0; i < length; i++)
  56. {
  57. if(string[i] == '\\')
  58. {
  59. if(g_unichar_isdigit((gunichar)string[i + 1]))
  60. {
  61. if((string[i + 1] == '0') && (string[i + 2] != 0))
  62. {
  63. if(g_unichar_isxdigit((gunichar)string[i + 3]))
  64. {
  65. str = &string[i + 2];
  66. i += 3;
  67. }
  68. else
  69. {
  70. str = &string[i + 1];
  71. if(g_unichar_isxdigit((gunichar)string[i + 2]))
  72. i += 2;
  73. else
  74. i++;
  75. }
  76. }
  77. else
  78. {
  79. str = &string[i + 1];
  80. if(g_unichar_isxdigit((gunichar)string[i + 2]))
  81. i += 2;
  82. else
  83. i++;
  84. }
  85. if(sscanf(str, "%02X", &val_read) == 1)
  86. a = (guchar)val_read;
  87. else
  88. a = '\\';
  89. }
  90. else
  91. {
  92. switch(string[i + 1])
  93. {
  94. case 'a':
  95. a = '\a';
  96. break;
  97. case 'b':
  98. a = '\b';
  99. break;
  100. case 't':
  101. a = '\t';
  102. break;
  103. case 'n':
  104. a = '\n';
  105. break;
  106. case 'v':
  107. a = '\v';
  108. break;
  109. case 'f':
  110. a = '\f';
  111. break;
  112. case 'r':
  113. a = '\r';
  114. break;
  115. case '\\':
  116. a = '\\';
  117. break;
  118. default:
  119. a = '\\';
  120. i--;
  121. break;
  122. }
  123. i++;
  124. }
  125. send_serial(&a, 1);
  126. }
  127. else
  128. {
  129. send_serial(&string[i], 1);
  130. }
  131. }
  132. str = g_strdup_printf(_("Macro \"%s\" sent !"), macros[(long)number].shortcut);
  133. Put_temp_message(str, 800);
  134. g_free(str);
  135. }
  136. void create_shortcuts(macro_t *macro, gint size)
  137. {
  138. macros = g_malloc((size + 1) * sizeof(macro_t));
  139. if(macros != NULL)
  140. {
  141. memcpy(macros, macro, size * sizeof(macro_t));
  142. macros[size].shortcut = NULL;
  143. macros[size].action = NULL;
  144. }
  145. else
  146. perror("malloc");
  147. }
  148. void add_shortcuts(void)
  149. {
  150. long i = 0;
  151. guint acc_key;
  152. GdkModifierType mod;
  153. if(macros == NULL)
  154. return;
  155. while(macros[i].shortcut != NULL)
  156. {
  157. macros[i].closure = g_cclosure_new_swap(G_CALLBACK(shortcut_callback), (gpointer)i, NULL);
  158. gtk_accelerator_parse(macros[i].shortcut, &acc_key, &mod);
  159. if(acc_key != 0)
  160. gtk_accel_group_connect(shortcuts, acc_key, mod, GTK_ACCEL_MASK, macros[i].closure);
  161. i++;
  162. }
  163. }
  164. static void macros_destroy(void)
  165. {
  166. gint i = 0;
  167. if(macros == NULL)
  168. return;
  169. while(macros[i].shortcut != NULL)
  170. {
  171. g_free(macros[i].shortcut);
  172. g_free(macros[i].action);
  173. /*
  174. g_closure_unref(macros[i].closure);
  175. */
  176. i++;
  177. }
  178. g_free(macros);
  179. macros = NULL;
  180. }
  181. void remove_shortcuts(void)
  182. {
  183. gint i = 0;
  184. if(macros == NULL)
  185. return;
  186. while(macros[i].shortcut != NULL)
  187. {
  188. gtk_accel_group_disconnect(shortcuts, macros[i].closure);
  189. i++;
  190. }
  191. macros_destroy();
  192. }
  193. static GtkTreeModel *create_model(void)
  194. {
  195. gint i = 0;
  196. GtkListStore *store;
  197. GtkTreeIter iter;
  198. /* create list store */
  199. store = gtk_list_store_new (NUM_COLUMNS,
  200. G_TYPE_STRING,
  201. G_TYPE_STRING,
  202. G_TYPE_BOOLEAN,
  203. G_TYPE_BOOLEAN);
  204. /* add data to the list store */
  205. if(macros != NULL)
  206. {
  207. while(1)
  208. {
  209. if(macros[i].shortcut == NULL)
  210. break;
  211. gtk_list_store_append (store, &iter);
  212. gtk_list_store_set (store, &iter,
  213. COLUMN_SHORTCUT, macros[i].shortcut,
  214. COLUMN_ACTION, macros[i].action,
  215. -1);
  216. i++;
  217. }
  218. }
  219. return GTK_TREE_MODEL(store);
  220. }
  221. static gboolean
  222. shortcut_edited (GtkCellRendererText *cell,
  223. const gchar *path_string,
  224. const gchar *new_text,
  225. gpointer data)
  226. {
  227. GtkTreeModel *model = (GtkTreeModel *)data;
  228. GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
  229. GtkTreeIter iter;
  230. gtk_tree_model_get_iter(model, &iter, path);
  231. gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_ACTION, new_text, -1);
  232. gtk_tree_path_free (path);
  233. return TRUE;
  234. }
  235. static void
  236. add_columns (GtkTreeView *treeview)
  237. {
  238. GtkCellRenderer *renderer;
  239. GtkTreeViewColumn *column;
  240. GtkTreeModel *model = gtk_tree_view_get_model (treeview);
  241. renderer = gtk_cell_renderer_text_new ();
  242. column = gtk_tree_view_column_new_with_attributes (_("Shortcut"),
  243. renderer,
  244. "text",
  245. COLUMN_SHORTCUT,
  246. NULL);
  247. gtk_tree_view_column_set_sort_column_id (column, COLUMN_SHORTCUT);
  248. gtk_tree_view_append_column (treeview, column);
  249. renderer = gtk_cell_renderer_text_new ();
  250. g_signal_connect (renderer, "edited", G_CALLBACK(shortcut_edited), model);
  251. column = gtk_tree_view_column_new_with_attributes ("Action", renderer, "text", COLUMN_ACTION, NULL);
  252. g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
  253. gtk_tree_view_column_set_sort_column_id (column, COLUMN_ACTION);
  254. gtk_tree_view_append_column (treeview, column);
  255. }
  256. static gint Add_shortcut(GtkWidget *button, gpointer pointer)
  257. {
  258. GtkTreeIter iter;
  259. GtkTreeModel *model = (GtkTreeModel *)pointer;
  260. gtk_list_store_append(GTK_LIST_STORE(model), &iter);
  261. gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_SHORTCUT, "None", -1);
  262. return FALSE;
  263. }
  264. static gboolean Delete_shortcut(GtkWidget *button, gpointer pointer)
  265. {
  266. GtkTreeIter iter;
  267. GtkTreeView *treeview = (GtkTreeView *)pointer;
  268. GtkTreeModel *model = gtk_tree_view_get_model (treeview);
  269. GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
  270. if (gtk_tree_selection_get_selected (selection, NULL, &iter))
  271. {
  272. gint i;
  273. GtkTreePath *path;
  274. path = gtk_tree_model_get_path(model, &iter);
  275. i = gtk_tree_path_get_indices(path)[0];
  276. gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
  277. gtk_tree_path_free (path);
  278. }
  279. return FALSE;
  280. }
  281. static gboolean Save_shortcuts(GtkWidget *button, gpointer pointer)
  282. {
  283. GtkTreeIter iter;
  284. GtkTreeView *treeview = (GtkTreeView *)pointer;
  285. GtkTreeModel *model = gtk_tree_view_get_model (treeview);
  286. gint i = 0;
  287. remove_shortcuts();
  288. if(gtk_tree_model_get_iter_first(model, &iter))
  289. {
  290. do
  291. {
  292. i++;
  293. } while(gtk_tree_model_iter_next(model, &iter));
  294. gtk_tree_model_get_iter_first(model, &iter);
  295. macros = g_malloc((i + 1) * sizeof(macro_t));
  296. i = 0;
  297. if(macros != NULL)
  298. {
  299. do
  300. {
  301. gtk_tree_model_get(model, &iter, COLUMN_SHORTCUT, &(macros[i].shortcut), \
  302. COLUMN_ACTION, &(macros[i].action), \
  303. -1);
  304. i++;
  305. } while(gtk_tree_model_iter_next(model, &iter));
  306. macros[i].shortcut = NULL;
  307. macros[i].action = NULL;
  308. }
  309. }
  310. add_shortcuts();
  311. return FALSE;
  312. }
  313. static gboolean key_pressed(GtkWidget *window, GdkEventKey *key, gpointer pointer)
  314. {
  315. GtkTreeIter iter;
  316. GtkTreeView *treeview = (GtkTreeView *)pointer;
  317. GtkTreeModel *model = gtk_tree_view_get_model (treeview);
  318. GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
  319. gchar *str = NULL;
  320. switch(key->keyval)
  321. {
  322. case GDK_Shift_L:
  323. case GDK_Shift_R:
  324. case GDK_Control_L:
  325. case GDK_Control_R:
  326. case GDK_Caps_Lock:
  327. case GDK_Shift_Lock:
  328. case GDK_Meta_L:
  329. case GDK_Meta_R:
  330. case GDK_Alt_L:
  331. case GDK_Alt_R:
  332. case GDK_Super_L:
  333. case GDK_Super_R:
  334. case GDK_Hyper_L:
  335. case GDK_Hyper_R:
  336. case GDK_Mode_switch:
  337. return FALSE;
  338. default:
  339. break;
  340. }
  341. if(gtk_tree_selection_get_selected(selection, NULL, &iter))
  342. {
  343. gint i;
  344. GtkTreePath *path;
  345. path = gtk_tree_model_get_path(model, &iter);
  346. i = gtk_tree_path_get_indices(path)[0];
  347. str = gtk_accelerator_name(key->keyval, key->state & ~GDK_MOD2_MASK);
  348. gtk_list_store_set(GTK_LIST_STORE (model), &iter, COLUMN_SHORTCUT, str, -1);
  349. gtk_tree_path_free(path);
  350. g_free(str);
  351. g_signal_handlers_disconnect_by_func(window, G_CALLBACK(key_pressed), pointer);
  352. }
  353. return FALSE;
  354. }
  355. static gboolean Capture_shortcut(GtkWidget *button, gpointer pointer)
  356. {
  357. g_signal_connect_after(window, "key_press_event", G_CALLBACK(key_pressed), pointer);
  358. return FALSE;
  359. }
  360. static gboolean Help_screen(GtkWidget *button, gpointer pointer)
  361. {
  362. GtkWidget *Dialogue, *Label, *Bouton, *Frame;
  363. Dialogue = gtk_dialog_new();
  364. gtk_window_set_title(GTK_WINDOW(Dialogue), _("Help on macros"));
  365. Bouton = gtk_button_new_from_stock (GTK_STOCK_OK);
  366. gtk_signal_connect_object(GTK_OBJECT(Bouton), "clicked", (GtkSignalFunc)gtk_widget_destroy, GTK_OBJECT(Dialogue));
  367. gtk_signal_connect(GTK_OBJECT(Dialogue), "destroy", (GtkSignalFunc)gtk_widget_destroy, NULL);
  368. gtk_signal_connect(GTK_OBJECT(Dialogue), "delete_event", (GtkSignalFunc)gtk_widget_destroy, NULL);
  369. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(Dialogue)->action_area), Bouton, TRUE, TRUE, 0);
  370. Label = gtk_label_new(_("The \"action\" field of a macro is the data to be sent on the port. Text can be entered, but also special chars, like \\n, \\t, \\r, etc. You can also enter hexadecimal data preceded by a '\\'. The hexadecimal data should not begin with a letter (eg. use \\0FF and not \\FF)\nExamples :\n\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal"));
  371. gtk_label_set_line_wrap(GTK_LABEL (Label), TRUE);
  372. gtk_label_set_selectable(GTK_LABEL(Label), TRUE);
  373. gtk_misc_set_padding(GTK_MISC(Label), 10, 10);
  374. Frame = gtk_frame_new(NULL);
  375. gtk_container_set_border_width(GTK_CONTAINER(Frame), 5);
  376. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(Dialogue)->vbox), Frame, FALSE, FALSE, 0);
  377. gtk_container_add(GTK_CONTAINER(Frame), Label);
  378. gtk_widget_show_all(Dialogue);
  379. return FALSE;
  380. }
  381. gint Config_macros(GtkWidget *wid, guint param)
  382. {
  383. GtkWidget *vbox, *hbox;
  384. GtkWidget *sw;
  385. GtkTreeModel *model;
  386. GtkWidget *treeview;
  387. GtkWidget *button;
  388. GtkWidget *separator;
  389. /* create window, etc */
  390. window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  391. gtk_window_set_title (GTK_WINDOW (window), _("Configure Macros"));
  392. g_signal_connect (window, "destroy",
  393. G_CALLBACK (gtk_widget_destroyed), &window);
  394. gtk_container_set_border_width (GTK_CONTAINER (window), 8);
  395. vbox = gtk_vbox_new (FALSE, 8);
  396. gtk_container_add (GTK_CONTAINER (window), vbox);
  397. sw = gtk_scrolled_window_new (NULL, NULL);
  398. gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
  399. GTK_SHADOW_ETCHED_IN);
  400. gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
  401. GTK_POLICY_NEVER,
  402. GTK_POLICY_AUTOMATIC);
  403. gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
  404. /* create tree model */
  405. model = create_model ();
  406. /* create tree view */
  407. treeview = gtk_tree_view_new_with_model (model);
  408. gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
  409. gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
  410. COLUMN_SHORTCUT);
  411. g_object_unref (model);
  412. gtk_container_add (GTK_CONTAINER (sw), treeview);
  413. /* add columns to the tree view */
  414. add_columns (GTK_TREE_VIEW (treeview));
  415. hbox = gtk_hbox_new (TRUE, 4);
  416. gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  417. button = gtk_button_new_with_mnemonic (_("_Add"));
  418. g_signal_connect(button, "clicked", G_CALLBACK(Add_shortcut), (gpointer)model);
  419. gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  420. button = gtk_button_new_with_mnemonic (_("_Delete"));
  421. g_signal_connect(button, "clicked", G_CALLBACK(Delete_shortcut), (gpointer)treeview);
  422. gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  423. button = gtk_button_new_with_mnemonic (_("_Capture Shortcut"));
  424. g_signal_connect(button, "clicked", G_CALLBACK(Capture_shortcut), (gpointer)treeview);
  425. gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  426. separator = gtk_hseparator_new();
  427. gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
  428. hbox = gtk_hbox_new (TRUE, 4);
  429. gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  430. button = gtk_button_new_from_stock (GTK_STOCK_HELP);
  431. g_signal_connect(button, "clicked", G_CALLBACK(Help_screen), NULL);
  432. gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  433. button = gtk_button_new_from_stock (GTK_STOCK_OK);
  434. g_signal_connect(button, "clicked", G_CALLBACK(Save_shortcuts), (gpointer)treeview);
  435. g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)window);
  436. gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  437. button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
  438. g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)window);
  439. gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  440. gtk_window_set_default_size (GTK_WINDOW(window), 300, 400);
  441. gtk_widget_show_all(window);
  442. return FALSE;
  443. }