diff options
Diffstat (limited to 'muc.c')
-rw-r--r-- | muc.c | 298 |
1 files changed, 298 insertions, 0 deletions
@@ -0,0 +1,298 @@ +#include <curses.h> +#include <stdio.h> + +/* Curses based powwow movie player. + * Author: Steve Slaven - http://hoopajoo.net + */ + +#define JUMP_SMALL 1000 +#define JUMP_BIG 5000 +#define MAX_SPEED 20 + +/* Speed is a variable from 0 - 9, where 5 = normal and > 5 is faster */ +int main( int argc, char *argv[] ) { + WINDOW *text, *status; + int speed = 5; + int key, sleep, orig, i, color, looping, cursx, cursy; + FILE *in; + char line[ 1000 ], *displine, action[ 100 ]; + long curr_pos, file_size, new_pos; + + if( argc < 2 ) { + fprintf( stderr, + "mud cinema v%s\n" + "Author: Steve Slaven - http://hoopajoo.net\n" + "\n" + "Usage: muc file\n" + "\n" + "file should be a #movie file generated in powwow\n", + VERSION ); + exit( 1 ); + } + + /* Validate our file passed */ + if( ! ( in = fopen( argv[ 1 ], "ro" ) ) ) { + perror( "Unable to open file" ); + exit( 1 ); + } + + /* Get file size */ + fseek( in, 0, SEEK_END ); + file_size = ftell( in ); + rewind( in ); + + /* Setup some basic stuff */ + initscr(); + cbreak(); + noecho(); + + /* Initialize color */ + start_color(); + + /* this *should* init the default ansi colors... :/ */ + for( i = 0; i < 16; i++ ) + init_pair( i, i, COLOR_BLACK ); + + /* Create our windows, a status bar on the bottom and a + scrollable window on top */ + text = newwin( LINES - 2, COLS, 0, 0 ); + status = newwin( 2, COLS, LINES - 2, 0 ); + + keypad( stdscr, TRUE ); + scrollok( text, TRUE ); + leaveok( text, TRUE ); + leaveok( status, TRUE ); + /* wattron( status, A_BOLD ); */ + wbkgd( status, A_REVERSE ); + + /* instructions */ + mvwprintw( status, 0, 0, + "(q)uit (r)ew small (R)ew large (f)orw small (F)orw large (0-9)(+)(-) speed" ); + + /* Main loop */ + refresh(); + timeout( 0 ); + looping = 1; + while( looping ) { + bzero( line, 1000 ); + fgets( line, 1000, in ); + + /* get file pos */ + new_pos = curr_pos = ftell( in ); + + /* handle disp or other */ + displine = NULL; + if( strncmp( line, "line", 4 ) == 0 ) { + displine = &line[ 5 ]; + sleep = 0; + }else if( strncmp( line, "prompt", 5 ) == 0 ) { + displine = &line[ 7 ]; + /* Munch newline */ + line[ strlen( line ) - 1 ] = 0; + sleep = 0; + }else if( strncmp( line, "sleep", 5 ) == 0 ) { + sscanf( line, "sleep %d", &sleep ); + }else if( line[ 0 ] == '#' ) { /* custom extension for commenting logs */ + sscanf( line, "#%d", &sleep ); + if( sleep > 0 ) + sleep *= 100; /* comment sleep is in seconds */ + + /* Skip to space */ + displine = line; + while( displine[ 0 ] != ' ' && displine[ 0 ] != 0 ) { + displine++; + } + displine++; + + /* We will go ahead and display it here, in bold, then + null out displine so it will not display later */ + wattron( text, A_REVERSE ); + wprintw( text, "##==> %s", displine ); + wattroff( text, A_REVERSE ); + displine = NULL; + } + + /* suck out action for display */ + sscanf( line, "%100s", action ); + + /* Modify sleep time according to speed, zero is fast as you can go, 1 == pause */ + orig = sleep; + if( speed > 5 ) { + sleep /= ( ( speed - 5 ) * 2 ); + }else{ + sleep *= ( 6 - speed ); + } + + /* Handle pause */ + if( speed == 0 ) + sleep = -1; + + /* handle insane speed */ + /* if( speed == 9 ) + sleep = 0; */ + + /* Setup sleeptime for getch() */ + timeout( sleep ); + + /* Update status line */ + mvwprintw( status, 1, 0, + "%7d/%7d/%2d%% Speed: %d (5=normal,0=pause) Cmd: %-6s (%d/%d)\n", + curr_pos, file_size, curr_pos * 100 / file_size, + speed, action, sleep, orig ); + wrefresh( status ); + + /* Disp if we found an offset to do */ + if( displine != NULL ) { + /* handle converting ansi colors to curses attrs */ + for( i = 0; i < strlen( displine ); i++ ) { + if( displine[ i ] == 0x1b ) { + /* this is super crappy ansi color decoding */ + i++; + if( strncmp( &displine[ i ], "[3", 2 ) == 0 ) { + /* start a color */ + sscanf( &displine[ i ], "[3%dm", &color ); + wattron( text, COLOR_PAIR( color ) ); + }else if( strncmp( &displine[ i ], "[9", 2 ) == 0 ) { + /* start a high color */ + sscanf( &displine[ i ], "[9%dm", &color ); + wattron( text, COLOR_PAIR( color ) ); + wattron( text, A_BOLD ); + }else if( strncmp( &displine[ i ], "[1", 2 ) == 0 ) { + wattron( text, A_BOLD ); + }else if( strncmp( &displine[ i ], "[0", 2 ) == 0 ) { + /* end color, color will (should?) still be set from last color */ + /* wattr_off( text, COLOR_PAIR( color ), NULL ); */ + wattrset( text, A_NORMAL ); + } + /* eat chars to the next m */ + while( displine[ i ] != 'm' && displine != 0 ) + i++; + }else{ + waddch( text, (unsigned char)displine[ i ] ); + } + } + } + + /* check if we are at EOF and override timeout */ + if( curr_pos == file_size ) { + wprintw( text, "\n**** END ***\n" ); + timeout( -1 ); + } + + wrefresh( text ); + + /* Move the cursor to the end of the text window, so it looks + like a real session */ + getyx( text, cursy, cursx ); + move( cursy, cursx ); + + key = getch(); + + switch( key ) { + case 'Q': + case 'q': + looping = 0; + break; + case '+': + case '=': + speed++; + break; + case '-': + speed--; + break; + + case '1': + speed = 1; + break; + case '2': + speed = 2; + break; + case '3': + speed = 3; + break; + case '4': + speed = 4; + break; + case '5': + speed = 5; + break; + case '6': + speed = 6; + break; + case '7': + speed = 7; + break; + case '8': + speed = 8; + break; + case '9': + speed = 9; + break; + case '0': + speed = 0; + break; + + case 'r': + new_pos -= JUMP_SMALL; + break; + case 'R': + new_pos -= JUMP_BIG; + break; + case 'f': + new_pos += JUMP_SMALL; + break; + case 'F': + new_pos += JUMP_BIG; + break; + + default: + break; + } + + /* Validate speed is ok */ + if( speed > MAX_SPEED ) + speed = MAX_SPEED; + + if( speed < 0 ) + speed = 0; + + /* Check if we are moving the seek */ + if( new_pos != curr_pos ) { + wattron( text, A_BOLD ); + if( new_pos > file_size ) + new_pos = file_size; + + if( new_pos < 0 ) + new_pos = 0; + + wprintw( text, + "\n=============\nMoving from %d to file offset %d\n", + curr_pos, new_pos ); + + /* calcs offsets because we may want to seek to + 0, which using SEEK_CUR won't let us do without + some other error checking that I don't want to do */ + fseek( in, new_pos, SEEK_SET ); + + /* read to next newline so we don't break up + lines seeking around */ + fgets( line, 1000, in ); + new_pos = ftell( in ); + + /* Make a note of moving */ + wprintw( text, + "Final offset after adjusting for newline: %d (%d)\n=============\n", + new_pos, new_pos - curr_pos ); + wattroff( text, A_BOLD ); + } + } + + /* Cleanup */ + delwin( text ); + delwin( status ); + endwin(); + + fclose( in ); + + return( 0 ); +} |