diff -urN cui122/Makefile cui123/Makefile --- cui122/Makefile Fri Apr 18 22:00:00 2014 +++ cui123/Makefile Sun Apr 20 23:00:00 2014 @@ -5,9 +5,15 @@ ifeq ($(OS), FreeBSD) # use gmake LFLAGS += -lutil endif +LFLAGS += -lm TARG = cui_test cui_srv -OBJS = cui.o arg.o readable.o select.o sock.o focus.o num.o etext.o menu.o dialog.o timer.o term.o scline.o scpanel.o tbar.o rszbox.o scbar.o fillbtn.o tab.o radio.o ckbox.o button.o lblfix.o fill.o label.o panel.o handler.o esc.o key.o rect.o dbg.o list.o +OBJS = cui.o arg.o readable.o select.o sock.o focus.o +OBJS += num.o etext.o menu.o dialog.o timer.o term.o +OBJS += scline.o scpanel.o tbar.o rszbox.o scbar.o +OBJS += kbd.o fillbtn.o tab.o radio.o ckbox.o button.o +OBJS += lblfix.o fill.o label.o panel.o +OBJS += handler.o esc.o key.o rect.o dbg.o list.o all: $(TARG) diff -urN cui122/kbd.c cui123/kbd.c --- cui122/kbd.c Thu Jan 1 09:00:00 1970 +++ cui123/kbd.c Sun Apr 20 23:00:00 2014 @@ -0,0 +1,288 @@ +#include "kbd.h" +#include "handler.h" +#include "key.h" +#include "scline.h" +#include "menu.h" +#include "num.h" +#include +#include +#include +#include + +static int +kbd_note_x(int note) +{ + int i = note % 12; + int o = note / 12; + return o * 14 + i + (i >= 5); +} + +static int +kbd_x_note(int x) +{ + int o = x / 14; + int i = x % 14; + if(i == 5 || i == 13) return -1; + return o * 12 + i - (i >= 5); +} + +cui +cui_kbd_new(cui parent, int x, int y, int w) +{ + cui obj = cui_alloc(sizeof(struct cui_kbd)); + cui_kbd_init(obj, parent, x, y, w); + return obj; +} + +void +cui_kbd_init(cui obj, cui parent, int x, int y, int w) +{ + cui_kbd p = (cui_kbd)obj; + int i; + char *name_lst[] = { "G#", "G", "F#", "F", "E", "D#", "D", "C#", "C", "B", "A#", "A", NULL }; + + cui_base_init(obj, parent, x, y, w, 3); + p->sheet = cui_base_new(obj, 0, 1, kbd_note_x(128), 2); + + obj->flags |= CUI_FLG_CAN_FOCUS; + for(i=0; i<128; i++) p->v[i] = FALSE; + p->play_mode = FALSE; + p->cursor = 69; + cui_x_set(p->sheet, -kbd_note_x(p->cursor)); + + cui_bind(obj, CUI_EVT_DRAW | CUI_EVT_KEY | CUI_EVT_RESIZE, cui_kbd_hdr, NULL); + + p->scl = cui_scline_new(obj, 0, 0, 0); + p->sc_sheet = cui_base_new(cui_scline_view_get(p->scl), 0, 0, 0, 1); + cui_scline_sheet_set(p->scl, p->sc_sheet); + + p->oct = cui_menu_int_new(p->sc_sheet, 0, 0, 2+1, 5, -1, 9); + p->name = cui_menu_popup_new(p->sc_sheet, cui_x2(p->oct), 0, 2+1, name_lst, 11); + p->note_no = cui_num_new(p->sc_sheet, cui_x2(p->name)+2, 0, 3+3, 69, 0, 127, 0); + p->freq = cui_num_dbl_new(p->sc_sheet, cui_x2(p->note_no)+2, 0, 7+3, 440.0, 8.2, 12543.9, 0.1, 0); + cui_w_set(p->sc_sheet, cui_x2(p->freq)); + cui_w_set(p->scl, w); + + cui_bind(p->oct, CUI_EVT_BUTTON, cui_kbd_hdr, obj); + cui_bind(p->name, CUI_EVT_BUTTON, cui_kbd_hdr, obj); + cui_bind(p->note_no, CUI_EVT_BUTTON, cui_kbd_hdr, obj); + cui_bind(p->freq, CUI_EVT_BUTTON, cui_kbd_hdr, obj); +} + +static void +kbd_draw_x_char_attr(cui obj, int fc, int x, char *c_u, int *a_u, char *c_l, int *a_l) +{ + cui_kbd p = (cui_kbd)obj; + int note = kbd_x_note(x); + int blk = x & 1; + *c_u = note < 0 ? '|' : ' '; + *a_u = note >= 0 && blk ? CUI_ATTR_REVERSE : CUI_ATTR_NORMAL; + *c_l = blk ? '|' : ' '; + *a_l = CUI_ATTR_NORMAL; + + if(p->play_mode) *a_l |= CUI_ATTR_ULINE; + if(note == p->cursor){ + if(blk) *c_l = '^'; + else *a_u |= CUI_ATTR_ULINE; + } + if(note >= 0 && p->v[note]){ + if(blk) *c_u = 'o'; + else *c_l = 'o'; + } + if(!p->play_mode && fc){ + *a_u ^= CUI_ATTR_REVERSE; + *a_l ^= CUI_ATTR_REVERSE; + } +} + +static void +kbd_draw_x(cui obj, int fc, int x) +{ + cui_kbd p = (cui_kbd)obj; + char c_u, c_l; + int a_u, a_l; + char buf[2]; + buf[1] = '\0'; + + kbd_draw_x_char_attr(obj, fc, x, &c_u, &a_u, &c_l, &a_l); + + buf[0] = c_u; + cui_draw_str(p->sheet, x, 0, buf, a_u); + + buf[0] = c_l; + cui_draw_str(p->sheet, x, 1, buf, a_l); +} + +static void +kbd_draw_note(cui obj, int fc, int note) +{ + kbd_draw_x(obj, fc, kbd_note_x(note)); +} + +static void +kbd_draw(cui obj, int fc) +{ + cui_kbd p = (cui_kbd)obj; + int x; + for(x=0; xsheet->w; x++) kbd_draw_x(obj, fc, x); +} + +int +cui_kbd_hdr(cui obj, int evt, int val, void *prm) +{ + cui ev_obj = obj; + cui_kbd p = (cui_kbd)obj; + + switch(evt){ + case CUI_EVT_DRAW: + kbd_draw(obj, val == CUI_DRAW_FOCUS); + break; + case CUI_EVT_KEY: + if(!p->play_mode){ + if(val == CUI_KEY_ENTER){ + p->play_mode = TRUE; + cui_draw(obj); + return TRUE; + } + return FALSE; + } + /* play_mode */ + switch(val){ + case CUI_KEY_ENTER: + p->play_mode = FALSE; + cui_draw(obj); + break; + case CUI_KEY_LEFT: + if(p->cursor > 0){ + int mv = -( p->sheet->x + kbd_note_x(p->cursor - 1) ); + if(mv > 0){ + cui_x_set(p->sheet, p->sheet->x + mv); + cui_draw(obj); + } + kbd_draw_note(obj, FALSE, p->cursor--); + kbd_draw_note(obj, FALSE, p->cursor); + cui_num_set(p->note_no, p->cursor); + cui_handler_call(p->note_no, CUI_EVT_BUTTON, p->cursor); + } + break; + case CUI_KEY_RIGHT: + if(p->cursor < 127){ + int mv = p->sheet->x + kbd_note_x(p->cursor + 1) - (obj->w - 1); + if(mv > 0){ + cui_x_set(p->sheet, p->sheet->x - mv); + cui_draw(obj); + } + kbd_draw_note(obj, FALSE, p->cursor++); + kbd_draw_note(obj, FALSE, p->cursor); + cui_num_set(p->note_no, p->cursor); + cui_handler_call(p->note_no, CUI_EVT_BUTTON, p->cursor); + } + break; + case CUI_KEY_UP: + if(p->v[ p->cursor ]){ + p->v[ p->cursor ] = FALSE; + kbd_draw_note(obj, FALSE, p->cursor); + cui_handler_call(obj, CUI_EVT_BUTTON, p->cursor); + } + break; + case CUI_KEY_DOWN: + if(!p->v[ p->cursor ]){ + p->v[ p->cursor ] = TRUE; + kbd_draw_note(obj, FALSE, p->cursor); + cui_handler_call(obj, CUI_EVT_BUTTON, p->cursor | 0x100); /* ON flag */ + } + break; + } + break; + case CUI_EVT_BUTTON: + obj = (cui)prm; + p = (cui_kbd)obj; + + if(ev_obj == p->note_no){ + int note = val; + int oct_v = (note - 9 + 12) / 12 - 1; + int name_v = (note - 9) % 12; + double fq = 440 * pow(2, (note - 69) / 12.0); + + if(cui_menu_int_get(p->oct) != oct_v) cui_menu_int_set(p->oct, oct_v); + if(cui_menu_popup_get(p->name) != 11-name_v) cui_menu_popup_set(p->name, 11-name_v); + if(cui_num_dbl_get(p->freq) != fq) cui_num_dbl_set(p->freq, fq); + if(cui_kbd_cursor_get(obj) != note) cui_kbd_cursor_set(obj, note); + }else if(ev_obj == p->oct){ + int oct_v = val; + int name_v = 11 - cui_menu_popup_get(p->name); + int note = oct_v * 12 + name_v + 9; + if(cui_num_get(p->note_no) != note){ + cui_num_set(p->note_no, note); + cui_handler_call(p->note_no, CUI_EVT_BUTTON, note); + } + }else if(ev_obj == p->name){ + int oct_v = cui_menu_int_get(p->oct); + int name_v = 11 - val; + int note = oct_v * 12 + name_v + 9; + if(cui_num_get(p->note_no) != note){ + cui_num_set(p->note_no, note); + cui_handler_call(p->note_no, CUI_EVT_BUTTON, note); + } + }else if(ev_obj == p->freq){ + double fq = cui_num_dbl_get(p->freq); + int note = (int)( ( log(fq/440) / log(2) ) * 12 + 69 + 0.5 ); + cui_num_set(p->note_no, note); + cui_handler_call(p->note_no, CUI_EVT_BUTTON, note); + }else return FALSE; + break; + case CUI_EVT_RESIZE: + cui_w_set(p->scl, obj->w); + break; + default: + return FALSE; + } + return TRUE; +} + +void +cui_kbd_set(cui obj, int note, int v) +{ + cui_kbd p = (cui_kbd)obj; + p->v[ note ] = v; + kbd_draw_note(obj, cui_focus_get() == obj, note); +} + +int +cui_kbd_get(cui obj, int note) +{ + cui_kbd p = (cui_kbd)obj; + return p->v[ note ]; +} + +void +cui_kbd_cursor_set(cui obj, int note) +{ + cui_kbd p = (cui_kbd)obj; + int bak = p->cursor; + int x, mv = 0; + + if(note < 0) note = 0; + if(note > 127) note = 127; + if(bak == note) return; + + x = p->sheet->x + kbd_note_x(note); + if(x < 0) mv = -x; + else if(x > obj->w-1) mv = -(x - (obj->w-1)); + if(mv != 0){ + cui_x_set(p->sheet, p->sheet->x + mv); + cui_draw(obj); + } + p->cursor = note; + kbd_draw_note(obj, FALSE, bak); + kbd_draw_note(obj, FALSE, p->cursor); +} + +int +cui_kbd_cursor_get(cui obj) +{ + cui_kbd p = (cui_kbd)obj; + return p->cursor; +} + +/* EOF */ diff -urN cui122/kbd.h cui123/kbd.h --- cui122/kbd.h Thu Jan 1 09:00:00 1970 +++ cui123/kbd.h Sun Apr 20 23:00:00 2014 @@ -0,0 +1,24 @@ +#ifndef __KBD_H__ +#define __KBD_H__ + +#include "cui.h" + +typedef struct cui_kbd{ + struct cui_base base; + int v[128]; + int play_mode; + int cursor; + cui sheet; + + cui scl, sc_sheet; + cui oct, name, note_no, freq; +} *cui_kbd; + +cui cui_kbd_new(cui parent, int x, int y, int w); +void cui_kbd_init(cui obj, cui parent, int x, int y, int w); +int cui_kbd_hdr(cui obj, int evt, int val, void *prm); +void cui_kbd_set(cui obj, int note, int v); +void cui_kbd_cursor_set(cui obj, int note); +int cui_kbd_cursor_get(cui obj); + +#endif