/* local function */ static void sig_handler(int signo) { fflush(stdout); normalmode(); printf("Exit by Signal %d\n", signo); exit(0); }
//main entry int main(int argc, char **argv) { unsigned int key = 0; signal(SIGINT, sig_handler); signal(SIGHUP, sig_handler); signal(SIGTERM, sig_handler); signal(SIGKILL, sig_handler); get_term_width_height(0, &gs.w, &gs.h); rawmode(); gs.buf = (char *)malloc(gs.w * gs.h+ gs.w); if( gs.buf == NULL ) goto EXIT; memset(gs.buf, 0, gs.w * gs.h+ gs.w); draw_start(); //start edit while(1) { key = get_key(); if( key == 'q' || key == 'Q' ) break; switch( key ) { case 's': case 'S': sc_cls(); break; case 'u': case 'U': sc_up(); break; case 'd': case 'D': sc_down(); break; case 'l': case 'L': sc_left(); break; case 'R': case 'r': sc_right(); break; default: sc_put_char(key); break; } } //free then exit free(gs.buf); normalmode(); EXIT: return 0; }
/* normal mode */ void normalmode(int c){ int i; // don't save the action for repeat if it's a movement or a repeat, or // something else that doesnt make sense to repeat if(c != 'h' && c != 'j' && c != 'k' && c != 'l' && c != CTRL('D') && c != CTRL('U') && c != CTRL('H') && c != CTRL('L') && c != 'H' && c != 'M' && c != 'L' && c != 'g' && c != 'G' && c != '.'){ lastaction = c; lastrepeatnum = cmdrepeatnum; } for(i=0; i<cmdrepeatnum; i++){ switch(c){ /* add line */ case 'a': act_addline(); break; case '.': // if the last command was a replace, just insert the last thing // inserted instead of calling insertmode() if(lastaction == 'r') _insertc(lastinsert); else normalmode(lastaction); cmdrepeatnum = lastrepeatnum; break; case KEY_ESCAPE: disptick = 0; jammermode(); break; case CTRL('Y'): switch(currtab){ case 0: if(songoffs>0){ if(songy==getmaxy(stdscr)-3+songoffs) songy--; songoffs--; } break; case 1: if(trackoffs>0){ if(tracky==getmaxy(stdscr)-3+trackoffs) tracky--; trackoffs--; } break; case 2: if(instroffs>0){ if(instry==getmaxy(stdscr)-3+instroffs) instry--; instroffs--; } break; } break; case CTRL('E'): switch(currtab){ case 0: if(songy<=tune->songlen-2){ if(songy==songoffs) songy++; songoffs++; } break; case 1: if(tracky<=(tune->tracklen)-2){ if(tracky==trackoffs) tracky++; trackoffs++; } break; case 2: if(instry<=instrument[currinstr].length-2){ if(instry==instroffs) instry++; instroffs++; } break; } break; case 'H': switch(currtab){ case 0: songy = songoffs; break; case 1: tracky = trackoffs; break; case 2: instry = instroffs; break; } break; // the second cases (to the right of the colon) for M and L // took some serious guesswork, so I'm not sure if they're // correct but they seem to work. case 'M': switch(currtab){ case 0: songy = (tune->songlen <= getmaxy(stdscr)-2)? tune->songlen/2 : ((getmaxy(stdscr)-6)/2) + songoffs; break; case 1: tracky = (tune->tracklen <= getmaxy(stdscr)-2)? tune->tracklen/2 : ((getmaxy(stdscr)-6)/2) + trackoffs; break; case 2: instry = (instrument[currinstr].length <= getmaxy(stdscr)-2)? instrument[currinstr].length/2 : ((getmaxy(stdscr)-6)/2) + instroffs; break; } break; case 'L': switch(currtab){ case 0: songy = (tune->songlen <= getmaxy(stdscr)-2)? tune->songlen-1 : getmaxy(stdscr)-3+songoffs; break; case 1: tracky = (tune->tracklen <= getmaxy(stdscr)-2)? tune->tracklen-1 : getmaxy(stdscr)-3+trackoffs; break; case 2: instry = (instrument[currinstr].length <= getmaxy(stdscr)-2)? instrument[currinstr].length-1 : getmaxy(stdscr)-3+instroffs; break; } break; case 'g': if(nextchar() == 'g'){ act_mvtop(); } break; case 'G': act_mvbottom(); break; // yank case 'y': c = nextchar(); switch(c){ case 'y': //tclip = malloc(1); if(currtab == 0){ tcliplen = 1; memcpy(&tclip, &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 1; memcpy(&tclip, &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 1; memcpy(&iclip, &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; case 'j': //tclip = malloc(2); if(currtab == 0){ tcliplen = 2; memcpy(&tclip[0], &tune->sng[songy], sizeof(struct songline)); act_mvdown(); memcpy(&tclip[1], &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 2; memcpy(&tclip[0], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); act_mvdown(); memcpy(&tclip[1], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 2; memcpy(&iclip[0], &instrument[currinstr].line[instry], sizeof(struct instrline)); act_mvdown(); memcpy(&iclip[1], &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; case 'k': //tclip = malloc(2); if(currtab == 0){ tcliplen = 2; memcpy(&tclip[1], &tune->sng[songy], sizeof(struct songline)); act_mvup(); memcpy(&tclip[0], &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 2; memcpy(&tclip[1], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); act_mvup(); memcpy(&tclip[0], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 2; memcpy(&iclip[1], &instrument[currinstr].line[instry], sizeof(struct instrline)); act_mvup(); memcpy(&iclip[0], &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; } break; //paste case 'p': if(currtab == 0){ if(tune->songlen < 256){ for(int i = 0; i < tcliplen; i++){ // insert new line memmove(&tune->sng[songy + 2], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); songy++; tune->songlen++; memset(&tune->sng[songy], 0, sizeof(struct songline)); // paste to new line memcpy(&tune->sng[songy], &tclip[i], sizeof(struct songline)); } } }else if(currtab == 1){ for(int i = 0; i < tcliplen; i++){ memcpy(&tune->trk[currtrack].line[tracky], &tclip[i], sizeof(struct trackline)); if(tracky < (tune->tracklen)-step) tracky += step; else tracky = (tune->tracklen)-1; } }else if(currtab == 2){ if(instrument[currinstr].length < 256){ // insert new line for(int i = 0; i < icliplen; i++){ struct instrument *in = &instrument[currinstr]; instry++; memmove(&in->line[instry + 1], &in->line[instry + 0], sizeof(struct instrline) * (in->length - instry)); in->length++; in->line[instry].cmd = '0'; in->line[instry].param = 0; // paste to new line memcpy(&instrument[currinstr].line[instry], &iclip[i], sizeof(struct instrline)); } } //if(instry < instrument[currinstr].length-1) instry++; } break; // copy everything in the current phrase or instrument into the next free one case '^': if(currtab == 1){ f = nextfreetrack(); memcpy(&tune->trk[f], &tune->trk[currtrack], sizeof(struct track)); currtrack = f; }else if(currtab == 2){ f = nextfreeinstr(); memcpy(&instrument[f], &instrument[currinstr], sizeof(struct instrument)); currinstr = f; } break; // TODO: Y and P can be removed after we make visual mode // copy whole phrase or instrument case 'Y': if(currtab == 1){ memcpy(&tclip, &tune->trk[currtrack], sizeof(struct track)); }else if(currtab == 2){ memcpy(&iclip, &instrument[currinstr], sizeof(struct instrument)); } break; // paste whole phrase or instrument case 'P': if(currtab == 1){ memcpy(&tune->trk[currtrack], &tclip, sizeof(struct track)); }else if(currtab == 2){ memcpy(&instrument[currinstr], &iclip, sizeof(struct instrument)); } break; /* delete line */ // TODO: clean this SHIT up // TODO: add an ACT_ function for delete case 'd': c = nextchar(); switch(c){ case 'd': act_delline(); break; case 'k': if(currtab == 2){ struct instrument *in = &instrument[currinstr]; instry--; int i; for(i=0; i<2; i++){ if(in->length > 1){ memmove(&in->line[instry + 0], &in->line[instry + 1], sizeof(struct instrline) * (in->length - instry - 1)); in->length--; if(instry >= in->length) instry = in->length - 1; } } }else if(currtab == 0){ songy--; int i; for(i=0; i<2; i++){ if(tune->songlen > 1){ memmove(&tune->sng[songy + 0], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); tune->songlen--; if(songy >= tune->songlen) songy = tune->songlen - 1; } } } break; case 'j': if(currtab == 2){ struct instrument *in = &instrument[currinstr]; int i; for(i=0; i<2; i++){ if(in->length > 1){ memmove(&in->line[instry + 0], &in->line[instry + 1], sizeof(struct instrline) * (in->length - instry - 1)); in->length--; if(instry >= in->length) instry = in->length - 1; } } }else if(currtab == 0){ int i; for(i=0; i<2; i++){ if(tune->songlen > 1){ memmove(&tune->sng[songy + 0], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); tune->songlen--; if(songy >= tune->songlen) songy = tune->songlen - 1; } } } break; } break; /* undo */ case 'u': act_undo(); /* Clear */ case 'x': act_clronething(); break; case 'X': act_clritall(); break; case ENTER: if(currtab != 2){ if(currtab == 1){ silence(); startplaytrack(currtrack); }else if(currtab == 0){ silence(); startplaysong(songy); } } break; case 'Z': c = nextchar(); switch(c){ case 'Z': lft_savefile(filename); erase(); refresh(); endwin(); exit(0); break; case 'Q': erase(); refresh(); endwin(); exit(0); break; } break; /* Enter command mode */ case ':': cmdlinemode(); break; case ' ': silence(); tune->plonked = 0; break; // TODO: make an act_ function for '`' case '`': if(currtab == 0){ int t = tune->sng[songy].track[songx / 4]; if(t) currtrack = t; currtab = 1; if(playtrack){ startplaytrack(currtrack); } }else if((currtab == 1) && ((trackx == 2) || (trackx == 3))){ int i = tune->trk[currtrack].line[tracky].instr; if(i) currinstr = i; currtab = 2; } else if(currtab == 1){ currtab = 0; }else if(currtab == 2){ currtab = 1; } break; /* Enter insert mode */ case 'i': insertmode(); break; /* Enter visual mode */ case 'v': visualmode(); break; /* Enter visual line mode */ case 'V': visuallinemode(); break; /* enter jammer mode */ case CTRL('A'): jammermode(); break; /* Add new line and enter insert mode */ case 'o': act_addline(); insertmode(); break; case 'h': case KEY_LEFT: act_mvleft(); break; case 'j': case KEY_DOWN: act_mvdown(); break; case 'k': case KEY_UP: act_mvup(); break; case 'l': case KEY_RIGHT: act_mvright(); break; case '<': if(octave) octave--; break; case '>': if(octave < 8) octave++; break; case '{': if(currtrack > 1) currtrack--; break; case '}': if(currtrack < 255) currtrack++; break; case 'J': if(currtab == 0){ if( (songx%4) < 2){ act_trackdec(); }else{ act_transpdec(); } }else if(currtab == 1){ switch(trackx){ case 0: act_notedec(); break; case 1: act_octavedec(); break; case 2: act_instrdec(); break; case 3: act_instrdec(); break; case 4: act_fxdec(); break; case 5: case 6: act_paramdec(); break; case 7: act_fxdec(); break; case 8: case 9: act_paramdec(); break; default: setdisplay("in J"); break; } }else if(currtab == 2){ switch(instrx){ case 0: act_fxdec(); break; case 1: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_notedec(); }else{ act_paramdec(); } break; case 2: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_notedec(); }else{ act_paramdec(); } break; } } break; case 'K': if(currtab == 0){ if( (songx%4) < 2){ act_trackinc(); }else{ act_transpinc(); } }else if(currtab == 1){ switch(trackx){ case 0: act_noteinc(); break; case 1: act_octaveinc(); break; case 2: act_instrinc(); break; case 3: act_instrinc(); break; case 4: act_fxinc(); break; case 5: case 6: act_paraminc(); break; case 7: act_fxinc(); break; case 8: case 9: act_paraminc(); break; default: setdisplay("in K"); break; } }else if(currtab == 2){ switch(instrx){ case 0: act_fxinc(); break; case 1: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_noteinc(); }else{ act_paraminc(); } break; case 2: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_noteinc(); }else{ act_paraminc(); } break; } } break; case CTRL('J'): if(currtab == 2){ act_viewinstrdec(); }else if(currtab == 1){ act_viewtrackdec(); } break; case CTRL('K'): if(currtab == 2){ act_viewinstrinc(); }else if(currtab == 1){ act_viewtrackinc(); } break; case '[': act_viewinstrdec(); break; case ']': act_viewinstrinc(); break; case '(': callbacktime++; break; case ')': callbacktime--; break; case '-': if(step > 0) step--; break; case '=': if(step < 0x0f) step++; break; case CTRL('H'): currtab--; if(currtab < 0) currtab = 2; break; case CTRL('L'): currtab++; currtab %= 3; break; case KEY_TAB: currtab++; currtab %= 3; break; case CTRL('U'): act_bigmvup(); break; case CTRL('D'): act_bigmvdown(); break; /*case CTRL('P'): vimode = false; break;*/ // replace case 'r': _insertc(nextchar()); break; default: break; } // end switch } // end for cmdrepeatnum = 1; cmdrepeat = 0; }