1
0
mirror of https://git.code.sf.net/p/fuse-emulator/fuse synced 2026-01-27 01:41:34 +03:00
Files
fuse/ui/widget/browse.c
2016-10-24 11:45:18 +11:00

235 lines
5.4 KiB
C

/* browse.c: tape browser widget
Copyright (c) 2002-2004 Philip Kendall
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
E-mail: philip-fuse@shadowmagic.org.uk
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_LIB_GLIB
#include <glib.h>
#else /* #ifdef HAVE_LIB_GLIB */
#include <libspectrum.h>
#endif /* #ifdef HAVE_LIB_GLIB */
#include "fuse.h"
#include "tape.h"
#include "widget_internals.h"
#define MAX_BLOCK_DESC 30
/* The descriptions of the blocks */
static GSList *blocks;
/* How many blocks we have in total */
size_t block_count;
/* Which block is shown on the top line of the widget */
static int top_line;
/* Which block is currently highlighted */
static int highlight;
static void show_blocks( void );
static void add_block_description( libspectrum_tape_block *block,
void *user_data );
static void free_description( gpointer data, gpointer user_data );
int
widget_browse_draw( void *data GCC_UNUSED )
{
int error;
blocks = NULL; block_count = 0;
error = tape_foreach( add_block_description, &blocks );
if( error ) return error;
widget_dialog_with_border( 1, 2, 30, 20 );
widget_printstring( 10, 16, WIDGET_COLOUR_TITLE, "Browse Tape" );
widget_display_lines( 2, 1 );
highlight = tape_get_current_block();
top_line = highlight - 8; if( top_line < 0 ) top_line = 0;
show_blocks();
return 0;
}
static void
add_block_description( libspectrum_tape_block *block, void *user_data )
{
char data_detail[MAX_BLOCK_DESC];
GSList **ptr = user_data;
char *buffer;
tape_block_details( data_detail, MAX_BLOCK_DESC, block );
buffer = malloc( MAX_BLOCK_DESC ); if( !buffer ) return;
libspectrum_tape_block_description( buffer, MAX_BLOCK_DESC, block );
if( strlen( data_detail ) ) strcpy( buffer, data_detail );
(*ptr) = g_slist_append( *ptr, buffer );
block_count++;
}
static void
show_blocks( void )
{
size_t i; char buffer[64];
GSList *ptr;
int numpos = g_slist_length( blocks );
if( numpos < 10 ) {
numpos = 24;
} else if( numpos < 100 ) {
numpos = 32;
} else {
numpos = 40;
}
widget_rectangle( 9, 2*8, 30*8-2, 19*8, WIDGET_COLOUR_BACKGROUND );
for( i = 0, ptr = g_slist_nth( blocks, top_line );
i < 18 && ptr;
i++, ptr = ptr->next ) {
int colour = WIDGET_COLOUR_FOREGROUND;
if( top_line + i == highlight )
widget_rectangle( 9, i*8+24, 30*8-2, 1*8, WIDGET_COLOUR_HIGHLIGHT );
sprintf( buffer, "%lu", (unsigned long)( top_line + i + 1 ) );
widget_printstring_right( numpos, i*8+24, colour, buffer );
snprintf( buffer, sizeof( buffer ), ": %s", (char *)ptr->data );
widget_printstring( numpos + 1, i*8+24, colour, buffer );
}
widget_display_lines( 3, 19 );
}
void
widget_browse_keyhandler( input_key key )
{
switch( key ) {
#if 0
case INPUT_KEY_Resize: /* Fake keypress used on window resize */
widget_browse_draw( NULL );
break;
#endif
case INPUT_KEY_Escape:
case INPUT_JOYSTICK_FIRE_2:
widget_end_widget( WIDGET_FINISHED_CANCEL );
return;
case INPUT_KEY_Down:
case INPUT_KEY_6:
case INPUT_KEY_j:
case INPUT_JOYSTICK_DOWN:
if( highlight < block_count - 1 ) {
highlight++;
if( highlight >= top_line + 18 ) top_line += 18;
show_blocks();
}
break;
case INPUT_KEY_Up:
case INPUT_KEY_7:
case INPUT_KEY_k:
case INPUT_JOYSTICK_UP:
if( highlight > 0 ) {
highlight--;
if( highlight < top_line )
{
top_line -= 18;
if( top_line < 0 ) top_line = 0;
}
show_blocks();
}
break;
case INPUT_KEY_Page_Up:
highlight -= 18; if( highlight < 0 ) highlight = 0;
top_line -= 18; if( top_line < 0 ) top_line = 0;
show_blocks();
break;
case INPUT_KEY_Page_Down:
highlight += 18;
if( highlight >= block_count ) highlight = block_count - 1;
top_line += 18;
if( top_line >= block_count ) {
top_line = block_count - 18;
if( top_line < 0 ) top_line = 0;
}
show_blocks();
break;
case INPUT_KEY_Home:
highlight = top_line = 0;
show_blocks();
break;
case INPUT_KEY_End:
highlight = block_count - 1;
top_line = block_count - 18; if( top_line < 0 ) top_line = 0;
show_blocks();
break;
case INPUT_KEY_Return:
case INPUT_KEY_KP_Enter:
case INPUT_JOYSTICK_FIRE_1:
widget_end_widget( WIDGET_FINISHED_OK );
return;
default: /* Keep gcc happy */
break;
}
}
int
widget_browse_finish( widget_finish_state finished )
{
g_slist_foreach( blocks, free_description, NULL );
g_slist_free( blocks );
if( finished == WIDGET_FINISHED_OK ) {
if( highlight != -1 ) tape_select_block( highlight );
widget_end_all( WIDGET_FINISHED_OK );
}
return 0;
}
static void
free_description( gpointer data, gpointer user_data )
{
free( data );
}