Example #1
0
void parse_keybinding(char *ptr)
{
    char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
    sc *s, *newsc;
    int i, menu;

    assert(ptr != NULL);

    if (*ptr == '\0') {
	rcfile_error(N_("Missing key name"));
	return;
    }

    keyptr = ptr;
    ptr = parse_next_word(ptr);
    keycopy = mallocstrcpy(NULL, keyptr);
    for (i = 0; i < strlen(keycopy); i++)
	keycopy[i] = toupper(keycopy[i]);

    if (keycopy[0] != 'M' && keycopy[0] != '^' && keycopy[0] != 'F' && keycopy[0] != 'K') {
	rcfile_error(
		N_("keybindings must begin with \"^\", \"M\", or \"F\""));
	return;
    }

    funcptr = ptr;
    ptr = parse_next_word(ptr);

    if (!strcmp(funcptr, "")) {
	rcfile_error(
		N_("Must specify function to bind key to"));
	return;
    }

    menuptr = ptr;
    ptr = parse_next_word(ptr);

    if (!strcmp(menuptr, "")) {
	rcfile_error(
		/* Note to translators, do not translate the word "all"
		   in the sentence below, everything else is fine */
		N_("Must specify menu to bind key to (or \"all\")"));
	return;
    }

    newsc = strtosc(menu, funcptr);
    if (newsc == NULL) {
	rcfile_error(
		N_("Could not map name \"%s\" to a function"), funcptr);
	return;
    }

    menu = strtomenu(menuptr);
    if (menu < 1) {
	rcfile_error(
		N_("Could not map name \"%s\" to a menu"), menuptr);
	return;
    }


#ifdef DEBUG
    fprintf(stderr, "newsc now address %d, menu func assigned = %d, menu = %d\n",
	&newsc, newsc->scfunc, menu);
#endif


    newsc->keystr = keycopy;
    newsc->menu = menu;
    newsc->type = strtokeytype(newsc->keystr);
    assign_keyinfo(newsc);
#ifdef DEBUG
    fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
    fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
#endif

    if (check_bad_binding(newsc)) {
	rcfile_error(
		N_("Sorry, keystr \"%s\" is an illegal binding"), newsc->keystr);
	return;
    }


    /* now let's have some fun.  Try and delete the other entries
       we found for the same menu, then make this new new
       beginning */
    for (s = sclist; s != NULL; s = s->next) {
        if (((s->menu & newsc->menu)) && s->seq == newsc->seq) {
	    s->menu &= ~newsc->menu;
#ifdef DEBUG
	    fprintf(stderr, "replaced menu entry %d\n", s->menu);
#endif
	}
    }
    newsc->next = sclist;
    sclist = newsc;
}
Example #2
0
File: rcfile.c Project: ris21/yoda
/* Bind or unbind a key combo, to or from a function. */
void parse_binding(char *ptr, bool dobind)
{
    char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
    sc *s, *newsc = NULL;
    int menu;

    assert(ptr != NULL);

#ifdef DEBUG
    fprintf(stderr, "Starting the rebinding code...\n");
#endif

    if (*ptr == '\0') {
	rcfile_error(N_("Missing key name"));
	return;
    }

    keyptr = ptr;
    ptr = parse_next_word(ptr);
    keycopy = mallocstrcpy(NULL, keyptr);

    if (strlen(keycopy) < 2) {
	rcfile_error(N_("Key name is too short"));
	return;
    }

    /* Uppercase only the first two or three characters of the key name. */
    keycopy[0] = toupper(keycopy[0]);
    keycopy[1] = toupper(keycopy[1]);
    if (keycopy[0] == 'M' && keycopy[1] == '-') {
	if (strlen(keycopy) > 2)
	    keycopy[2] = toupper(keycopy[2]);
	else {
	    rcfile_error(N_("Key name is too short"));
	    return;
	}
    }

    /* Allow the codes for Insert and Delete to be rebound, but apart
     * from those two only Control, Meta and Function sequences. */
    if (!strcasecmp(keycopy, "Ins") || !strcasecmp(keycopy, "Del"))
	keycopy[1] = tolower(keycopy[1]);
    else if (keycopy[0] != '^' && keycopy[0] != 'M' && keycopy[0] != 'F') {
	rcfile_error(N_("Key name must begin with \"^\", \"M\", or \"F\""));
	return;
    }

    if (dobind) {
	funcptr = ptr;
	ptr = parse_next_word(ptr);

	if (funcptr[0] == '\0') {
	    rcfile_error(N_("Must specify a function to bind the key to"));
	    return;
	}
    }

    menuptr = ptr;
    ptr = parse_next_word(ptr);

    if (menuptr[0] == '\0') {
	/* TRANSLATORS: Do not translate the word "all". */
	rcfile_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key"));
	return;
    }

    if (dobind) {
	newsc = strtosc(funcptr);
	if (newsc == NULL) {
	    rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr);
	    return;
	}
    }

    menu = strtomenu(menuptr);
    if (menu < 1) {
	rcfile_error(N_("Cannot map name \"%s\" to a menu"), menuptr);
	return;
    }

#ifdef DEBUG
    if (dobind)
	fprintf(stderr, "newsc address is now %ld, assigned func = %ld, menu = %x\n",
	    (long)&newsc, (long)newsc->scfunc, menu);
    else
	fprintf(stderr, "unbinding \"%s\" from menu %x\n", keycopy, menu);
#endif

    if (dobind) {
	subnfunc *f;
	int mask = 0;

	/* Tally up the menus where the function exists. */
	for (f = allfuncs; f != NULL; f = f->next)
	    if (f->scfunc == newsc->scfunc)
		mask = mask | f->menus;

	/* Handle the special case of the toggles. */
	if (newsc->scfunc == do_toggle_void)
	    mask = MMAIN;

	/* Now limit the given menu to those where the function exists. */
	if (is_universal(newsc->scfunc))
	    menu = menu & MMOST;
	else
	    menu = menu & mask;

	if (!menu) {
	    rcfile_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr);
	    free(newsc);
	    return;
	}

	newsc->keystr = keycopy;
	newsc->menu = menu;
	newsc->type = strtokeytype(newsc->keystr);
	assign_keyinfo(newsc);
#ifdef DEBUG
	fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
	fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
#endif

	if (check_bad_binding(newsc)) {
	    rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr);
	    free(newsc);
	    return;
	}
    }

    /* Now find and delete any existing same shortcut in the menu(s). */
    for (s = sclist; s != NULL; s = s->next) {
	if (((s->menu & menu)) && !strcmp(s->keystr, keycopy)) {
#ifdef DEBUG
	    fprintf(stderr, "deleting entry from menu %x\n", s->menu);
#endif
	    s->menu &= ~menu;
	}
    }

    if (dobind) {
	/* Add the new shortcut at the start of the list. */
	newsc->next = sclist;
	sclist = newsc;
    }
}