[Fuse-for-macosx-commits] SF.net SVN: fuse-for-macosx: [528] vendor/fuse-emulator/current/fuse
Brought to you by:
fredm
|
From: <fr...@us...> - 2008-05-07 12:25:37
|
Revision: 528
http://fuse-for-macosx.svn.sourceforge.net/fuse-for-macosx/?rev=528&view=rev
Author: fredm
Date: 2008-05-07 05:25:42 -0700 (Wed, 07 May 2008)
Log Message:
-----------
To prepare to load . into vendor/fuse-emulator/current, perform 20
renames.
* vendor/fuse-emulator/current/fuse/ui/widget/fuse.font.sbf: Renamed
from vendor/fuse-emulator/current/fuse/widget/fuse.font.sbf.
* vendor/fuse-emulator/current/fuse/ui/widget/debugger.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/debugger.c.
* vendor/fuse-emulator/current/fuse/ui/widget/browse.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/browse.c.
* vendor/fuse-emulator/current/fuse/ui/widget/error.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/error.c.
* vendor/fuse-emulator/current/fuse/ui/widget/filesel.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/filesel.c.
* vendor/fuse-emulator/current/fuse/ui/widget/widget.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/widget.c.
* vendor/fuse-emulator/current/fuse/ui/widget/widget.h: Renamed from
vendor/fuse-emulator/current/fuse/widget/widget.h.
* vendor/fuse-emulator/current/fuse/ui/widget/select.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/select.c.
* vendor/fuse-emulator/current/fuse/ui/widget/widget_internals.h:
Renamed from
vendor/fuse-emulator/current/fuse/widget/widget_internals.h.
* vendor/fuse-emulator/current/fuse/ui/widget/Makefile.am: Renamed from
vendor/fuse-emulator/current/fuse/widget/Makefile.am.
* vendor/fuse-emulator/current/fuse/ui/widget/picture.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/picture.c.
* vendor/fuse-emulator/current/fuse/ui/widget/query.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/query.c.
* vendor/fuse-emulator/current/fuse/ui/widget/menu.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/menu.c.
* vendor/fuse-emulator/current/fuse/ui/widget/memory.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/memory.c.
* vendor/fuse-emulator/current/fuse/ui/widget/mkfusefont.pl: Renamed
from vendor/fuse-emulator/current/fuse/widget/mkfusefont.pl.
* vendor/fuse-emulator/current/fuse/ui/widget/options-header.pl:
Renamed from
vendor/fuse-emulator/current/fuse/widget/options-header.pl.
* vendor/fuse-emulator/current/fuse/ui/widget/options.pl: Renamed from
vendor/fuse-emulator/current/fuse/widget/options.pl.
* vendor/fuse-emulator/current/fuse/ui/widget/pokefinder.c: Renamed
from vendor/fuse-emulator/current/fuse/widget/pokefinder.c.
* vendor/fuse-emulator/current/fuse/ui/widget/text.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/text.c.
* vendor/fuse-emulator/current/fuse/ui/widget/roms.c: Renamed from
vendor/fuse-emulator/current/fuse/widget/roms.c.
Added Paths:
-----------
vendor/fuse-emulator/current/fuse/ui/widget/
vendor/fuse-emulator/current/fuse/ui/widget/Makefile.am
vendor/fuse-emulator/current/fuse/ui/widget/browse.c
vendor/fuse-emulator/current/fuse/ui/widget/debugger.c
vendor/fuse-emulator/current/fuse/ui/widget/error.c
vendor/fuse-emulator/current/fuse/ui/widget/filesel.c
vendor/fuse-emulator/current/fuse/ui/widget/fuse.font.sbf
vendor/fuse-emulator/current/fuse/ui/widget/memory.c
vendor/fuse-emulator/current/fuse/ui/widget/menu.c
vendor/fuse-emulator/current/fuse/ui/widget/mkfusefont.pl
vendor/fuse-emulator/current/fuse/ui/widget/options-header.pl
vendor/fuse-emulator/current/fuse/ui/widget/options.pl
vendor/fuse-emulator/current/fuse/ui/widget/picture.c
vendor/fuse-emulator/current/fuse/ui/widget/pokefinder.c
vendor/fuse-emulator/current/fuse/ui/widget/query.c
vendor/fuse-emulator/current/fuse/ui/widget/roms.c
vendor/fuse-emulator/current/fuse/ui/widget/select.c
vendor/fuse-emulator/current/fuse/ui/widget/text.c
vendor/fuse-emulator/current/fuse/ui/widget/widget.c
vendor/fuse-emulator/current/fuse/ui/widget/widget.h
vendor/fuse-emulator/current/fuse/ui/widget/widget_internals.h
Removed Paths:
-------------
vendor/fuse-emulator/current/fuse/widget/Makefile.am
vendor/fuse-emulator/current/fuse/widget/browse.c
vendor/fuse-emulator/current/fuse/widget/debugger.c
vendor/fuse-emulator/current/fuse/widget/error.c
vendor/fuse-emulator/current/fuse/widget/filesel.c
vendor/fuse-emulator/current/fuse/widget/fuse.font.sbf
vendor/fuse-emulator/current/fuse/widget/memory.c
vendor/fuse-emulator/current/fuse/widget/menu.c
vendor/fuse-emulator/current/fuse/widget/mkfusefont.pl
vendor/fuse-emulator/current/fuse/widget/options-header.pl
vendor/fuse-emulator/current/fuse/widget/options.pl
vendor/fuse-emulator/current/fuse/widget/picture.c
vendor/fuse-emulator/current/fuse/widget/pokefinder.c
vendor/fuse-emulator/current/fuse/widget/query.c
vendor/fuse-emulator/current/fuse/widget/roms.c
vendor/fuse-emulator/current/fuse/widget/select.c
vendor/fuse-emulator/current/fuse/widget/text.c
vendor/fuse-emulator/current/fuse/widget/widget.c
vendor/fuse-emulator/current/fuse/widget/widget.h
vendor/fuse-emulator/current/fuse/widget/widget_internals.h
Copied: vendor/fuse-emulator/current/fuse/ui/widget/Makefile.am (from rev 527, vendor/fuse-emulator/current/fuse/widget/Makefile.am)
===================================================================
--- vendor/fuse-emulator/current/fuse/ui/widget/Makefile.am (rev 0)
+++ vendor/fuse-emulator/current/fuse/ui/widget/Makefile.am 2008-05-07 12:25:42 UTC (rev 528)
@@ -0,0 +1,77 @@
+## Process this file with automake to produce Makefile.in
+## Copyright (c) 2001,2002 Philip Kendall
+
+## $Id: Makefile.am 3151 2007-09-05 15:41:46Z zubzero $
+
+## 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: phi...@sh...
+
+AUTOMAKE_OPTIONS = foreign
+
+AM_CPPFLAGS = -I$(srcdir)/..
+
+noinst_LIBRARIES = libwidget.a
+
+libwidget_a_SOURCES = \
+ browse.c \
+ debugger.c \
+ error.c \
+ filesel.c \
+ memory.c \
+ menu.c \
+ menu_data.c \
+ options.c \
+ picture.c \
+ pokefinder.c \
+ query.c \
+ roms.c \
+ select.c \
+ text.c \
+ widget.c
+
+INCLUDES = @GTK_CFLAGS@ @GLIB_CFLAGS@ @LIBSPEC_CFLAGS@
+
+BUILT_SOURCES = menu_data.c \
+ options.c \
+ options.h \
+ fuse.font
+
+menu_data.c: $(srcdir)/../perl/cpp-perl.pl $(srcdir)/../menu_data.dat $(srcdir)/../menu_data.pl ../config.h
+ @PERL@ $(srcdir)/../perl/cpp-perl.pl ../config.h $(srcdir)/../menu_data.dat | @PERL@ -I$(srcdir)/../perl $(srcdir)/../menu_data.pl widget > $@.tmp && mv $@.tmp $@
+
+options.c: $(srcdir)/../perl/cpp-perl.pl ../config.h $(srcdir)/options.pl $(srcdir)/../ui/options.dat $(srcdir)/../perl/Fuse.pm $(srcdir)/../perl/Fuse/Dialog.pm
+ @PERL@ $(srcdir)/../perl/cpp-perl.pl ../config.h $(srcdir)/../ui/options.dat | @PERL@ -I$(srcdir)/../perl $(srcdir)/options.pl - > $@.tmp && mv $@.tmp $@
+
+options.h: $(srcdir)/../perl/cpp-perl.pl ../config.h $(srcdir)/options-header.pl $(srcdir)/../ui/options.dat $(srcdir)/../perl/Fuse.pm $(srcdir)/../perl/Fuse/Dialog.pm
+ @PERL@ $(srcdir)/../perl/cpp-perl.pl ../config.h $(srcdir)/../ui/options.dat | @PERL@ -I$(srcdir)/../perl $(srcdir)/options-header.pl - > $@.tmp && mv $@.tmp $@
+
+fuse.font: $(srcdir)/mkfusefont.pl $(srcdir)/fuse.font.sbf
+ @PERL@ $(srcdir)/mkfusefont.pl $(srcdir)/fuse.font.sbf > $@.tmp && mv $@.tmp $@
+
+noinst_HEADERS = widget.h widget_internals.h \
+ options.h options.pl options-header.pl
+
+pkgdata_DATA = fuse.font
+
+EXTRA_DIST = mkfusefont.pl \
+ fuse.font.sbf
+
+CLEANFILES = menu_data.c \
+ options.c \
+ options.h \
+ fuse.font
Copied: vendor/fuse-emulator/current/fuse/ui/widget/browse.c (from rev 527, vendor/fuse-emulator/current/fuse/widget/browse.c)
===================================================================
--- vendor/fuse-emulator/current/fuse/ui/widget/browse.c (rev 0)
+++ vendor/fuse-emulator/current/fuse/ui/widget/browse.c 2008-05-07 12:25:42 UTC (rev 528)
@@ -0,0 +1,226 @@
+/* browse.c: tape browser widget
+ Copyright (c) 2002-2004 Philip Kendall
+
+ $Id: browse.c 3461 2008-01-03 13:42:54Z pak21 $
+
+ 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: phi...@sh...
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.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"
+
+/* 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_print_title( 16, WIDGET_COLOUR_FOREGROUND, "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 )
+{
+ GSList **ptr = user_data;
+
+ char *buffer;
+
+ buffer = malloc( 30 ); if( !buffer ) return;
+ libspectrum_tape_block_description( buffer, 30, block );
+
+ (*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( 2*8, 4*8, 28*8, 18*8, WIDGET_COLOUR_BACKGROUND );
+
+ for( i = 0, ptr = g_slist_nth( blocks, top_line );
+ i < 18 && ptr;
+ i++, ptr = ptr->next ) {
+
+ int colour = ( top_line + i == highlight )
+ ? WIDGET_COLOUR_BACKGROUND : WIDGET_COLOUR_FOREGROUND;
+
+ if( top_line + i == highlight )
+ widget_rectangle( 16, i*8+32, 28*8, 1*8, WIDGET_COLOUR_FOREGROUND );
+
+ sprintf( buffer, "%lu", (unsigned long)( top_line + i + 1 ) );
+ widget_printstring_right( numpos, i*8+32, colour, buffer );
+ snprintf( buffer, sizeof( buffer ), ": %s", (char *)ptr->data );
+ widget_printstring( numpos + 1, i*8+32, colour, buffer );
+ }
+
+ widget_display_lines( 4, 18 );
+}
+
+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:
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ return;
+
+ case INPUT_KEY_Down:
+ case INPUT_KEY_6:
+ case INPUT_KEY_j:
+ 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:
+ 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:
+ 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 );
+}
Copied: vendor/fuse-emulator/current/fuse/ui/widget/debugger.c (from rev 527, vendor/fuse-emulator/current/fuse/widget/debugger.c)
===================================================================
--- vendor/fuse-emulator/current/fuse/ui/widget/debugger.c (rev 0)
+++ vendor/fuse-emulator/current/fuse/ui/widget/debugger.c 2008-05-07 12:25:42 UTC (rev 528)
@@ -0,0 +1,547 @@
+/* debugger.c: The debugger widget
+ Copyright (c) 2002-2004 Philip Kendall, Darren Salt
+
+ $Id: debugger.c 3115 2007-08-19 02:49:14Z fredm $
+
+ 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: phi...@sh...
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <libspectrum.h>
+
+#include "display.h"
+#include "keyboard.h"
+#include "machine.h"
+#include "scld.h"
+#include "ui/uidisplay.h"
+#include "ula.h"
+#include "widget.h"
+#include "debugger/debugger.h"
+#include "widget_internals.h"
+#include "z80/z80.h"
+#include "z80/z80_macros.h"
+#include "zxcf.h"
+
+static enum {
+ DB_REGISTERS, DB_BYTES, DB_TEXT, DB_DISASM, DB_BREAKPT
+} display = DB_REGISTERS;
+
+struct {
+ libspectrum_word value;
+ size_t page;
+ char x, width, column;
+} db_editv = {
+ 0, 0, 255, 0
+};
+
+static libspectrum_word debugger_memaddr;
+static int breakpt_no = 0, breakpt_show = 0;
+
+/* Various data displays */
+static void display_registers( void );
+static void display_bytes( void );
+static void display_text( void );
+static void display_disasm( void );
+static void display_breakpts( void );
+
+/* Scrolling for the data displays */
+static void scroll( int step );
+
+#define LC(X) ( (X)*8 - DISPLAY_BORDER_ASPECT_WIDTH )
+#define LR(Y) ( (Y)*8 - DISPLAY_BORDER_HEIGHT )
+
+static inline const char *format_8_bit( void )
+{
+ return debugger_output_base == 10 ? "%-3d" : "%02X";
+}
+
+static inline const char *format_16_bit( void )
+{
+ return debugger_output_base == 10 ? "%-5d" : "%04X";
+}
+
+int ui_debugger_activate( void )
+{
+ return widget_do( WIDGET_TYPE_DEBUGGER, NULL );
+}
+
+int ui_debugger_deactivate( int interruptible GCC_UNUSED )
+{
+ /* Refresh the Spectrum's display, including the border */
+ display_refresh_all();
+ return widget_end_all( WIDGET_FINISHED_OK );
+}
+
+int ui_debugger_update( void )
+{
+ return widget_debugger_draw( NULL );
+}
+
+int ui_debugger_disassemble( libspectrum_word addr )
+{
+ debugger_memaddr = addr;
+ return 0;
+}
+
+int widget_debugger_draw( void *data )
+{
+ static const char state[][8] = {
+ "Running", "Halted", "Stepped", "Breakpt"
+ };
+ int x;
+ char pbuf[8];
+
+ widget_rectangle( LC(0), LR(0), 40 * 8, 11 * 8 + 4, 1 );
+ widget_rectangle( LC(0), LR(11) + 2, 320, 1, 7 );
+
+ switch ( display ) {
+ case DB_REGISTERS: display_registers(); break;
+ case DB_BYTES: display_bytes(); break;
+ case DB_TEXT: display_text(); break;
+ case DB_DISASM: display_disasm(); break;
+ case DB_BREAKPT: display_breakpts(); break;
+ }
+
+ widget_printstring( LC(0), LR(9) - 4, 6, state[debugger_mode] );
+ widget_printstring( LC(10), LR(9) - 4, 6,
+ "\012S\011ingle step \012C\011ontinue Co\012m\011mand" );
+
+ x = LC(-1);
+ if( display != DB_REGISTERS )
+ x = widget_printstring( x + 8, LR(10), 7, "\012R\011egs" );
+ if( display != DB_BYTES )
+ x = widget_printstring( x + 8, LR(10), 7, "\012B\011ytes" );
+ if( display != DB_TEXT )
+ x = widget_printstring( x + 8, LR(10), 7, "\012T\011ext" );
+ if( display != DB_DISASM )
+ x = widget_printstring( x + 8, LR(10), 7, "\012D\011isasm" );
+ if( display != DB_BREAKPT )
+ x = widget_printstring( x + 8, LR(10), 7, "Brea\012k\011pts" );
+
+ widget_printstring_right( LC(25) + 4, LR(10), 5, "PC" );
+ sprintf( pbuf, "%04X", PC );
+ widget_printstring_fixed( LC(26) / 8, LR(10) / 8, 7, pbuf );
+
+ widget_printstring_right( LR(35) + 4, LR(10), 5, "Bas\012e\011" );
+ sprintf( pbuf, "%d", debugger_output_base );
+ widget_printstring( LR(36), LR(10), 7, pbuf );
+
+ widget_display_lines( LR(0) / 8, 12 );
+
+ return 0;
+}
+
+
+void widget_debugger_keyhandler( input_key key )
+{
+ /* Display mode */
+ switch ( key ) {
+ case INPUT_KEY_Escape: /* Close widget */
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ debugger_run();
+ break;
+
+ case INPUT_KEY_c:
+ case INPUT_KEY_Return: /* Close widget */
+ widget_end_all( WIDGET_FINISHED_OK );
+ debugger_run();
+ break;
+
+ case INPUT_KEY_s: /* Single step & reopen widget */
+ debugger_mode = DEBUGGER_MODE_HALTED;
+ widget_end_all( WIDGET_FINISHED_OK );
+ break;
+
+ case INPUT_KEY_r: /* Display the registers */
+ display = DB_REGISTERS;
+ widget_debugger_draw( NULL );
+ break;
+
+ case INPUT_KEY_b: /* Display a memory dump (bytes) */
+ display = DB_BYTES;
+ widget_debugger_draw( NULL );
+ break;
+
+ case INPUT_KEY_t: /* Display a memory dump (text) */
+ display = DB_TEXT;
+ widget_debugger_draw( NULL );
+ break;
+
+ case INPUT_KEY_d: /* Display a disassembly */
+ display = DB_DISASM;
+ widget_debugger_draw( NULL );
+ break;
+
+ case INPUT_KEY_k: /* Display the breakpoints */
+ display = DB_BREAKPT;
+ widget_debugger_draw( NULL );
+ break;
+
+ case INPUT_KEY_e: /* Switch base */
+ debugger_output_base = 26 - debugger_output_base; /* 10 or 16 */
+ widget_debugger_draw( NULL );
+ break;
+
+ case INPUT_KEY_m: /* Enter a command */
+ {
+ widget_text_t text_data;
+
+ text_data.title = "Debugger command";
+ text_data.allow = WIDGET_INPUT_ASCII;
+ text_data.text[0] = 0;
+ if( !widget_do( WIDGET_TYPE_TEXT, &text_data ) )
+ debugger_command_evaluate( widget_text_text );
+ }
+ break;
+
+ case INPUT_KEY_Up: /* Back one line */
+ scroll( -1 );
+ break;
+
+ case INPUT_KEY_Down: /* Back one instruction or four lines */
+ scroll( 1 );
+ break;
+
+ case INPUT_KEY_Page_Up: /* Back eight lines */
+ scroll( -8 );
+ break;
+
+ case INPUT_KEY_Page_Down: /* Forward eight lines */
+ scroll( 8 );
+ break;
+
+ case INPUT_KEY_Home: /* To start of memory */
+ debugger_memaddr = 0;
+ scroll( 0 );
+ break;
+
+ case INPUT_KEY_End: /* To end of RAM */
+ debugger_memaddr = 0;
+ scroll( -8 );
+ break;
+
+ default:;
+ }
+}
+
+static void show_register0( int x, int y, const char *label, int value )
+{
+ char pbuf[8];
+
+ sprintf( pbuf, "%d", value );
+ widget_printstring_right( x - 4, y, 5, label );
+ widget_printstring_fixed( x / 8, y / 8, 7, pbuf );
+}
+
+static void show_register1( int x, int y, const char *label, int value )
+{
+ char pbuf[8];
+
+ sprintf( pbuf, format_8_bit(), value );
+ widget_printstring_right( x - 4, y, 5, label );
+ widget_printstring_fixed( x / 8, y / 8, 7, pbuf );
+}
+
+static void show_register2( int x, int y, const char *label, int value )
+{
+ char pbuf[8];
+
+ sprintf( pbuf, format_16_bit(), value );
+ widget_printstring_right( x - 4, y, 5, label );
+ widget_printstring_fixed( x / 8, y / 8, 7, pbuf );
+}
+
+static void display_registers( void )
+{
+ char pbuf[16];
+ int i, capabilities;
+
+ show_register2( LC(3), LR(0), "AF", AF );
+ show_register2( LC(12), LR(0), "AF'", AF_ );
+ show_register2( LC(20), LR(0), "SP", SP );
+ show_register2( LC(29), LR(0), "PC", PC );
+ show_register1( LC(36), LR(0), "R", ( R & 0x7F ) | ( R7 & 0x80 ) );
+
+ show_register2( LC(3), LR(1), "BC", BC );
+ show_register2( LC(12), LR(1), "BC'", BC_ );
+ show_register2( LC(20), LR(1), "IX", IX );
+ show_register2( LC(29), LR(1), "IY", IY );
+ show_register1( LC(36), LR(1), "I", I );
+
+ show_register2( LC(3), LR(2), "DE", DE );
+ show_register2( LC(12), LR(2), "DE'", DE_ );
+ show_register0( LC(20), LR(2), "IM", IM );
+ show_register0( LC(29), LR(2), "IFF1", IFF1 );
+ show_register0( LC(36), LR(2), "IFF2", IFF2 );
+
+ show_register2( LC(3), LR(3), "HL", HL );
+ show_register2( LC(12), LR(3), "HL'", HL_ );
+ widget_printstring_fixed( LC(20) / 8, LR(3) / 8, 5, "SZ5H3PNC" );
+ show_register1( LC(36), LR(3), "ULA", ula_last_byte() );
+
+ sprintf( pbuf, "%d", tstates );
+ widget_printstring_right( LC(12) - 4, LR(4), 5, "Tstates" );
+ widget_printstring_fixed( LC(12) / 8, LR(4) / 8, 7, pbuf );
+ for( i = 0; i < 8; ++i )
+ pbuf[i] = '0' + ( F >> i & 1 );
+ pbuf[8] = 0;
+ widget_printstring_fixed( LC(20) / 8, LR(4) / 8, 7, pbuf );
+
+ capabilities = libspectrum_machine_capabilities( machine_current->machine );
+
+ if( capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_AY )
+ show_register1( LC(37), LR(4), "AY",
+ machine_current->ay.current_register );
+
+ if( capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY )
+ show_register1( LC(6), LR(5), "128Mem",
+ machine_current->ram.last_byte );
+
+ if( capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY )
+ show_register1( LC(15), LR(5), "+3Mem",
+ machine_current->ram.last_byte2 );
+
+ if( capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_VIDEO ||
+ capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_MEMORY ||
+ capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_SE_MEMORY )
+ show_register1( LC(24), LR(5), "TmxDec", scld_last_dec.byte );
+
+ if( capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_MEMORY ||
+ capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_SE_MEMORY )
+ show_register1( LC(33), LR(5), "TmxHSR", scld_last_hsr );
+
+ if( settings_current.zxcf_active )
+ show_register1( LC(6), LR(5), "ZXCF", zxcf_last_memctl() );
+
+ for( i = 0; i < 8; ++i ) {
+ int x = LC(2 + 10 * ( i & 3) ), y = LR(i < 4 ? 6 : 7);
+
+ sprintf( pbuf, "P%X", i );
+ widget_printstring_right( x, y, 5, pbuf );
+ snprintf( pbuf, sizeof( pbuf ), "%s %d",
+ memory_bank_name( &memory_map_read[i] ),
+ memory_map_read[i].page_num );
+ x = widget_printstring( x + 4, y, 7, pbuf ) + 4;
+ if( memory_map_read[i].writable )
+ x = widget_printstring( x, y, 4, "w" );
+ if( memory_map_read[i].contended )
+ x = widget_printstring( x, y, 4, "c" );
+ }
+}
+
+
+static void display_bytes( void )
+{
+ int x, y;
+ char pbuf[36];
+
+ for( y = 0; y < 8; ++y ) {
+ libspectrum_word addr = debugger_memaddr + y * 8;
+
+ sprintf( pbuf, format_16_bit(), addr );
+ widget_printstring_fixed( LC(1) / 8, LR(y) / 8, 7, pbuf );
+ widget_printstring( LC(6), LR(y), 5, ":" );
+
+ for( x = 0; x < 8; ++x ) {
+ sprintf( pbuf + x * 4, format_8_bit(),
+ readbyte_internal( addr + x ) );
+ if( x < 7 )
+ strcat( pbuf, " " );
+ }
+ widget_printstring_fixed( LC(7) / 8, LR(y) / 8, 7, pbuf );
+ }
+}
+
+
+static void display_text( void )
+{
+ int x, y;
+ char pbuf[8];
+
+ for( y = 0; y < 8; ++y ) {
+ libspectrum_word addr = debugger_memaddr + y * 32;
+
+ sprintf( pbuf, format_16_bit(), addr );
+ widget_printstring_fixed( LC(1) / 8, LR(y) / 8, 7, pbuf );
+ widget_printstring( LC(6), LR(y), 5, ":" );
+
+ for( x = 0; x < 32; ++x )
+ widget_printchar_fixed( LC(x + 8) / 8, LR(y) / 8, 7,
+ readbyte_internal( addr + x ) );
+ }
+}
+
+
+static void display_disasm( void )
+{
+ int y;
+ char pbuf[40];
+ libspectrum_word addr = debugger_memaddr;
+
+ for( y = 0; y < 8; ++y ) {
+ size_t length;
+ char *spc;
+
+ sprintf( pbuf, format_16_bit(), addr );
+ widget_printstring_fixed( LC(1) / 8, LR(y) / 8, 7, pbuf );
+ widget_printstring( LC(6), LR(y), 5, ":" );
+
+ debugger_disassemble( pbuf, sizeof( pbuf ), &length, addr );
+ addr += length;
+ spc = strchr( pbuf, ' ' );
+ if( spc )
+ *spc = 0;
+ widget_printstring( LC(8), LR(y), 7, pbuf );
+ if( spc ) {
+ spc += 1 + strspn( spc + 1, " " );
+ widget_printstring( LC(12) + 4, LR(y), 7, spc );
+ }
+ }
+}
+
+
+static void display_breakpts( void )
+{
+ GSList *ptr;
+ int i = -breakpt_show;
+ char pbuf[80], fmt[20];
+
+ if( i )
+ widget_up_arrow( LC(0), LR(0), 7 );
+
+ for( ptr = debugger_breakpoints; i < 8 && ptr; ptr = ptr->next, ++i ) {
+ const debugger_breakpoint *bp = ptr->data;
+
+ if( i < 0 )
+ continue;
+
+ sprintf( pbuf, "%lu", ( unsigned long )bp->id );
+ widget_printstring( LC(1), LR(i), 5, pbuf );
+ widget_printstring( LC(6), LR(i), 7,
+ debugger_breakpoint_type_abbr[bp->type] );
+
+ switch ( bp->type ) {
+ case DEBUGGER_BREAKPOINT_TYPE_EXECUTE:
+ case DEBUGGER_BREAKPOINT_TYPE_READ:
+ case DEBUGGER_BREAKPOINT_TYPE_WRITE:
+ if( bp->value.address.page == -1 )
+ sprintf( pbuf, format_16_bit(), bp->value.address.offset );
+ else {
+ debugger_breakpoint_decode_page( pbuf, sizeof( pbuf ) - 12,
+ bp->value.address.page );
+ if( pbuf[0] == '[' )
+ sprintf( pbuf, "?%d", bp->value.address.page );
+ strcat( pbuf, ":" );
+ sprintf( pbuf + strlen( pbuf ), format_16_bit(),
+ bp->value.address.offset );
+ }
+ break;
+
+ case DEBUGGER_BREAKPOINT_TYPE_PORT_READ:
+ case DEBUGGER_BREAKPOINT_TYPE_PORT_WRITE:
+ sprintf( fmt, "%s:%s", format_16_bit(), format_16_bit() );
+ sprintf( pbuf, fmt, bp->value.port.mask, bp->value.port.port );
+ break;
+
+ case DEBUGGER_BREAKPOINT_TYPE_TIME:
+ sprintf( pbuf, "%5d", bp->value.tstates );
+ break;
+ }
+ widget_printstring( LC(10), LR(i), 6, pbuf );
+
+ sprintf( pbuf, "%lu", ( unsigned long )bp->ignore );
+ widget_printstring( LC(18) + 4, LR(i), 7, pbuf );
+
+ sprintf( pbuf, "%s", debugger_breakpoint_life_abbr[bp->life] );
+ widget_printstring( LC(23), LR(i), 7, pbuf );
+
+ if( bp->condition ) {
+ debugger_expression_deparse( pbuf, sizeof( pbuf ), bp->condition );
+ widget_printstring( LC(28) + 4, LR(i), 6, pbuf );
+ }
+ }
+
+ if( !i )
+ widget_printstring( LC(1), LR(0), 5, "(No breakpoints)" );
+ else if( ptr )
+ widget_down_arrow( LC(0), LC(7), 7 );
+}
+
+
+static void scroll( int step )
+{
+ switch ( display ) {
+ case DB_BYTES:
+ debugger_memaddr += 8 * step;
+ break;
+
+ case DB_TEXT:
+ debugger_memaddr += 32 * step;
+ break;
+
+ case DB_DISASM:
+ if( step > 0 )
+ for( ; step; --step ) {
+ size_t length;
+
+ debugger_disassemble( NULL, 0, &length, debugger_memaddr );
+ debugger_memaddr += length;
+ } else
+ for( ; step; ++step ) {
+ /* For details, see ui/gtk/debugger.c:move_disassembly() */
+ size_t i, longest = 1;
+
+ for( i = 1; i <= 8; ++i ) {
+ size_t length;
+
+ debugger_disassemble( NULL, 0, &length, debugger_memaddr );
+ if( length == i )
+ longest = i;
+ }
+ debugger_memaddr -= longest;
+ }
+ break;
+
+ case DB_BREAKPT:
+ {
+ int length = g_slist_length( debugger_breakpoints );
+
+ breakpt_no += step;
+ if( breakpt_no >= length )
+ breakpt_no = length - 1;
+ if( breakpt_no < 0 )
+ breakpt_no = 0;
+ if( breakpt_no < breakpt_show )
+ breakpt_show = breakpt_no;
+ else if( breakpt_no > breakpt_show + 7 )
+ breakpt_show = breakpt_no - 7;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ widget_debugger_draw( NULL );
+}
Copied: vendor/fuse-emulator/current/fuse/ui/widget/error.c (from rev 527, vendor/fuse-emulator/current/fuse/widget/error.c)
===================================================================
--- vendor/fuse-emulator/current/fuse/ui/widget/error.c (rev 0)
+++ vendor/fuse-emulator/current/fuse/ui/widget/error.c 2008-05-07 12:25:42 UTC (rev 528)
@@ -0,0 +1,183 @@
+/* error.c: The error reporting widget
+ Copyright (c) 2002-2005 Philip Kendall
+
+ $Id: error.c 3115 2007-08-19 02:49:14Z fredm $
+
+ 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: phi...@sh...
+
+*/
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "fuse.h"
+#include "widget_internals.h"
+
+widget_error_t *error_info;
+
+int
+ui_error_specific( ui_error_level severity, const char *message )
+{
+ widget_error_t error_info;
+ /* Can't output widgets if we don't have a display yet */
+ if( !display_ui_initialised ) return 0;
+
+
+ error_info.severity = severity;
+ error_info.message = message;
+
+ fuse_emulation_pause();
+ widget_do( WIDGET_TYPE_ERROR, &error_info );
+ fuse_emulation_unpause();
+
+ return 0;
+}
+
+int widget_error_draw( void *data )
+{
+ char **lines; size_t count;
+ size_t i;
+
+ error_info = (widget_error_t*)data;
+ if( split_message( error_info->message, &lines, &count, 28 ) ) return 1;
+
+ widget_dialog_with_border( 1, 2, 30, count+2 );
+
+ switch( error_info->severity ) {
+ case UI_ERROR_INFO:
+ widget_print_title( 16, WIDGET_COLOUR_FOREGROUND, "Info" );
+ break;
+ case UI_ERROR_WARNING:
+ widget_print_title( 16, WIDGET_COLOUR_FOREGROUND, "Warning" );
+ break;
+ case UI_ERROR_ERROR:
+ widget_print_title( 16, WIDGET_COLOUR_FOREGROUND, "Error" );
+ break;
+ default:
+ widget_print_title( 16, WIDGET_COLOUR_FOREGROUND, "(Unknown message)" );
+ break;
+ }
+
+ for( i=0; i<count; i++ ) {
+ widget_printstring( 17, i*8+28, WIDGET_COLOUR_FOREGROUND, lines[i] );
+ free( lines[i] );
+ }
+
+ free( lines );
+
+ widget_display_lines( 2, count + 4 );
+
+ return 0;
+}
+
+int
+split_message( const char *message, char ***lines, size_t *count,
+ size_t line_length )
+{
+ const char *ptr = message;
+ int position;
+
+ line_length *= 8;
+
+ /* Setup so we'll allocate the first line as soon as we get the first
+ word */
+ *lines = NULL; *count = 0; position = line_length;
+
+ while( *ptr ) {
+
+ /* Skip any whitespace */
+ while( *ptr && isspace( *ptr ) ) ptr++; message = ptr;
+
+ /* Find end of word */
+ while( *ptr && !isspace( *ptr ) ) ptr++;
+
+ /* message now points to a word of length (ptr-message); if
+ that's longer than an entire line (most likely filenames), just
+ take the last bit */
+ while( widget_substringwidth( message, ptr - message ) >= line_length )
+ message++;
+
+ /* Check we've got room for the word, plus some prefixing space */
+ if( position + widget_substringwidth( message, ptr - message ) + 4
+ >= line_length ) {
+
+ char **new_lines; size_t i;
+
+ /* If we've filled the screen, stop */
+ if( *count == 18 ) return 0;
+
+ new_lines = realloc( (*lines), (*count + 1) * sizeof( char** ) );
+ if( new_lines == NULL ) {
+ for( i=0; i<*count; i++ ) free( (*lines)[i] );
+ if(*lines) free( (*lines) );
+ return 1;
+ }
+ (*lines) = new_lines;
+
+ (*lines)[*count] = malloc( (line_length+1) );
+ if( (*lines)[*count] == NULL ) {
+ for( i=0; i<*count; i++ ) free( (*lines)[i] );
+ free( (*lines) );
+ return 1;
+ }
+
+ strncpy( (*lines)[*count], message, ptr - message );
+ position = widget_substringwidth( message, ptr - message );
+ (*lines)[*count][ptr - message] = '\0';
+
+ (*count)++;
+
+ } else { /* Enough room on this line */
+
+ strcat( (*lines)[*count-1], " " );
+ (*lines)[*count-1][strlen( (*lines)[*count-1] ) + ptr - message] = '\0';
+ strncat( (*lines)[*count-1], message, ptr - message );
+ position += widget_substringwidth( message, ptr - message ) + 4;
+
+ }
+
+ message = ptr;
+
+ }
+
+ return 0;
+}
+
+void
+widget_error_keyhandler( input_key key )
+{
+ switch( key ) {
+
+ case INPUT_KEY_Escape:
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ return;
+
+ case INPUT_KEY_Return:
+ widget_end_widget( WIDGET_FINISHED_OK );
+ return;
+
+ default: /* Keep gcc happy */
+ break;
+
+ }
+}
Copied: vendor/fuse-emulator/current/fuse/ui/widget/filesel.c (from rev 527, vendor/fuse-emulator/current/fuse/widget/filesel.c)
===================================================================
--- vendor/fuse-emulator/current/fuse/ui/widget/filesel.c (rev 0)
+++ vendor/fuse-emulator/current/fuse/ui/widget/filesel.c 2008-05-07 12:25:42 UTC (rev 528)
@@ -0,0 +1,960 @@
+/* filesel.c: File selection dialog box
+ Copyright (c) 2001-2005 Matan Ziv-Av, Philip Kendall, Russell Marks,
+ Marek Januszewski
+
+ $Id: filesel.c 3286 2007-11-09 16:41:57Z zubzero $
+
+ 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: phi...@sh...
+
+*/
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <direct.h>
+#include <ctype.h>
+#endif /* #ifdef WIN32 */
+
+#include "fuse.h"
+#include "ui/ui.h"
+#include "utils.h"
+#include "widget_internals.h"
+
+#if defined AMIGA || defined __MORPHOS__
+#include <proto/asl.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+
+struct Library *AslBase;
+
+#ifndef __MORPHOS__
+struct AslIFace *IAsl;
+struct Library *DOSBase;
+#endif /* #ifndef __MORPHOS__ */
+
+#ifndef __MORPHOS__
+struct DOSIFace *IDOS;
+struct Library *ExecBase;
+#endif /* #ifndef __MORPHOS__ */
+
+
+int err = 0;
+#endif /* ifdef AMIGA */
+
+struct widget_dirent **widget_filenames; /* Filenames in the current
+ directory */
+size_t widget_numfiles; /* The number of files in the current
+ directory */
+
+static const char *title;
+static int is_saving;
+
+#ifdef WIN32
+static int is_drivesel = 0;
+static int is_rootdir;
+#endif /* #ifdef WIN32 */
+
+#define PAGESIZE (is_saving ? 32 : 36)
+
+/* The number of the filename in the top-left corner of the current
+ display, that of the filename which the `cursor' is on, and that
+ which it will be on after this keypress */
+static size_t top_left_file, current_file, new_current_file;
+
+static char *widget_get_filename( const char *title, int saving );
+
+static int widget_add_filename( int *allocated, int *number,
+ struct widget_dirent ***namelist, char *name );
+static void widget_scan( char *dir );
+static int widget_select_file( const struct dirent *dirent );
+static int widget_scan_compare( const widget_dirent **a,
+ const widget_dirent **b );
+
+#if !defined AMIGA && !defined __MORPHOS__
+static char* widget_getcwd( void );
+#endif /* ifndef AMIGA */
+static int widget_print_all_filenames( struct widget_dirent **filenames, int n,
+ int top_left, int current,
+ const char *dir );
+static int widget_print_filename( struct widget_dirent *filename, int position,
+ int inverted );
+#ifdef WIN32
+static void widget_filesel_chdrv( void );
+static void widget_filesel_drvlist( void );
+#endif /* #ifdef WIN32 */
+static int widget_filesel_chdir( void );
+
+/* The filename to return */
+char* widget_filesel_name;
+
+/* Should we exit all widgets when we're done with this selector? */
+static int exit_all_widgets;
+
+static char *
+widget_get_filename( const char *title, int saving )
+{
+ char *filename = NULL;
+ widget_type wtype;
+
+ widget_filesel_data data;
+
+ data.exit_all_widgets = 1;
+ data.title = title;
+
+ if( saving ) {
+ wtype = WIDGET_TYPE_FILESELECTOR_SAVE;
+ } else {
+ wtype = WIDGET_TYPE_FILESELECTOR;
+ }
+ widget_do( wtype, &data );
+ if( widget_filesel_name ) {
+ filename = strdup( widget_filesel_name );
+ if( !filename )
+ ui_error( UI_ERROR_ERROR, "Out of memory at %s:%d", __FILE__, __LINE__ );
+ }
+
+ return filename;
+
+}
+
+char *
+ui_get_open_filename( const char *title )
+{
+ return widget_get_filename( title, 0 );
+}
+
+char *
+ui_get_save_filename( const char *title )
+{
+ return widget_get_filename( title, 1 );
+}
+
+static int widget_add_filename( int *allocated, int *number,
+ struct widget_dirent ***namelist,
+ char *name ) {
+ int i; size_t length;
+
+ if( ++*number > *allocated ) {
+ struct widget_dirent **oldptr = *namelist;
+
+ *namelist = realloc( (*namelist), 2 * *allocated * sizeof(**namelist) );
+ if( *namelist == NULL ) {
+ for( i=0; i<*number-1; i++ ) {
+ free( oldptr[i]->name );
+ free( oldptr[i] );
+ }
+ free( oldptr );
+ return -1;
+ }
+ *allocated *= 2;
+ }
+
+ (*namelist)[*number-1] = malloc( sizeof(***namelist) );
+ if( !(*namelist)[*number-1] ) {
+ for( i=0; i<*number-1; i++ ) {
+ free( (*namelist)[i]->name );
+ free( (*namelist)[i] );
+ }
+ free( *namelist );
+ *namelist = NULL;
+ return -1;
+ }
+
+ length = strlen( name ) + 1;
+ if( length < 16 ) length = 16;
+
+ (*namelist)[*number-1]->name = malloc( length );
+ if( !(*namelist)[*number-1]->name ) {
+ free( (*namelist)[*number-1] );
+ for( i=0; i<*number-1; i++ ) {
+ free( (*namelist)[i]->name );
+ free( (*namelist)[i] );
+ }
+ free( *namelist );
+ *namelist = NULL;
+ return -1;
+ }
+
+ strncpy( (*namelist)[*number-1]->name, name, length );
+ (*namelist)[*number-1]->name[ length - 1 ] = 0;
+
+ return 0;
+}
+
+#if defined AMIGA || defined __MORPHOS__
+static char *
+amiga_asl( char *title ) {
+ char *filename;
+ struct FileRequester *filereq;
+
+#ifndef __MORPHOS__
+ if( AslBase = IExec->OpenLibrary( "asl.library", 52 ) ) {
+ if( IAsl = ( struct AslIFace * ) IExec->GetInterface( AslBase,"main",1,NULL ) ) {
+ filereq = IAsl->AllocAslRequestTags( ASL_FileRequest,
+ ASLFR_RejectIcons,TRUE,
+ ASLFR_TitleText,title,
+ ASLFR_DoSaveMode,is_saving,
+ ASLFR_InitialPattern,"#?.(sna|z80|szx|sp|snp|zxs|tap|tzx|csw|rzx|dsk|trd|scl|mdr|dck|hdf|rom|psg|scr|png|gz|bz2)",
+ ASLFR_DoPatterns,TRUE,
+ TAG_DONE );
+ if( err = IAsl->AslRequest( filereq, NULL ) ) {
+ filename = ( STRPTR ) IExec->AllocVec( 1024, MEMF_CLEAR );
+#else /* #ifndef __MORPHOS__ */
+ if( AslBase = OpenLibrary( "asl.library", 0 ) ) {
+ filereq = AllocAslRequestTags( ASL_FileRequest,
+ ASLFR_RejectIcons,TRUE,
+ ASLFR_TitleText,title,
+ ASLFR_DoSaveMode,is_saving,
+ ASLFR_InitialPattern,"#?.(sna|z80|szx|sp|snp|zxs|tap|tzx|csw|rzx|dsk|trd|scl|mdr|dck|hdf|rom|psg|scr|png|gz|bz2)",
+ ASLFR_DoPatterns,TRUE,
+ TAG_DONE );
+ if( err = AslRequest( filereq, NULL ) ) {
+ filename = ( STRPTR ) AllocVec( 1024, MEMF_CLEAR );
+#endif /* #ifndef __MORPHOS__ */
+
+ strcpy( filename,filereq->fr_Drawer );
+#ifndef __MORPHOS__
+ IDOS->AddPart( filename, filereq->fr_File, 1024 );
+#else /* #ifndef __MORPHOS__ */
+ AddPart( filename, filereq->fr_File, 1024 );
+#endif /* #ifndef __MORPHOS__ */
+ widget_filesel_name = strdup( filename );
+#ifndef __MORPHOS__
+ IExec->FreeVec( filename );
+#else /* #ifndef __MORPHOS__ */
+ FreeVec( filename );
+#endif /* #ifndef __MORPHOS__ */
+ err = WIDGET_FINISHED_OK;
+ } else {
+ err = WIDGET_FINISHED_CANCEL;
+ }
+#ifndef __MORPHOS__
+ IExec->DropInterface( ( struct Interface * )IAsl );
+ }
+ IExec->CloseLibrary( AslBase );
+#else /* #ifndef __MORPHOS__ */
+ CloseLibrary( AslBase );
+#endif /* #ifndef __MORPHOS__ */
+ }
+ return widget_filesel_name;
+}
+#else /* ifdef AMIGA */
+
+static int widget_scandir( const char *dir, struct widget_dirent ***namelist,
+ int (*select_fn)(const struct dirent*) )
+{
+ DIR *directory; struct dirent *dirent;
+
+ int allocated, number;
+ int i;
+
+ *namelist = malloc( 32 * sizeof(**namelist) );
+ if( !*namelist ) return -1;
+
+ allocated = 32; number = 0;
+
+ directory = opendir( dir );
+ if( !directory ) {
+ free( *namelist );
+ *namelist = NULL;
+ return -1;
+ }
+
+#ifdef WIN32
+ /* Assume this is the root directory, unless we find an entry named ".." */
+ is_rootdir = 1;
+#endif /* #ifdef WIN32 */
+
+ while( 1 ) {
+ errno = 0;
+ dirent = readdir( directory );
+
+ if( !dirent ) {
+ if( errno == 0 ) { /* End of directory */
+ break;
+ } else {
+ for( i=0; i<number; i++ ) {
+ free( (*namelist)[i]->name );
+ free( (*namelist)[i] );
+ }
+ free( *namelist );
+ *namelist = NULL;
+ closedir( directory );
+ return -1;
+ }
+ }
+
+ if( select_fn( dirent ) ) {
+#ifdef WIN32
+ if( is_rootdir && !strcmp( dirent->d_name, ".." ) ) {
+ is_rootdir = 0;
+ }
+#endif /* #ifdef WIN32 */
+ if( widget_add_filename( &allocated, &number, namelist,
+ dirent->d_name ) ) {
+ closedir( directory );
+ return -1;
+ }
+ }
+ }
+
+ if( closedir( directory ) ) {
+ for( i=0; i<number; i++ ) {
+ free( (*namelist)[i]->name );
+ free( (*namelist)[i] );
+ }
+ free( *namelist );
+ *namelist = NULL;
+ return -1;
+ }
+
+#ifdef WIN32
+ if( is_rootdir ) {
+ /* Add a fake ".." entry for drive selection */
+ if( widget_add_filename( &allocated, &number, namelist, ".." ) ) {
+ return -1;
+ }
+ }
+#endif /* #ifdef WIN32 */
+
+ return number;
+}
+
+#ifdef WIN32
+static int widget_scandrives( struct widget_dirent ***namelist )
+{
+ int allocated, number;
+ unsigned long drivemask;
+ int i;
+ char drive[3];
+ char *driveletters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ drive[1] = ':';
+ drive[2] = '\0';
+
+ *namelist = malloc( 32 * sizeof(**namelist) );
+ if( !*namelist ) return -1;
+
+ allocated = 32; number = 0;
+
+ drivemask = _getdrives();
+ if( !drivemask ) {
+ free( *namelist );
+ *namelist = NULL;
+ return -1;
+ }
+
+ for( i = 0; i < 26; i++ ) {
+ if( drivemask & 1) {
+ drive[0] = driveletters[i];
+ if( widget_add_filename( &allocated, &number, namelist, drive ) ) {
+ return -1;
+ }
+ }
+ drivemask >>= 1;
+ }
+
+ return number;
+}
+#endif
+
+static void widget_scan( char *dir )
+{
+ struct stat file_info;
+
+ size_t i; int error;
+
+ /* Free the memory belonging to the files in the previous directory */
+ for( i=0; i<widget_numfiles; i++ ) {
+ free( widget_filenames[i]->name );
+ free( widget_filenames[i] );
+ }
+
+#ifdef WIN32
+ if( dir ) {
+ widget_numfiles = widget_scandir( dir, &widget_filenames,
+ widget_select_file );
+ } else {
+ widget_numfiles = widget_scandrives( &widget_filenames );
+ }
+#else /* #ifdef WIN32 */
+ widget_numfiles = widget_scandir( dir, &widget_filenames,
+ widget_select_file );
+#endif /* #ifdef WIN32 */
+
+ if( widget_numfiles == (size_t)-1 ) return;
+
+ for( i=0; i<widget_numfiles; i++ ) {
+ error = stat( widget_filenames[i]->name, &file_info );
+ widget_filenames[i]->mode = error ? 0 : file_info.st_mode;
+ }
+
+ qsort( widget_filenames, widget_numfiles, sizeof(struct widget_dirent*),
+ (int(*)(const void*,const void*))widget_scan_compare );
+
+}
+
+static int widget_select_file(const struct dirent *dirent){
+ return( dirent->d_name && strcmp( dirent->d_name, "." ) );
+}
+
+static int widget_scan_compare( const struct widget_dirent **a,
+ const struct widget_dirent **b )
+{
+ int isdir1 = S_ISDIR( (*a)->mode ),
+ isdir2 = S_ISDIR( (*b)->mode );
+
+ if( isdir1 && !isdir2 ) {
+ return -1;
+ } else if( isdir2 && !isdir1 ) {
+ return 1;
+ } else {
+ return strcmp( (*a)->name, (*b)->name );
+ }
+
+}
+#endif /* ifdef AMIGA */
+
+/* File selection widget */
+
+static int
+widget_filesel_draw( void *data )
+{
+ widget_filesel_data *filesel_data = data;
+ char *directory;
+ int error;
+
+ exit_all_widgets = filesel_data->exit_all_widgets;
+ title = filesel_data->title;
+
+#if !defined AMIGA && !defined __MORPHOS__
+#ifdef WIN32
+ if( !is_drivesel ) {
+ directory = widget_getcwd();
+ if( directory == NULL ) return 1;
+ } else {
+ directory = NULL;
+ }
+#else /* #ifdef WIN32 */
+ directory = widget_getcwd();
+ if( directory == NULL ) return 1;
+#endif /* #ifdef WIN32 */
+
+ widget_scan( directory );
+ new_current_file = current_file = 0;
+ top_left_file = 0;
+
+ /* Create the dialog box */
+ error = widget_dialog_with_border( 1, 2, 30, 21 );
+ if( error ) {
+ if( directory ) free( directory );
+ return error;
+ }
+
+#ifdef WIN32
+ if( directory == NULL ) {
+ directory = "Drive selection";
+ }
+#endif /* #ifdef WIN32 */
+
+ /* Show all the filenames */
+ widget_print_all_filenames( widget_filenames, widget_numfiles,
+ top_left_file, current_file, directory );
+#else /* ifndef AMIGA */
+ amiga_asl(title);
+#endif /* ifndef AMIGA */
+
+ return 0;
+}
+
+int widget_filesel_finish( widget_finish_state finished ) {
+
+ /* Return with null if we didn't finish cleanly */
+ if( finished != WIDGET_FINISHED_OK ) {
+ if( widget_filesel_name ) free( widget_filesel_name );
+ widget_filesel_name = NULL;
+ }
+
+ return 0;
+}
+
+int
+widget_filesel_load_draw( void *data )
+{
+ is_saving = 0;
+ return widget_filesel_draw( data );
+}
+
+int
+widget_filesel_save_draw( void *data )
+{
+ is_saving = 1;
+ return widget_filesel_draw( data );
+}
+
+#if !defined AMIGA && !defined __MORPHOS__
+static char* widget_getcwd( void )
+{
+ char *directory; size_t directory_length;
+ char *ptr;
+
+ directory_length = 64;
+ directory = malloc( directory_length * sizeof( char ) );
+ if( directory == NULL ) {
+ return NULL;
+ }
+
+ do {
+ ptr = getcwd( directory, directory_length );
+ if( ptr ) break;
+ if( errno == ERANGE ) {
+ ptr = directory;
+ directory_length *= 2;
+ directory =
+ (char*)realloc( directory, directory_length * sizeof( char ) );
+ if( directory == NULL ) {
+ free( ptr );
+ return NULL;
+ }
+ } else {
+ free( directory );
+ return NULL;
+ }
+ } while(1);
+
+#ifdef WIN32
+ if( directory[0] && directory[1] == ':' ) {
+ directory[0] = toupper( directory[0] );
+ }
+#endif
+
+ return directory;
+}
+
+static int widget_print_all_filenames( struct widget_dirent **filenames, int n,
+ int top_left, int current,
+ const char *dir )
+{
+ int i;
+ int error;
+
+ /* Give us a clean box to start with */
+ error = widget_dialog( 1, 2, 30, 21 );
+ if( error ) return error;
+
+ widget_print_title( 16, WIDGET_COLOUR_FOREGROUND, title );
+ if( widget_stringwidth( dir ) > 223 ) {
+ char buffer[128];
+ int prefix = widget_stringwidth( "..." ) + 1;
+ while( widget_stringwidth( dir ) > 223 - prefix ) dir++;
+ snprintf( buffer, sizeof( buffer ), "...%s", dir );
+ widget_print_title( 28, WIDGET_COLOUR_FOREGROUND, buffer );
+ } else {
+ widget_print_title( 28, WIDGET_COLOUR_FOREGROUND, dir );
+ }
+
+ if( top_left ) widget_up_arrow( 1, 5, WIDGET_COLOUR_FOREGROUND );
+
+ /* Print the filenames, mostly normally, but with the currently
+ selected file inverted */
+ for( i = top_left; i < n && i < top_left + PAGESIZE; i++ ) {
+ if( i == current ) {
+ widget_print_filename( filenames[i], i-top_left, 1 );
+ } else {
+ widget_print_filename( filenames[i], i-top_left, 0 );
+ }
+ }
+
+ if( is_saving )
+ {
+ widget_printstring( 12, 22 * 8, WIDGET_COLOUR_FOREGROUND,
+ "\012RETURN\011 = select" );
+ widget_printstring_right( 244, 22 * 8, WIDGET_COLOUR_FOREGROUND,
+ "\012TAB\011 = enter name" );
+ }
+
+ if( i < n )
+ widget_down_arrow( 1, is_saving ? 20 : 22, WIDGET_COLOUR_FOREGROUND );
+
+ /* Display that lot */
+ widget_display_lines( 2, 21 );
+
+ return 0;
+}
+
+/* Print a filename onto the dialog box */
+static int widget_print_filename( struct widget_dirent *filename, int position,
+ int inverted )
+{
+ char buffer[64], suffix[64], *dot = 0;
+ int width, suffix_width = 0;
+ int dir = S_ISDIR( filename->mode );
+ int truncated = 0, suffix_truncated = 0;
+
+#define FILENAME_WIDTH 112
+#define MAX_SUFFIX_WIDTH 56
+
+ int x = (position & 1) ? 132 : 16,
+ y = 40 + (position >> 1) * 8;
+
+ int foreground = inverted ? WIDGET_COLOUR_BACKGROUND
+ : WIDGET_COLOUR_FOREGROUND,
+
+ background = inverted ? WIDGET_COLOUR_FOREGROUND
+ : WIDGET_COLOUR_BACKGROUND;
+
+ widget_rectangle( x, y, FILENAME_WIDTH, 8, background );
+
+ strncpy( buffer, filename->name, sizeof( buffer ) - dir - 1);
+ buffer[sizeof( buffer ) - dir - 1] = '\0';
+
+ if (dir)
+ dir = widget_charwidth( FUSE_DIR_SEP_CHR );
+ else {
+ /* get filename extension */
+ dot = strrchr( filename->name, '.' );
+
+ /* if .gz or .bz2, we want the previous component too */
+ if( dot &&( !strcasecmp( dot, ".gz" ) || !strcasecmp( dot, ".bz2" ) ) ) {
+ char *olddot = dot;
+ *olddot = '\0';
+ dot = strrchr( filename->name, '.' );
+ *olddot = '.';
+ if (!dot)
+ dot = olddot;
+ }
+
+ /* if the dot is at the start of the name, ignore it */
+ if( dot == filename->name )
+ dot = 0;
+ }
+
+ if( dot ) {
+ /* split filename at extension separator */
+ if( dot - filename->name < sizeof( buffer ) )
+ buffer[dot - filename->name] = '\0';
+
+ /* get extension width (for display purposes) */
+ snprintf( suffix, sizeof( suffix ), "%s", dot );
+ while( ( suffix_width = ( dot && !dir )
+ ? widget_stringwidth( suffix ) : 0 ) > 110 ) {
+ suffix_truncated = 1;
+ suffix[strlen( suffix ) - 1] = '\0';
+ }
+ }
+
+ while( ( width = widget_stringwidth( buffer ) ) >=
+ FILENAME_WIDTH - dir - ( dot ? truncated + suffix_width : 0 ) ) {
+ truncated = 2;
+ if( suffix_width >= MAX_SUFFIX_WIDTH ) {
+ suffix_truncated = 2;
+ suffix[strlen (suffix) - 1] = '\0';
+ suffix_width = widget_stringwidth (suffix);
+ }
+ else
+ buffer[strlen (buffer) - 1] = '\0';
+ }
+ if( dir )
+ strcat (buffer, FUSE_DIR_SEP_STR );
+
+ widget_printstring( x + 1, y, foreground, buffer );
+ if( truncated )
+ widget_rectangle( x + width + 2, y, 1, 8, 4 );
+ if( dot )
+ widget_printstring( x + width + 2 + truncated, y,
+ foreground ^ 2, suffix );
+ if( suffix_truncated )
+ widget_rectangle( x + FILENAME_WIDTH, y, 1, 8, 4 );
+
+ return 0;
+}
+#endif /* ifndef AMIGA */
+
+#ifdef WIN32
+static void
+widget_filesel_chdrv( void )
+{
+ char *fn;
+
+ if( chdir( widget_filenames[ current_file ]->name ) ) {
+ ui_error( UI_ERROR_ERROR, "Could not change directory" );
+ return;
+ }
+
+ is_drivesel = 0;
+ fn = widget_getcwd();
+ widget_scan( fn ); free( fn );
+ new_current_file = 0;
+ /* Force a redisplay of all filenames */
+ current_file = 1; top_left_file = 1;
+}
+
+static void
+widget_filesel_drvlist( void )
+{
+ is_drivesel = 1;
+ widget_scan( NULL );
+ new_current_file = 0;
+ /* Force a redisplay of all filenames */
+ current_file = 1; top_left_file = 1;
+}
+#endif /* #ifdef WIN32 */
+
+static int
+widget_filesel_chdir( void )
+{
+ char *fn, *ptr;
+
+ /* Get the new directory name */
+ fn = widget_getcwd();
+ if( fn == NULL ) {
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ return 1;
+ }
+ ptr = fn;
+ fn = realloc( fn,
+ ( strlen( fn ) + 1 + strlen( widget_filenames[ current_file ]->name ) +
+ 1 ) * sizeof(char)
+ );
+ if( fn == NULL ) {
+ free( ptr );
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ return 1;
+ }
+ strcat( fn, FUSE_DIR_SEP_STR );
+ strcat( fn, widget_filenames[ current_file ]->name );
+
+/*
+in Win32 errno resulting from chdir on file is EINVAL which may mean many things
+this will not be fixed in mingw - must use native function instead
+http://thread.gmane.org/gmane.comp.gnu.mingw.user/9197
+*/
+
+ if( chdir( fn ) == -1 ) {
+#ifndef WIN32
+ if( errno == ENOTDIR ) {
+#else /* #ifndef WIN32 */
+ if( GetFileAttributes( fn ) != FILE_ATTRIBUTE_DIRECTORY ) {
+#endif /* #ifndef WIN32 */
+ widget_filesel_name = fn;
+ if( exit_all_widgets ) {
+ widget_end_all( WIDGET_FINISHED_OK );
+ } else {
+ widget_end_widget( WIDGET_FINISHED_OK );
+ }
+ }
+ } else {
+ widget_scan( fn ); free( fn );
+ new_current_file = 0;
+ /* Force a redisplay of all filenames */
+ current_file = 1; top_left_file = 1;
+ }
+
+ return 0;
+}
+
+void
+widget_filesel_keyhandler( input_key key )
+{
+#if defined AMIGA || defined __MORPHOS__
+ if( exit_all_widgets ) {
+ widget_end_all( err );
+ } else {
+ widget_end_widget( err );
+ }
+#else /* ifndef AMIGA */
+ char *fn;
+ char *dirtitle;
+
+ new_current_file = current_file;
+
+ switch(key) {
+
+#if 0
+ case INPUT_KEY_Resize: /* Fake keypress used on window resize */
+ widget_dialog_with_border( 1, 2, 30, 20 );
+ widget_print_all_filenames( widget_filenames, widget_numfiles,
+ top_left_file, current_file );
+ break;
+#endif
+
+ case INPUT_KEY_Escape:
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ break;
+
+ case INPUT_KEY_Left:
+ case INPUT_KEY_5:
+ case INPUT_KEY_h:
+ if( current_file > 0 ) new_current_file--;
+ break;
+
+ case INPUT_KEY_Down:
+ case INPUT_KEY_6:
+ case INPUT_KEY_j:
+ if( current_file+2 < widget_numfiles ) new_current_file += 2;
+ break;
+
+ case INPUT_KEY_Up:
+ case INPUT_KEY_7: /* Up */
+ case INPUT_KEY_k:
+ if( current_file > 1 ) new_current_file -= 2;
+ break;
+
+ case INPUT_KEY_Right:
+ case INPUT_KEY_8:
+ case INPUT_KEY_l:
+ if( current_file < widget_numfiles-1 ) new_current_file++;
+ break;
+
+ case INPUT_KEY_Page_Up:
+ new_current_file = ( current_file > PAGESIZE ) ?
+ current_file - PAGESIZE :
+ 0;
+ break;
+
+ case INPUT_KEY_Page_Down:
+ new_current_file = current_file + PAGESIZE;
+ if( new_current_file >= widget_numfiles )
+ new_current_file = widget_numfiles - 1;
+ break;
+
+ case INPUT_KEY_Home:
+ new_current_file = 0;
+ break;
+
+ case INPUT_KEY_End:
+ new_current_file = widget_numfiles - 1;
+ break;
+
+ case INPUT_KEY_Tab:
+ if( is_saving ) {
+ widget_text_t text_data;
+ text_data.title = title;
+ text_data.allow = WIDGET_INPUT_ASCII;
+ text_data.text[0] = 0;
+ if( widget_do( WIDGET_TYPE_TEXT, &text_data ) ||
+ !widget_text_text || !*widget_text_text )
+ break;
+ if( !compat_is_absolute_path( widget_text_text ) ) {
+ /* relative name */
+ /* Get current dir name and allocate space for the leafname */
+ fn = widget_getcwd();
+ if( fn )
+ fn = realloc( fn, strlen( fn ) + strlen( widget_text_text ) + 2 );
+ if( !fn ) {
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ return;
+ }
+ /* Append the leafname and return it */
+ strcat( fn, FUSE_DIR_SEP_STR );
+ strcat( fn, widget_text_text );
+ } else { /* absolute name */
+ fn = strdup( widget_text_text );
+ if( !fn ) {
+ widget_end_widget( WIDGET_FINISHED_CANCEL );
+ return;
+ }
+ }
+ widget_filesel_name = fn;
+ if( exit_all_widgets ) {
+ widget_end_all( WIDGET_FINISHED_OK );
+ } else {
+ widget_end_widget( WIDGET_FINISHED_OK );
+ }
+ }
+ break;
+
+ case INPUT_KEY_Return:
+#ifdef WIN32
+ if( is_drivesel ) {
+ widget_filesel_chdrv();
+ } else if( is_rootdir &&
+ !strcmp( widget_filenames[ current_file ]->name, ".." ) ) {
+ widget_filesel_drvlist();
+ } else {
+#endif /* #ifdef WIN32 */
+ if( widget_filesel_chdir() ) return;
+#ifdef WIN32
+ }
+#endif /* #ifdef WIN32 */
+ break;
+
+ default: /* Keep gcc happy */
+ break;
+
+ }
+
+#ifdef WIN32
+ if( is_drivesel ) {
+ dirtitle = "Drive selection";
+ } else {
+#endif /* #ifdef WIN32 */
+ dirtitle = widget_getcwd();
+#ifdef WIN32
+ }
+#endif /* #ifdef WIN32 */
+
+ /* If we moved the cursor */
+ if( new_current_file != current_file ) {
+
+ /* If we've got off the top or bottom of the currently displayed
+ file list, then reset the top-left corner and display the whole
+ thing */
+ if( new_current_file < top_left_file ) {
+
+ top_left_file = new_current_file & ~1;
+ widget_print_all_filenames( widget_filenames, widget_numfiles,
+ top_left_file, new_current_file, dirtitle );
+
+ } else if( new_current_file >= top_left_file+PAGESIZE ) {
+
+ top_left_file = ne...
[truncated message content] |