void menu(void) { int i; menu_init(); /* let LED on pin 4 of the DIP8 blink */ //Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 2); /* pcs(pcs_led_out); for( i = 0; i < 10; i++ ) { pcs(pcs_led_high); delay_micro_seconds(50000UL); pcs(pcs_led_low); delay_micro_seconds(50000UL); } */ //key_add_to_queue(KEY_NEXT); for(;;) { if ( menu_handle_key() != 0 || clk_o.is_update != 0 ) { clk_o.is_update = 0; oled_start_page(&oled_o); do { menu_draw(); /* pcs(pcs_led_high); delay_micro_seconds(100000UL); pcs(pcs_led_low); delay_micro_seconds(100000UL); */ } while( oled_next_page(&oled_o) ); } } }
struct menu * menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt, const char *initial, int flags, void (*match)(struct menu_q *, struct menu_q *, char *), void (*print)(struct menu *, int)) { struct menu_ctx mc; struct menu_q resultq; struct menu *mi = NULL; XEvent e; Window focuswin; int focusrevert, xsave, ysave, xcur, ycur; TAILQ_INIT(&resultq); xu_ptr_getpos(sc->rootwin, &xsave, &ysave); (void)memset(&mc, 0, sizeof(mc)); mc.sc = sc; mc.flags = flags; mc.match = match; mc.print = print; mc.entry = mc.prev = -1; mc.geom.x = xsave; mc.geom.y = ysave; if (mc.flags & CWM_MENU_LIST) mc.list = 1; (void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr)); if (initial != NULL) (void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr)); else mc.searchstr[0] = '\0'; mc.win = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1, Conf.bwidth, sc->xftcolor[CWM_COLOR_MENU_FG].pixel, sc->xftcolor[CWM_COLOR_MENU_BG].pixel); mc.xftdraw = XftDrawCreate(X_Dpy, mc.win, sc->visual, sc->colormap); XSelectInput(X_Dpy, mc.win, MENUMASK); XMapRaised(X_Dpy, mc.win); if (XGrabPointer(X_Dpy, mc.win, False, MENUGRABMASK, GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_QUESTION], CurrentTime) != GrabSuccess) { XftDrawDestroy(mc.xftdraw); XDestroyWindow(X_Dpy, mc.win); } XGetInputFocus(X_Dpy, &focuswin, &focusrevert); XSetInputFocus(X_Dpy, mc.win, RevertToPointerRoot, CurrentTime); /* make sure keybindings don't remove keys from the menu stream */ XGrabKeyboard(X_Dpy, mc.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); for (;;) { mc.changed = 0; XWindowEvent(X_Dpy, mc.win, MENUMASK, &e); switch (e.type) { case KeyPress: if ((mi = menu_handle_key(&e, &mc, menuq, &resultq)) != NULL) goto out; /* FALLTHROUGH */ case Expose: menu_draw(&mc, menuq, &resultq); break; case MotionNotify: menu_handle_move(&mc, &resultq, e.xbutton.x, e.xbutton.y); break; case ButtonRelease: if ((mi = menu_handle_release(&mc, &resultq, e.xbutton.x, e.xbutton.y)) != NULL) goto out; break; default: break; } } out: if ((mc.flags & CWM_MENU_DUMMY) == 0 && mi->dummy) { /* no mouse based match */ free(mi); mi = NULL; } XftDrawDestroy(mc.xftdraw); XDestroyWindow(X_Dpy, mc.win); XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime); /* restore if user didn't move */ xu_ptr_getpos(sc->rootwin, &xcur, &ycur); if (xcur == mc.geom.x && ycur == mc.geom.y) xu_ptr_setpos(sc->rootwin, xsave, ysave); XUngrabPointer(X_Dpy, CurrentTime); XUngrabKeyboard(X_Dpy, CurrentTime); return(mi); }
/* this is the important one */ void handle_key(struct key_event *k) { if (_handle_ime(k)) return; /* okay... */ if (!(status.flags & DISKWRITER_ACTIVE) && ACTIVE_PAGE.pre_handle_key) { if (ACTIVE_PAGE.pre_handle_key(k)) return; } if (handle_key_global(k)) return; if (!(status.flags & DISKWRITER_ACTIVE) && menu_handle_key(k)) return; if (widget_handle_key(k)) return; /* now check a couple other keys. */ switch (k->sym) { case SDLK_LEFT: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if ((k->mod & KMOD_CTRL) && status.current_page != PAGE_PATTERN_EDITOR) { _mp_finish(NULL); if (song_get_mode() == MODE_PLAYING) song_set_current_order(song_get_current_order() - 1); return; } break; case SDLK_RIGHT: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if ((k->mod & KMOD_CTRL) && status.current_page != PAGE_PATTERN_EDITOR) { _mp_finish(NULL); if (song_get_mode() == MODE_PLAYING) song_set_current_order(song_get_current_order() + 1); return; } break; case SDLK_ESCAPE: /* TODO | Page key handlers should return true/false depending on if the key was handled TODO | (same as with other handlers), and the escape key check should go *after* the TODO | page gets a chance to grab it. This way, the load sample page can switch back TODO | to the sample list on escape like it's supposed to. (The status.current_page TODO | checks above won't be necessary, either.) */ if (NO_MODIFIER(k->mod) && status.dialog_type == DIALOG_NONE && status.current_page != PAGE_LOAD_SAMPLE && status.current_page != PAGE_LOAD_INSTRUMENT) { if (k->state == KEY_RELEASE) return; if (_mp_active) { _mp_finish(NULL); return; } menu_show(); return; } break; case SDLK_SLASH: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if (k->orig_sym == SDLK_KP_DIVIDE) { kbd_set_current_octave(kbd_get_current_octave() - 1); } return; case SDLK_ASTERISK: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if (k->orig_sym == SDLK_KP_MULTIPLY) { kbd_set_current_octave(kbd_get_current_octave() + 1); } return; case SDLK_LEFTBRACKET: if (k->state == KEY_RELEASE) break; if (status.flags & DISKWRITER_ACTIVE) return; if (k->mod & KMOD_SHIFT) { song_set_current_speed(song_get_current_speed() - 1); status_text_flash("Speed set to %d frames per row", song_get_current_speed()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_speed(song_get_current_speed()); } } else if ((k->mod & KMOD_CTRL) && !(status.flags & CLASSIC_MODE)) { song_set_current_tempo(song_get_current_tempo() - 1); status_text_flash("Tempo set to %d frames per row", song_get_current_tempo()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_tempo(song_get_current_tempo()); } } else if (NO_MODIFIER(k->mod)) { song_set_current_global_volume(song_get_current_global_volume() - 1); status_text_flash("Global volume set to %d", song_get_current_global_volume()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_global_volume(song_get_current_global_volume()); } } return; case SDLK_RIGHTBRACKET: if (k->state == KEY_RELEASE) break; if (status.flags & DISKWRITER_ACTIVE) return; if (k->mod & KMOD_SHIFT) { song_set_current_speed(song_get_current_speed() + 1); status_text_flash("Speed set to %d frames per row", song_get_current_speed()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_speed(song_get_current_speed()); } } else if ((k->mod & KMOD_CTRL) && !(status.flags & CLASSIC_MODE)) { song_set_current_tempo(song_get_current_tempo() + 1); status_text_flash("Tempo set to %d frames per row", song_get_current_tempo()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_tempo(song_get_current_tempo()); } } else if (NO_MODIFIER(k->mod)) { song_set_current_global_volume(song_get_current_global_volume() + 1); status_text_flash("Global volume set to %d", song_get_current_global_volume()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_global_volume(song_get_current_global_volume()); } } return; default: break; } /* and if we STILL didn't handle the key, pass it to the page. * (or dialog, if one's active) */ if (status.dialog_type & DIALOG_BOX) { dialog_handle_key(k); } else { if (status.flags & DISKWRITER_ACTIVE) return; if (ACTIVE_PAGE.handle_key) ACTIVE_PAGE.handle_key(k); } }
struct menu * menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt, char *initial, int dummy, void (*match)(struct menu_q *, struct menu_q *, char *), void (*print)(struct menu *, int)) { struct menu_ctx mc; struct menu_q resultq; struct menu *mi = NULL; XEvent e; Window focuswin; int evmask, focusrevert; int xsave, ysave, xcur, ycur; TAILQ_INIT(&resultq); bzero(&mc, sizeof(mc)); xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y); xsave = mc.x; ysave = mc.y; if (prompt == NULL) { evmask = MENUMASK; mc.promptstr[0] = '\0'; mc.list = 1; } else { evmask = MENUMASK | KEYMASK; /* only accept keys if prompt */ (void)snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%s", prompt, PROMPT_SCHAR); (void)snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%s", mc.promptstr, mc.searchstr, PROMPT_ECHAR); mc.width = font_width(sc, mc.dispstr, strlen(mc.dispstr)); mc.hasprompt = 1; } if (initial != NULL) (void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr)); else mc.searchstr[0] = '\0'; mc.match = match; mc.print = print; mc.entry = mc.prev = -1; XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width, font_height(sc)); XSelectInput(X_Dpy, sc->menuwin, evmask); XMapRaised(X_Dpy, sc->menuwin); if (xu_ptr_grab(sc->menuwin, MENUGRABMASK, Cursor_question) < 0) { XUnmapWindow(X_Dpy, sc->menuwin); return (NULL); } XGetInputFocus(X_Dpy, &focuswin, &focusrevert); XSetInputFocus(X_Dpy, sc->menuwin, RevertToPointerRoot, CurrentTime); /* make sure keybindings don't remove keys from the menu stream */ XGrabKeyboard(X_Dpy, sc->menuwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); menu_draw(sc, &mc, menuq, &resultq); for (;;) { mc.changed = 0; XWindowEvent(X_Dpy, sc->menuwin, evmask, &e); switch (e.type) { case KeyPress: if ((mi = menu_handle_key(&e, &mc, menuq, &resultq)) != NULL) goto out; /* FALLTHROUGH */ case Expose: menu_draw(sc, &mc, menuq, &resultq); break; case MotionNotify: menu_handle_move(&e, &mc, &resultq, sc); break; case ButtonRelease: if ((mi = menu_handle_release(&e, &mc, sc, &resultq)) != NULL) goto out; break; default: break; } } out: if (dummy == 0 && mi->dummy) { /* no mouse based match */ xfree(mi); mi = NULL; } XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime); /* restore if user didn't move */ xu_ptr_getpos(sc->rootwin, &xcur, &ycur); if (xcur == mc.x && ycur == mc.y) xu_ptr_setpos(sc->rootwin, xsave, ysave); xu_ptr_ungrab(); XUnmapWindow(X_Dpy, sc->menuwin); XUngrabKeyboard(X_Dpy, CurrentTime); return (mi); }