static int key_load_kbs (void) { char *buf, *ibuf; struct stat st; struct key_binding *kb = NULL; int fd, len, state = 0, pnt = 0; guint keyval; GdkModifierType mod = 0; off_t size; fd = hexchat_open_file ("keybindings.conf", O_RDONLY, 0, 0); if (fd < 0) { ibuf = g_strdup (default_kb_cfg); size = strlen (default_kb_cfg); } else { if (fstat (fd, &st) != 0) { close (fd); return 1; } ibuf = g_malloc(st.st_size); read (fd, ibuf, st.st_size); size = st.st_size; close (fd); } if (keybind_list) { g_slist_free_full (keybind_list, key_free); keybind_list = NULL; } while (buf_get_line (ibuf, &buf, &pnt, size)) { if (buf[0] == '#') continue; if (strlen (buf) == 0) continue; switch (state) { case KBSTATE_MOD: kb = g_new0 (struct key_binding, 1); /* New format */ if (strncmp (buf, "ACCEL=", 6) == 0) { buf += 6; gtk_accelerator_parse (buf, &keyval, &mod); kb->keyval = keyval; kb->mod = key_modifier_get_valid (mod); state = KBSTATE_ACT; continue; } if (key_load_kbs_helper_mod (buf, &mod)) goto corrupt_file; kb->mod = mod; state = KBSTATE_KEY; continue; case KBSTATE_KEY: STRIP_WHITESPACE keyval = gdk_keyval_from_name (buf); if (keyval == 0) { g_free (ibuf); return 2; } kb->keyval = keyval; state = KBSTATE_ACT; continue; case KBSTATE_ACT: STRIP_WHITESPACE kb->action = key_get_action_from_string (buf); if (kb->action == KEY_MAX_ACTIONS + 1) { g_free (ibuf); return 3; } state = KBSTATE_DT1; continue; case KBSTATE_DT1: case KBSTATE_DT2: if (state == KBSTATE_DT1) kb->data1 = kb->data2 = NULL; while (buf[0] == ' ' || buf[0] == '\t') buf++; if (buf[0] != 'D') { g_free (ibuf); return 4; } switch (buf[1]) { case '1': if (state != KBSTATE_DT1) goto corrupt_file; break; case '2': if (state != KBSTATE_DT2) goto corrupt_file; break; default: goto corrupt_file; } if (buf[2] == ':') { len = strlen (buf); /* Add one for the NULL, subtract 3 for the "Dx:" */ len++; len -= 3; if (state == KBSTATE_DT1) { kb->data1 = g_strndup (&buf[3], len); } else { kb->data2 = g_strndup (&buf[3], len); } } else if (buf[2] == '!') { if (state == KBSTATE_DT1) kb->data1 = NULL; else kb->data2 = NULL; } if (state == KBSTATE_DT1) { state = KBSTATE_DT2; continue; } else { keybind_list = g_slist_append (keybind_list, kb); state = KBSTATE_MOD; } continue; } } g_free (ibuf); return 0; corrupt_file: g_free (ibuf); g_free (kb); return 5; }
static int key_load_kbs (char *filename) { char *buf, *ibuf; struct stat st; struct key_binding *kb = NULL, *last = NULL; int fd, len, pnt = 0, state = 0, n; if (filename == NULL) fd = xchat_open_file ("keybindings.conf", O_RDONLY, 0, 0); else fd = xchat_open_file (filename, O_RDONLY, 0, XOF_FULLPATH); if (fd < 0) return 1; if (fstat (fd, &st) != 0) return 1; ibuf = malloc (st.st_size); read (fd, ibuf, st.st_size); close (fd); while (buf_get_line (ibuf, &buf, &pnt, st.st_size)) { if (buf[0] == '#') continue; if (strlen (buf) == 0) continue; switch (state) { case KBSTATE_MOD: kb = (struct key_binding *) malloc (sizeof (struct key_binding)); if (key_load_kbs_helper_mod (buf, &kb->mod)) goto corrupt_file; state = KBSTATE_KEY; continue; case KBSTATE_KEY: /* First strip off the fluff */ while (buf[0] == ' ' || buf[0] == '\t') buf++; len = strlen (buf); while (buf[len] == ' ' || buf[len] == '\t') { buf[len] = 0; len--; } n = gdk_keyval_from_name (buf); if (n == 0) { /* Unknown keyname, abort */ if (last) last->next = NULL; free (ibuf); ibuf = malloc (1024); snprintf (ibuf, 1024, _("Unknown keyname %s in key bindings config file\nLoad aborted, please fix %s/keybindings.conf\n"), buf, get_xdir_utf8 ()); fe_message (ibuf, FE_MSG_ERROR); free (ibuf); return 2; } kb->keyname = gdk_keyval_name (n); kb->keyval = n; state = KBSTATE_ACT; continue; case KBSTATE_ACT: /* First strip off the fluff */ while (buf[0] == ' ' || buf[0] == '\t') buf++; len = strlen (buf); while (buf[len] == ' ' || buf[len] == '\t') { buf[len] = 0; len--; } for (n = 0; n < KEY_MAX_ACTIONS + 1; n++) { if (strcmp (key_actions[n].name, buf) == 0) { kb->action = n; break; } } if (n == KEY_MAX_ACTIONS + 1) { if (last) last->next = NULL; free (ibuf); ibuf = malloc (1024); snprintf (ibuf, 1024, _("Unknown action %s in key bindings config file\nLoad aborted, Please fix %s/keybindings\n"), buf, get_xdir_utf8 ()); fe_message (ibuf, FE_MSG_ERROR); free (ibuf); return 3; } state = KBSTATE_DT1; continue; case KBSTATE_DT1: case KBSTATE_DT2: if (state == KBSTATE_DT1) kb->data1 = kb->data2 = NULL; while (buf[0] == ' ' || buf[0] == '\t') buf++; if (buf[0] != 'D') { free (ibuf); ibuf = malloc (1024); snprintf (ibuf, 1024, _("Expecting Data line (beginning Dx{:|!}) but got:\n%s\n\nLoad aborted, Please fix %s/keybindings\n"), buf, get_xdir_utf8 ()); fe_message (ibuf, FE_MSG_ERROR); free (ibuf); return 4; } switch (buf[1]) { case '1': if (state != KBSTATE_DT1) goto corrupt_file; break; case '2': if (state != KBSTATE_DT2) goto corrupt_file; break; default: goto corrupt_file; } if (buf[2] == ':') { len = strlen (buf); /* Add one for the NULL, subtract 3 for the "Dx:" */ len++; len -= 3; if (state == KBSTATE_DT1) { kb->data1 = malloc (len); memcpy (kb->data1, &buf[3], len); } else { kb->data2 = malloc (len); memcpy (kb->data2, &buf[3], len); } } else if (buf[2] == '!') { if (state == KBSTATE_DT1) kb->data1 = NULL; else kb->data2 = NULL; } if (state == KBSTATE_DT1) { state = KBSTATE_DT2; continue; } else { if (last) last->next = kb; else keys_root = kb; last = kb; state = KBSTATE_MOD; } continue; } } if (last) last->next = NULL; free (ibuf); return 0; corrupt_file: /*if (getenv ("XCHAT_DEBUG")) abort ();*/ snprintf (ibuf, 1024, _("Key bindings config file is corrupt, load aborted\n" "Please fix %s/keybindings.conf\n"), get_xdir_utf8 ()); fe_message (ibuf, FE_MSG_ERROR); free (ibuf); return 5; }