1 /* vi:set ts=4 sts=4 sw=4 noexpandtab: */
3 /* welcome to gui.c, enjoy your stay 8-) */
13 static char *notenames
[] = {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "H-"};
16 // ** LOCAL FUNCTIONS ** //
18 int _char2int(char ch
);
22 // ** END LOCAL DECLARATIONS ** //
25 char cmdstr
[500] = "";
28 int currmode
= PM_NORMAL
;
31 int tracklen
= TRACKLEN
;
43 // 0 is like a blank command
44 char *validcmds
= "0dfi@smtvw~+=*";
56 /* hexinc and hexdec wrap around */
58 return (x
>= 0 && x
<= 14)? x
+1 : 0;
61 return (x
>= 1 && x
<= 15)? x
-1 : 15;
64 /* Wait for the next keyboard char and return it.
65 * This stops the screen from being updated. */
79 int _char2int(char ch
){
90 if(c
== '-' || c
== KEY_DC
) return 0;
92 s
= strchr(keymap
[0], c
);
94 f
= (s
- (keymap
[0])) + octave
* 12 + 1;
96 s
= strchr(keymap
[1], c
);
98 f
= (s
- (keymap
[1])) + octave
* 12 + 12 + 1;
102 if(f
> 12 * 9 + 1) return -1;
106 void initsonglines(void){
107 for(int i
=0; i
< songlen
; i
++){
108 memmove(&song
[i
+ 0], &song
[i
+ 1], sizeof(struct songline
) * (songlen
- i
- 1));
110 song
[0].track
[i
] = 0x000;
111 song
[0].transp
[i
] = 0x000;
117 void inittracks(void){
118 for(int i
=0; i
< 256; i
++){
119 for(int j
=0; j
< TRACKLEN
; j
++){
120 track
[i
].line
[j
].note
= 0x0000;
121 track
[i
].line
[j
].instr
= 0x0000;
122 for(int k
=0; k
< 2; k
++){
123 track
[i
].line
[j
].cmd
[k
] = 0x0000;
124 track
[i
].line
[j
].param
[k
] = 0x0000;
130 void initinstrs(void){
131 for(int i
=1; i
< 256; i
++){
132 instrument
[i
].length
= 1;
133 instrument
[i
].line
[0].cmd
= '0';
134 instrument
[i
].line
[0].param
= 0;
138 void readsong(int pos
, int ch
, u8
*dest
){
139 dest
[0] = song
[pos
].track
[ch
];
140 dest
[1] = song
[pos
].transp
[ch
];
143 void readtrack(int num
, int pos
, struct trackline
*tl
){
144 tl
->note
= track
[num
].line
[pos
].note
;
145 tl
->instr
= track
[num
].line
[pos
].instr
;
146 tl
->cmd
[0] = track
[num
].line
[pos
].cmd
[0];
147 tl
->cmd
[1] = track
[num
].line
[pos
].cmd
[1];
148 tl
->param
[0] = track
[num
].line
[pos
].param
[0];
149 tl
->param
[1] = track
[num
].line
[pos
].param
[1];
152 void readinstr(int num
, int pos
, u8
*il
){
153 if(pos
>= instrument
[num
].length
){
157 il
[0] = instrument
[num
].line
[pos
].cmd
;
158 il
[1] = instrument
[num
].line
[pos
].param
;
169 //if(setlocale(LC_CTYPE,"en_US.utf8") != NULL) setdisplay("UTF-8 enabled!");
171 // don't send newline on Enter key, and don't echo chars to the screen.
175 // make sure behaviour for special keys like ^H isn't overridden
176 keypad(stdscr
, FALSE
);
178 // nodelay() makes getch() non-blocking. This will cause the cpu to spin
179 // whenever we use getch() in a loop. This is necessary so the screen will
180 // update when you aren't pressing keys. halfdelay()'s minimum timeout time
181 // is one tenth of a second, which is too long for our purposes.
183 // Right now we are calling usleep() whenever we use getch() in a loop so
184 // the cpu won't spin. This solution isn't the best, for three reasons:
185 // 1. We're still wasting a little bit of cpu!!!!!
186 // 2. It is possible to enter keys faster than the usleep time. It's
187 // especially easy to do this by setting your key repeat rate really
188 // high and moving up or down, and the screen will lag a little.
189 // 3. nextchar() prevents the screen from being updated.
191 // Because of these two small problems, maybe we should eventually use
192 // keyboard interrupts to trigger gui events. I haven't done any research
194 nodelay(stdscr
, TRUE
);
201 void drawsonged(int x
, int y
, int height
){
206 if(songy
< songoffs
) songoffs
= songy
;
207 if(songy
>= songoffs
+ height
) songoffs
= songy
- height
+ 1;
209 for(i
= 0; i
< songlen
; i
++){
210 if(i
>= songoffs
&& i
- songoffs
< height
){
211 move(y
+ i
- songoffs
, x
+ 0);
212 if(i
== songy
) attrset(A_BOLD
);
214 snprintf(buf
, sizeof(buf
), "%02x", i
);
216 if(i
== 0){ addch(ACS_ULCORNER
); }
217 else if(i
== songlen
-1){ addch(ACS_LLCORNER
); }
218 else if(i
%4 == 0){ addch(ACS_LTEE
); }
219 else if(i
< songlen
-1){ addch(ACS_VLINE
); }
222 // should this line be highlighted?
223 //if( (match = list_contains(highlightlines, findu8, &i)) ){
224 if( currtab
== 0 && currmode
== PM_VISUALLINE
&&
225 ((i
<= highlight_firstline
&& i
>= highlight_lastline
)
226 || (i
>= highlight_firstline
&& i
<= highlight_lastline
)) ){
231 for(j
= 0; j
< 4; j
++){
232 snprintf(buf
, sizeof(buf
), "%02x:%02x", song
[i
].track
[j
], song
[i
].transp
[j
]);
234 if(j
!= 3) addch(' ');
236 if(playsong
&& songpos
== (i
+ 1)){
245 void drawtracked(int x
, int y
, int height
){
249 if(tracky
< trackoffs
) trackoffs
= tracky
;
250 if(tracky
>= trackoffs
+ height
) trackoffs
= tracky
- height
+ 1;
252 for(i
= 0; i
< tracklen
; i
++){
253 if(i
>= trackoffs
&& i
- trackoffs
< height
){
254 move(y
+ i
- trackoffs
, x
+ 0);
255 if(i
== tracky
) attrset(A_BOLD
);
257 snprintf(buf
, sizeof(buf
), "%02x", i
);
260 if(i
== 0){ addch(ACS_LLCORNER
); }
261 else if(i
== 1){ addch(ACS_ULCORNER
); }
262 else if(i
== tracklen
-1){ addch(ACS_LLCORNER
); }
263 else if(i
%4 == 0){ addch(ACS_LTEE
); }
264 else if(i
< tracklen
-1){ addch(ACS_VLINE
); }
267 // should this line be highlighted?
268 //if( (match = list_contains(highlightlines, findu8, &i)) ){
269 if(currtab
== 1 && currmode
== PM_VISUALLINE
270 && ((i
<= highlight_firstline
&& i
>= highlight_lastline
)
271 || (i
>= highlight_firstline
&& i
<= highlight_lastline
)) ){
275 if (currtab
== 1 && currmode
== PM_VISUAL
)
278 if(track
[currtrack
].line
[i
].note
){
279 snprintf(buf
, sizeof(buf
), "%s%d",
280 notenames
[(track
[currtrack
].line
[i
].note
- 1) % 12],
281 (track
[currtrack
].line
[i
].note
- 1) / 12);
283 snprintf(buf
, sizeof(buf
), "---");
286 snprintf(buf
, sizeof(buf
), " %02x", track
[currtrack
].line
[i
].instr
);
288 for(j
= 0; j
< 2; j
++){
289 if(track
[currtrack
].line
[i
].cmd
[j
]){
290 snprintf(buf
, sizeof(buf
), " %c%02x",
291 track
[currtrack
].line
[i
].cmd
[j
],
292 track
[currtrack
].line
[i
].param
[j
]);
294 snprintf(buf
, sizeof(buf
), " ...");
298 if(playtrack
&& ((i
+ 1) % tracklen
) == trackpos
){
307 void drawinstred(int x
, int y
, int height
){
311 if(instry
>= instrument
[currinstr
].length
) instry
= instrument
[currinstr
].length
- 1;
313 if(instry
< instroffs
) instroffs
= instry
;
314 if(instry
>= instroffs
+ height
) instroffs
= instry
- height
+ 1;
316 for(i
= 0; i
< instrument
[currinstr
].length
; i
++){
317 if(i
>= instroffs
&& i
- instroffs
< height
){
318 move(y
+ i
- instroffs
, x
+ 0);
319 if(i
== instry
) attrset(A_BOLD
);
321 snprintf(buf
, sizeof(buf
), "%02x", i
);
324 if(i
== 0){ addch(ACS_LLCORNER
); }
325 else if(i
== 1){ addch(ACS_ULCORNER
); }
326 else if(i
== instrument
[currinstr
].length
-1){ addch(ACS_LLCORNER
); }
327 else if(i
< instrument
[currinstr
].length
-1){ addch(ACS_VLINE
); }
330 // should this line be highlighted?
331 //if( (match = list_contains(highlightlines, findu8, &i)) ){
332 if( currtab
== 2 && currmode
== PM_VISUALLINE
&&
333 ((i
<= highlight_firstline
&& i
>= highlight_lastline
)
334 || (i
>= highlight_firstline
&& i
<= highlight_lastline
)) ){
338 snprintf(buf
, sizeof(buf
), "%c ", instrument
[currinstr
].line
[i
].cmd
);
340 if(instrument
[currinstr
].line
[i
].cmd
== '+' || instrument
[currinstr
].line
[i
].cmd
== '='){
341 if(instrument
[currinstr
].line
[i
].param
){
342 snprintf(buf
, sizeof(buf
), "%s%d",
343 notenames
[(instrument
[currinstr
].line
[i
].param
- 1) % 12],
344 (instrument
[currinstr
].line
[i
].param
- 1) / 12);
346 snprintf(buf
, sizeof(buf
), "---");
349 snprintf(buf
, sizeof(buf
), "%02x", instrument
[currinstr
].line
[i
].param
);
357 /* main input loop */
361 /*if(currmode == PM_NORMAL){*/
362 if((c
= getch()) != ERR
){
368 cmdrepeatnum
= _char2int(c
);
370 cmdrepeatnum
= (cmdrepeatnum
*10) + _char2int(c
);
379 void setdisplay(char *str
){
384 // display dispmesg in the center of the screen
386 int cx
= (getmaxx(stdscr
)/2)-(strlen(dispmesg
)/2)-1;
387 int cy
= getmaxy(stdscr
)/2;
389 mvaddch(cy
-1, cx
, ACS_ULCORNER
);
390 for(int i
=cx
+1; i
<cx
+strlen(dispmesg
)+1; i
++)
391 mvaddch(cy
-1, i
, ACS_HLINE
);
392 mvaddch(cy
-1, cx
+strlen(dispmesg
)+1, ACS_URCORNER
);
394 mvaddch(cy
, cx
, ACS_VLINE
);
395 mvaddstr(cy
, cx
+1, dispmesg
);
396 mvaddch(cy
, cx
+strlen(dispmesg
)+1, ACS_VLINE
);
398 mvaddch(cy
+1, cx
, ACS_LLCORNER
);
399 for(int i
=cx
+1; i
<cx
+strlen(dispmesg
)+1; i
++)
400 mvaddch(cy
+1, i
, ACS_HLINE
);
401 mvaddch(cy
+1, cx
+strlen(dispmesg
)+1, ACS_LRCORNER
);
407 int songcols
[] = {0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22};
408 int trackcols
[] = {0, 2, 4, 5, 7, 8, 9, 11, 12, 13};
409 int instrcols
[] = {0, 2, 3};
413 attrset(A_UNDERLINE
);
414 mvaddstr(0, 0, "PINEAPPLEtRACKER");
418 mvaddch(0, 31, ACS_ULCORNER
);
419 snprintf(buf
, sizeof(buf
), "%02x{}", currtrack
);
420 mvaddstr(0, 32, buf
);
421 drawtracked(29, 1, lines
- 2);
423 // display instrument num
424 mvaddch(0, 51, ACS_ULCORNER
);
425 snprintf(buf
, sizeof(buf
), "%02x[]", currinstr
);
426 mvaddstr(0, 52, buf
);
427 drawinstred(49, 1, lines
- 2);
429 mvaddstr(1, 0, "Song");
430 drawsonged(0, 1, lines
- 2);
432 // just a wild guess here..
433 tempo
= callbacktime
* (-1) + 300;
435 mvaddch(0, 17, ACS_DEGREE
);
436 snprintf(buf
, sizeof(buf
), "%d()", tempo
);
437 mvaddstr(0, 18, buf
);
440 mvaddch(0, 24, ACS_PI
);
441 snprintf(buf
, sizeof(buf
), "%d<>", octave
);
442 mvaddstr(0, 25, buf
);
444 // display step amount
445 mvaddstr(0, 60, "step -=");
446 snprintf(buf
, sizeof(buf
), "%0x", step
);
447 mvaddstr(0, 68, buf
);
450 mvaddstr(2, 60, "comment:");
451 snprintf(buf
, sizeof(buf
), "%s", comment
);
452 mvaddstr(3, 60, buf
);
454 if(currmode
== PM_NORMAL
){
455 mvaddstr(getmaxy(stdscr
)-1, 0, filename
);
456 if(!saved
&& currmode
!= PM_INSERT
){
467 if(currmode
== PM_INSERT
){
470 move(getmaxy(stdscr
)-1,0);
472 mvaddstr(getmaxy(stdscr
)-1, 0, "-- INSERT --");
473 }else if(currmode
== PM_VISUAL
){
476 move(getmaxy(stdscr
)-1,0);
478 mvaddstr(getmaxy(stdscr
)-1, 0, "-- VISUAL --");
479 }else if(currmode
== PM_VISUALLINE
){
482 move(getmaxy(stdscr
)-1,0);
484 mvaddstr(getmaxy(stdscr
)-1, 0, "-- VISUAL LINE --");
485 }else if(currmode
== PM_JAMMER
){
488 move(getmaxy(stdscr
)-1,0);
490 mvaddstr(getmaxy(stdscr
)-1, 0, "-- JAMMER --");
491 }else if(currmode
== PM_CMDLINE
){
494 move(getmaxy(stdscr
)-1,0);
496 mvaddstr(getmaxy(stdscr
) - 1, 0, cmdstr
);
497 }else if(infinitemsg
!= NULL
){
498 move(getmaxy(stdscr
)-1,0);
500 mvaddstr(getmaxy(stdscr
) - 1, 0, infinitemsg
);
505 move(1 + songy
- songoffs
, 0 + 4 + songcols
[songx
]);
508 move(1 + tracky
- trackoffs
, 29 + 4 + trackcols
[trackx
]);
511 move(1 + instry
- instroffs
, 49 + 4 + instrcols
[instrx
]);
524 // don't treat the escape key like a meta key