revision 1036:af7b0c5905dd
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1036:af7b0c5905dd |
parent | 1035:e3093fd7d1da |
child | 1037:297a73940eb6 |
author | nkeynes |
date | Wed Jun 24 06:06:40 2009 +0000 (14 years ago) |
Support shell substitutions in config paths
Keep track of last folder in file dialogs
Fix out-of-dateness in GTK path dialog
Keep track of last folder in file dialogs
Fix out-of-dateness in GTK path dialog
src/Makefile.am | view | annotate | diff | log | ||
src/Makefile.in | view | annotate | diff | log | ||
src/cocoaui/cocoa_ctrl.m | view | annotate | diff | log | ||
src/cocoaui/cocoa_path.m | view | annotate | diff | log | ||
src/cocoaui/cocoaui.h | view | annotate | diff | log | ||
src/cocoaui/cocoaui.m | view | annotate | diff | log | ||
src/config.c | view | annotate | diff | log | ||
src/config.h | view | annotate | diff | log | ||
src/dreamcast.c | view | annotate | diff | log | ||
src/gdlist.c | view | annotate | diff | log | ||
src/gtkui/gtk_ctrl.c | view | annotate | diff | log | ||
src/gtkui/gtk_gd.c | view | annotate | diff | log | ||
src/gtkui/gtk_path.c | view | annotate | diff | log | ||
src/gtkui/gtkcb.c | view | annotate | diff | log | ||
src/gtkui/gtkui.c | view | annotate | diff | log | ||
src/gtkui/gtkui.h | view | annotate | diff | log | ||
src/gui.h | view | annotate | diff | log | ||
src/guiutil.c | view | annotate | diff | log | ||
src/loader.c | view | annotate | diff | log | ||
src/main.c | view | annotate | diff | log |
1.1 --- a/src/Makefile.am Wed Jun 24 05:10:25 2009 +00001.2 +++ b/src/Makefile.am Wed Jun 24 06:06:40 2009 +00001.3 @@ -44,7 +44,7 @@1.4 gettext.h mem.c mem.h sdram.c mmio.h watch.c \1.5 asic.c asic.h clock.h serial.h \1.6 syscall.c syscall.h bios.c dcload.c gdbserver.c \1.7 - netutil.c netutil.h \1.8 + netutil.c netutil.h guiutil.c \1.9 gdrom/ide.c gdrom/ide.h gdrom/packet.h gdrom/gdimage.c \1.10 gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c gdrom/gdi.c \1.11 gdrom/edc_ecc.c gdrom/ecc.h gdrom/edc_crctable.h gdrom/edc_encoder.h \
2.1 --- a/src/Makefile.in Wed Jun 24 05:10:25 2009 +00002.2 +++ b/src/Makefile.in Wed Jun 24 06:06:40 2009 +00002.3 @@ -142,7 +142,7 @@2.4 lxdream.h dream.h gui.h cpu.h hook.h gettext.h mem.c mem.h \2.5 sdram.c mmio.h watch.c asic.c asic.h clock.h serial.h \2.6 syscall.c syscall.h bios.c dcload.c gdbserver.c netutil.c \2.7 - netutil.h gdrom/ide.c gdrom/ide.h gdrom/packet.h \2.8 + netutil.h guiutil.c gdrom/ide.c gdrom/ide.h gdrom/packet.h \2.9 gdrom/gdimage.c gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c \2.10 gdrom/cdi.c gdrom/gdi.c gdrom/edc_ecc.c gdrom/ecc.h \2.11 gdrom/edc_crctable.h gdrom/edc_encoder.h gdrom/edc_l2sq.h \2.12 @@ -238,42 +238,42 @@2.13 lxdream-asic.$(OBJEXT) lxdream-syscall.$(OBJEXT) \2.14 lxdream-bios.$(OBJEXT) lxdream-dcload.$(OBJEXT) \2.15 lxdream-gdbserver.$(OBJEXT) lxdream-netutil.$(OBJEXT) \2.16 - lxdream-ide.$(OBJEXT) lxdream-gdimage.$(OBJEXT) \2.17 - lxdream-gdrom.$(OBJEXT) lxdream-nrg.$(OBJEXT) \2.18 - lxdream-cdi.$(OBJEXT) lxdream-gdi.$(OBJEXT) \2.19 - lxdream-edc_ecc.$(OBJEXT) lxdream-dreamcast.$(OBJEXT) \2.20 - lxdream-eventq.$(OBJEXT) lxdream-sh4.$(OBJEXT) \2.21 - lxdream-intc.$(OBJEXT) lxdream-sh4mem.$(OBJEXT) \2.22 - lxdream-timer.$(OBJEXT) lxdream-dmac.$(OBJEXT) \2.23 - lxdream-mmu.$(OBJEXT) lxdream-sh4core.$(OBJEXT) \2.24 - lxdream-sh4dasm.$(OBJEXT) lxdream-sh4mmio.$(OBJEXT) \2.25 - lxdream-scif.$(OBJEXT) lxdream-sh4stat.$(OBJEXT) \2.26 - lxdream-xltcache.$(OBJEXT) lxdream-pmm.$(OBJEXT) \2.27 - lxdream-cache.$(OBJEXT) lxdream-armcore.$(OBJEXT) \2.28 - lxdream-armdasm.$(OBJEXT) lxdream-armmem.$(OBJEXT) \2.29 - lxdream-aica.$(OBJEXT) lxdream-audio.$(OBJEXT) \2.30 - lxdream-pvr2.$(OBJEXT) lxdream-pvr2mem.$(OBJEXT) \2.31 - lxdream-tacore.$(OBJEXT) lxdream-rendsort.$(OBJEXT) \2.32 - lxdream-texcache.$(OBJEXT) lxdream-yuv.$(OBJEXT) \2.33 - lxdream-rendsave.$(OBJEXT) lxdream-scene.$(OBJEXT) \2.34 - lxdream-gl_sl.$(OBJEXT) lxdream-gl_slsrc.$(OBJEXT) \2.35 - lxdream-glutil.$(OBJEXT) lxdream-glrender.$(OBJEXT) \2.36 - lxdream-maple.$(OBJEXT) lxdream-controller.$(OBJEXT) \2.37 - lxdream-kbd.$(OBJEXT) lxdream-mouse.$(OBJEXT) \2.38 - lxdream-lightgun.$(OBJEXT) lxdream-vmu.$(OBJEXT) \2.39 - lxdream-loader.$(OBJEXT) lxdream-bootstrap.$(OBJEXT) \2.40 - lxdream-util.$(OBJEXT) lxdream-gdlist.$(OBJEXT) \2.41 - lxdream-vmuvol.$(OBJEXT) lxdream-vmulist.$(OBJEXT) \2.42 - lxdream-display.$(OBJEXT) lxdream-audio_null.$(OBJEXT) \2.43 - lxdream-video_null.$(OBJEXT) lxdream-cd_mmc.$(OBJEXT) \2.44 - lxdream-video_gl.$(OBJEXT) lxdream-gl_fbo.$(OBJEXT) \2.45 - lxdream-hotkeys.$(OBJEXT) $(am__objects_1) $(am__objects_2) \2.46 - $(am__objects_3) $(am__objects_4) $(am__objects_5) \2.47 - $(am__objects_6) $(am__objects_7) $(am__objects_8) \2.48 - $(am__objects_9) $(am__objects_10) $(am__objects_11) \2.49 - $(am__objects_12) $(am__objects_13) $(am__objects_14) \2.50 - $(am__objects_15) $(am__objects_16) $(am__objects_17) \2.51 - $(am__objects_18)2.52 + lxdream-guiutil.$(OBJEXT) lxdream-ide.$(OBJEXT) \2.53 + lxdream-gdimage.$(OBJEXT) lxdream-gdrom.$(OBJEXT) \2.54 + lxdream-nrg.$(OBJEXT) lxdream-cdi.$(OBJEXT) \2.55 + lxdream-gdi.$(OBJEXT) lxdream-edc_ecc.$(OBJEXT) \2.56 + lxdream-dreamcast.$(OBJEXT) lxdream-eventq.$(OBJEXT) \2.57 + lxdream-sh4.$(OBJEXT) lxdream-intc.$(OBJEXT) \2.58 + lxdream-sh4mem.$(OBJEXT) lxdream-timer.$(OBJEXT) \2.59 + lxdream-dmac.$(OBJEXT) lxdream-mmu.$(OBJEXT) \2.60 + lxdream-sh4core.$(OBJEXT) lxdream-sh4dasm.$(OBJEXT) \2.61 + lxdream-sh4mmio.$(OBJEXT) lxdream-scif.$(OBJEXT) \2.62 + lxdream-sh4stat.$(OBJEXT) lxdream-xltcache.$(OBJEXT) \2.63 + lxdream-pmm.$(OBJEXT) lxdream-cache.$(OBJEXT) \2.64 + lxdream-armcore.$(OBJEXT) lxdream-armdasm.$(OBJEXT) \2.65 + lxdream-armmem.$(OBJEXT) lxdream-aica.$(OBJEXT) \2.66 + lxdream-audio.$(OBJEXT) lxdream-pvr2.$(OBJEXT) \2.67 + lxdream-pvr2mem.$(OBJEXT) lxdream-tacore.$(OBJEXT) \2.68 + lxdream-rendsort.$(OBJEXT) lxdream-texcache.$(OBJEXT) \2.69 + lxdream-yuv.$(OBJEXT) lxdream-rendsave.$(OBJEXT) \2.70 + lxdream-scene.$(OBJEXT) lxdream-gl_sl.$(OBJEXT) \2.71 + lxdream-gl_slsrc.$(OBJEXT) lxdream-glutil.$(OBJEXT) \2.72 + lxdream-glrender.$(OBJEXT) lxdream-maple.$(OBJEXT) \2.73 + lxdream-controller.$(OBJEXT) lxdream-kbd.$(OBJEXT) \2.74 + lxdream-mouse.$(OBJEXT) lxdream-lightgun.$(OBJEXT) \2.75 + lxdream-vmu.$(OBJEXT) lxdream-loader.$(OBJEXT) \2.76 + lxdream-bootstrap.$(OBJEXT) lxdream-util.$(OBJEXT) \2.77 + lxdream-gdlist.$(OBJEXT) lxdream-vmuvol.$(OBJEXT) \2.78 + lxdream-vmulist.$(OBJEXT) lxdream-display.$(OBJEXT) \2.79 + lxdream-audio_null.$(OBJEXT) lxdream-video_null.$(OBJEXT) \2.80 + lxdream-cd_mmc.$(OBJEXT) lxdream-video_gl.$(OBJEXT) \2.81 + lxdream-gl_fbo.$(OBJEXT) lxdream-hotkeys.$(OBJEXT) \2.82 + $(am__objects_1) $(am__objects_2) $(am__objects_3) \2.83 + $(am__objects_4) $(am__objects_5) $(am__objects_6) \2.84 + $(am__objects_7) $(am__objects_8) $(am__objects_9) \2.85 + $(am__objects_10) $(am__objects_11) $(am__objects_12) \2.86 + $(am__objects_13) $(am__objects_14) $(am__objects_15) \2.87 + $(am__objects_16) $(am__objects_17) $(am__objects_18)2.88 lxdream_OBJECTS = $(am_lxdream_OBJECTS)2.89 lxdream_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \2.90 $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \2.91 @@ -542,10 +542,10 @@2.92 lxdream_SOURCES = main.c version.c config.c config.h lxdream.h dream.h \2.93 gui.h cpu.h hook.h gettext.h mem.c mem.h sdram.c mmio.h \2.94 watch.c asic.c asic.h clock.h serial.h syscall.c syscall.h \2.95 - bios.c dcload.c gdbserver.c netutil.c netutil.h gdrom/ide.c \2.96 - gdrom/ide.h gdrom/packet.h gdrom/gdimage.c gdrom/gdrom.c \2.97 - gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c gdrom/gdi.c \2.98 - gdrom/edc_ecc.c gdrom/ecc.h gdrom/edc_crctable.h \2.99 + bios.c dcload.c gdbserver.c netutil.c netutil.h guiutil.c \2.100 + gdrom/ide.c gdrom/ide.h gdrom/packet.h gdrom/gdimage.c \2.101 + gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c \2.102 + gdrom/gdi.c gdrom/edc_ecc.c gdrom/ecc.h gdrom/edc_crctable.h \2.103 gdrom/edc_encoder.h gdrom/edc_l2sq.h gdrom/edc_scramble.h \2.104 gdrom/gddriver.h dreamcast.c dreamcast.h eventq.c eventq.h \2.105 sh4/sh4.c sh4/intc.c sh4/intc.h sh4/sh4mem.c sh4/timer.c \2.106 @@ -793,6 +793,7 @@2.107 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gtk_win.Po@am__quote@2.108 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gtkcb.Po@am__quote@2.109 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gtkui.Po@am__quote@2.110 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-guiutil.Po@am__quote@2.111 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-hotkeys.Po@am__quote@2.112 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-i386-dis.Po@am__quote@2.113 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-ide.Po@am__quote@2.114 @@ -1103,6 +1104,20 @@2.115 @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@2.116 @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lxdream-netutil.obj `if test -f 'netutil.c'; then $(CYGPATH_W) 'netutil.c'; else $(CYGPATH_W) '$(srcdir)/netutil.c'; fi`2.118 +lxdream-guiutil.o: guiutil.c2.119 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-guiutil.o -MD -MP -MF "$(DEPDIR)/lxdream-guiutil.Tpo" -c -o lxdream-guiutil.o `test -f 'guiutil.c' || echo '$(srcdir)/'`guiutil.c; \2.120 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lxdream-guiutil.Tpo" "$(DEPDIR)/lxdream-guiutil.Po"; else rm -f "$(DEPDIR)/lxdream-guiutil.Tpo"; exit 1; fi2.121 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='guiutil.c' object='lxdream-guiutil.o' libtool=no @AMDEPBACKSLASH@2.122 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@2.123 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lxdream-guiutil.o `test -f 'guiutil.c' || echo '$(srcdir)/'`guiutil.c2.124 +2.125 +lxdream-guiutil.obj: guiutil.c2.126 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-guiutil.obj -MD -MP -MF "$(DEPDIR)/lxdream-guiutil.Tpo" -c -o lxdream-guiutil.obj `if test -f 'guiutil.c'; then $(CYGPATH_W) 'guiutil.c'; else $(CYGPATH_W) '$(srcdir)/guiutil.c'; fi`; \2.127 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lxdream-guiutil.Tpo" "$(DEPDIR)/lxdream-guiutil.Po"; else rm -f "$(DEPDIR)/lxdream-guiutil.Tpo"; exit 1; fi2.128 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='guiutil.c' object='lxdream-guiutil.obj' libtool=no @AMDEPBACKSLASH@2.129 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@2.130 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lxdream-guiutil.obj `if test -f 'guiutil.c'; then $(CYGPATH_W) 'guiutil.c'; else $(CYGPATH_W) '$(srcdir)/guiutil.c'; fi`2.131 +2.132 lxdream-ide.o: gdrom/ide.c2.133 @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-ide.o -MD -MP -MF "$(DEPDIR)/lxdream-ide.Tpo" -c -o lxdream-ide.o `test -f 'gdrom/ide.c' || echo '$(srcdir)/'`gdrom/ide.c; \2.134 @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lxdream-ide.Tpo" "$(DEPDIR)/lxdream-ide.Po"; else rm -f "$(DEPDIR)/lxdream-ide.Tpo"; exit 1; fi
3.1 --- a/src/cocoaui/cocoa_ctrl.m Wed Jun 24 05:10:25 2009 +00003.2 +++ b/src/cocoaui/cocoa_ctrl.m Wed Jun 24 06:06:40 2009 +00003.3 @@ -596,13 +596,14 @@3.4 NSOpenPanel *panel = [NSOpenPanel openPanel];3.5 VMULoadValidator *valid = [[VMULoadValidator alloc] autorelease];3.6 [panel setDelegate: valid];3.7 - NSInteger result = [panel runModalForDirectory: [NSString stringWithUTF8String: lxdream_get_config_value(CONFIG_VMU_PATH)]3.8 + NSInteger result = [panel runModalForDirectory: [NSString stringWithUTF8String: gui_get_configurable_path(CONFIG_VMU_PATH)]3.9 file: nil types: array];3.10 if( result == NSOKButton ) {3.11 vmu_filename = [[panel filename] UTF8String];3.12 int idx = vmulist_get_index_by_filename(vmu_filename);3.13 [sender selectItemWithTag: (FIRST_VMU_TAG+idx)];3.14 new_device_class = &vmu_class;3.15 + gui_set_configurable_path(CONFIG_VMU_PATH, [[panel directory] UTF8String]);3.16 } else {3.17 /* Cancelled - restore previous value */3.18 setDevicePopupSelection( sender, current );3.19 @@ -615,7 +616,7 @@3.20 [panel setRequiredFileType: @"vmu"];3.21 VMUCreateValidator *valid = [[VMUCreateValidator alloc] autorelease];3.22 [panel setDelegate: valid];3.23 - NSInteger result = [panel runModalForDirectory: [NSString stringWithUTF8String: lxdream_get_config_value(CONFIG_VMU_PATH)]3.24 + NSInteger result = [panel runModalForDirectory: [NSString stringWithUTF8String: gui_get_configurable_path(CONFIG_VMU_PATH)]3.25 file: nil];3.26 if( result == NSFileHandlingPanelOKButton ) {3.27 /* Validator has already created the file by now */3.28 @@ -623,6 +624,7 @@3.29 int idx = vmulist_get_index_by_filename(vmu_filename);3.30 [sender selectItemWithTag: (FIRST_VMU_TAG+idx)];3.31 new_device_class = &vmu_class;3.32 + gui_set_configurable_path(CONFIG_VMU_PATH, [[panel directory] UTF8String]);3.33 } else {3.34 setDevicePopupSelection( sender, current );3.35 return;
4.1 --- a/src/cocoaui/cocoa_path.m Wed Jun 24 05:10:25 2009 +00004.2 +++ b/src/cocoaui/cocoa_path.m Wed Jun 24 06:06:40 2009 +00004.3 @@ -40,7 +40,7 @@4.4 int height = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;4.6 for( i=0; i<=CONFIG_KEY_MAX; i++ ) {4.7 - const struct lxdream_config_entry *entry = lxdream_get_config_entry(i);4.8 + const struct lxdream_config_entry *entry = lxdream_get_global_config_entry(i);4.9 if( entry->label != NULL ) {4.10 NSRect frame = NSMakeRect( TEXT_GAP, height -((TEXT_HEIGHT+TEXT_GAP)*i - 2),4.11 150, LABEL_HEIGHT );4.12 @@ -66,7 +66,7 @@4.13 {4.14 int tag = [[notify object] tag];4.15 const char *str = [[[notify object] stringValue] UTF8String];4.16 - const char *oldval = lxdream_get_config_value(tag);4.17 + const char *oldval = lxdream_get_global_config_value(tag);4.18 if( str[0] == '\0' )4.19 str = NULL;4.20 if( oldval == NULL ? str != NULL : (str == NULL || strcmp(oldval,str) != 0 ) ) {
5.1 --- a/src/cocoaui/cocoaui.h Wed Jun 24 05:10:25 2009 +00005.2 +++ b/src/cocoaui/cocoaui.h Wed Jun 24 06:06:40 2009 +00005.3 @@ -21,6 +21,7 @@5.5 #import <AppKit/AppKit.h>5.6 #include "lxdream.h"5.7 +#include "gui.h"5.8 #include "gettext.h"5.10 #ifdef __cplusplus
6.1 --- a/src/cocoaui/cocoaui.m Wed Jun 24 05:10:25 2009 +00006.2 +++ b/src/cocoaui/cocoaui.m Wed Jun 24 06:06:40 2009 +00006.3 @@ -220,47 +220,47 @@6.4 - (void) load_action: (id)sender6.5 {6.6 NSOpenPanel *panel = [NSOpenPanel openPanel];6.7 - const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);6.8 - NSString *path = (dir == NULL ? NSHomeDirectory() : [NSString stringWithCString: dir]);6.9 + NSString *path = [NSString stringWithCString: gui_get_configurable_path(CONFIG_SAVE_PATH)];6.10 NSArray *fileTypes = [NSArray arrayWithObject: @"dst"];6.11 int result = [panel runModalForDirectory: path file: nil types: fileTypes];6.12 if( result == NSOKButton && [[panel filenames] count] > 0 ) {6.13 NSString *filename = [[panel filenames] objectAtIndex: 0];6.14 dreamcast_load_state( [filename UTF8String] );6.15 + gui_set_configurable_path(CONFIG_SAVE_PATH, [[panel directory] UTF8String]);6.16 }6.17 }6.18 - (void) save_action: (id)sender6.19 {6.20 NSSavePanel *panel = [NSSavePanel savePanel];6.21 - const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);6.22 - NSString *path = (dir == NULL ? NSHomeDirectory() : [NSString stringWithCString: dir]);6.23 + NSString *path = [NSString stringWithCString: gui_get_configurable_path(CONFIG_SAVE_PATH)];6.24 [panel setRequiredFileType: @"dst"];6.25 int result = [panel runModalForDirectory: path file:@""];6.26 if( result == NSOKButton ) {6.27 NSString *filename = [panel filename];6.28 dreamcast_save_state( [filename UTF8String] );6.29 + gui_set_configurable_path(CONFIG_SAVE_PATH, [[panel directory] UTF8String]);6.30 }6.31 }6.32 - (void) load_binary_action: (id)sender6.33 {6.34 NSOpenPanel *panel = [NSOpenPanel openPanel];6.35 - const gchar *dir = lxdream_get_config_value(CONFIG_DEFAULT_PATH);6.36 - NSString *path = (dir == NULL ? NSHomeDirectory() : [NSString stringWithCString: dir]);6.37 + NSString *path = [NSString stringWithCString: gui_get_configurable_path(CONFIG_DEFAULT_PATH)];6.38 int result = [panel runModalForDirectory: path file: nil types: nil];6.39 if( result == NSOKButton && [[panel filenames] count] > 0 ) {6.40 NSString *filename = [[panel filenames] objectAtIndex: 0];6.41 file_load_magic( [filename UTF8String] );6.42 + gui_set_configurable_path(CONFIG_DEFAULT_PATH, [[panel directory] UTF8String]);6.43 }6.44 }6.45 - (void) mount_action: (id)sender6.46 {6.47 NSOpenPanel *panel = [NSOpenPanel openPanel];6.48 - const gchar *dir = lxdream_get_config_value(CONFIG_DEFAULT_PATH);6.49 - NSString *path = (dir == NULL ? NSHomeDirectory() : [NSString stringWithCString: dir]);6.50 + NSString *path = [NSString stringWithCString: gui_get_configurable_path(CONFIG_DEFAULT_PATH)];6.51 int result = [panel runModalForDirectory: path file: nil types: nil];6.52 if( result == NSOKButton && [[panel filenames] count] > 0 ) {6.53 NSString *filename = [[panel filenames] objectAtIndex: 0];6.54 gdrom_mount_image( [filename UTF8String] );6.55 + gui_set_configurable_path(CONFIG_DEFAULT_PATH, [[panel directory] UTF8String]);6.56 }6.57 }6.58 - (void) pause_action: (id)sender
7.1 --- a/src/config.c Wed Jun 24 05:10:25 2009 +00007.2 +++ b/src/config.c Wed Jun 24 06:06:40 2009 +00007.3 @@ -18,9 +18,11 @@7.5 #include <unistd.h>7.6 #include <stdio.h>7.7 +#include <ctype.h>7.8 #include <errno.h>7.9 #include <stdlib.h>7.10 #include <string.h>7.11 +#include <wordexp.h>7.12 #include <glib/gmem.h>7.13 #include <glib/gstrfuncs.h>7.14 #include "dream.h"7.15 @@ -136,7 +138,7 @@7.16 maple_detach_all();7.17 }7.19 -const gchar *lxdream_get_config_value( int key )7.20 +const gchar *lxdream_get_global_config_value( int key )7.21 {7.22 return global_config[key].value;7.23 }7.24 @@ -144,7 +146,7 @@7.25 GList *lxdream_get_global_config_list_value( int key )7.26 {7.27 GList *result = NULL;7.28 - const gchar *str = lxdream_get_config_value( key );7.29 + const gchar *str = lxdream_get_global_config_value( key );7.30 if( str != NULL ) {7.31 gchar **strv = g_strsplit(str, ":",0);7.32 int i;7.33 @@ -161,7 +163,7 @@7.34 if( list == NULL ) {7.35 lxdream_set_global_config_value( key, NULL );7.36 } else {7.37 - GList *ptr;7.38 + const GList *ptr;7.39 int size = 0;7.41 for( ptr = list; ptr != NULL; ptr = g_list_next(ptr) ) {7.42 @@ -177,6 +179,100 @@7.43 }7.44 }7.46 +gchar *get_expanded_path( const gchar *input )7.47 +{7.48 + wordexp_t we;7.49 + if( input == NULL ) {7.50 + return NULL;7.51 + }7.52 + memset(&we,0,sizeof(we));7.53 + int result = wordexp(input, &we, WRDE_NOCMD);7.54 + if( result != 0 || we.we_wordc == 0 ) {7.55 + /* On failure, return the original input unchanged */7.56 + return g_strdup(input);7.57 + } else {7.58 + /* On success, concatenate all 'words' together into a single7.59 + * space-separated string7.60 + */7.61 + int length = we.we_wordc, i;7.62 + gchar *result, *p;7.63 +7.64 + for( i=0; i<we.we_wordc; i++ ) {7.65 + length += strlen(we.we_wordv[i]);7.66 + }7.67 + p = result = g_malloc(length);7.68 + for( i=0; i<we.we_wordc; i++ ) {7.69 + if( i != 0 )7.70 + *p++ = ' ';7.71 + strcpy( p, we.we_wordv[i] );7.72 + p += strlen(p);7.73 + }7.74 + wordfree(&we);7.75 + return result;7.76 + }7.77 +}7.78 +7.79 +/**7.80 + * Test if we need to escape a path to prevent substitution mangling.7.81 + * @return TRUE if the input value contains any character that doesn't7.82 + * match [a-zA-Z0-9._@%/] (this will escape slightly more than it needs to,7.83 + * but is safe)7.84 + */7.85 +gboolean path_needs_escaping( const gchar *value )7.86 +{7.87 + const gchar *p = value;7.88 + while( *p ) {7.89 + if( !isalnum(*p) && *p != '.' && *p != '_' &&7.90 + *p != '@' && *p != '%' && *p != '/' ) {7.91 + return TRUE;7.92 + }7.93 + p++;7.94 + }7.95 + return FALSE;7.96 +}7.97 +7.98 +gchar *get_escaped_path( const gchar *value )7.99 +{7.100 + if( value != NULL && path_needs_escaping(value) ) {7.101 + /* Escape with "", and backslash the remaining characters:7.102 + * \ " $ `7.103 + */7.104 + char buf[strlen(value)*2+3];7.105 + const char *s = value;7.106 + char *p = buf;7.107 + *p++ = '\"';7.108 + while( *s ) {7.109 + if( *s == '\\' || *s == '"' || *s == '$' || *s == '`' ) {7.110 + *p++ = '\\';7.111 + }7.112 + *p++ = *s++;7.113 + }7.114 + *p++ = '\"';7.115 + *p = '\0';7.116 + return g_strdup(buf);7.117 + } else {7.118 + return g_strdup(value);7.119 + }7.120 +}7.121 +7.122 +gchar *lxdream_get_global_config_path_value( int key )7.123 +{7.124 + const gchar *str = lxdream_get_global_config_value(key);7.125 + if( str == NULL ) {7.126 + return NULL;7.127 + } else {7.128 + return get_expanded_path(str);7.129 + }7.130 +}7.131 +7.132 +const gchar *lxdream_set_global_config_path_value( int key, const gchar *value )7.133 +{7.134 + gchar *temp = get_escaped_path(value);7.135 + lxdream_set_global_config_value(key,temp);7.136 + g_free(temp);7.137 + return lxdream_get_global_config_value(key);7.138 +}7.139 +7.140 void lxdream_set_config_value( lxdream_config_entry_t param, const gchar *value )7.141 {7.142 if( param->value != value ) {7.143 @@ -192,7 +288,7 @@7.144 lxdream_set_config_value(&global_config[key], value);7.145 }7.147 -const struct lxdream_config_entry * lxdream_get_config_entry( int key )7.148 +const struct lxdream_config_entry * lxdream_get_global_config_entry( int key )7.149 {7.150 return &global_config[key];7.151 }
8.1 --- a/src/config.h Wed Jun 24 05:10:25 2009 +00008.2 +++ b/src/config.h Wed Jun 24 06:06:40 2009 +00008.3 @@ -62,15 +62,32 @@8.4 extern struct lxdream_config_group lxdream_config_root[];8.6 /* Global config values */8.7 -const gchar *lxdream_get_config_value( int key );8.8 -const struct lxdream_config_entry * lxdream_get_config_entry( int key );8.9 +const gchar *lxdream_get_global_config_value( int key );8.10 +const struct lxdream_config_entry * lxdream_get_global_config_entry( int key );8.11 +void lxdream_set_global_config_value( int key, const gchar *value );8.12 +8.13 void lxdream_register_config_group( const gchar *key, lxdream_config_entry_t group );8.14 -void lxdream_set_global_config_value( int key, const gchar *value );8.15 void lxdream_set_config_value( lxdream_config_entry_t entry, const gchar *value );8.16 gboolean lxdream_set_group_value( lxdream_config_group_t group, const gchar *key, const gchar *value );8.17 void lxdream_copy_config_list( lxdream_config_entry_t dest, lxdream_config_entry_t src );8.19 /**8.20 + * Return a fully expanded path value for a key - this performs substitutions8.21 + * for ~ and simple shell variables ($VAR and ${VAR})8.22 + *8.23 + * The returned string is newly allocated and must be freed by the caller8.24 + */8.25 +gchar *lxdream_get_global_config_path_value( int key );8.26 +8.27 +/**8.28 + * Set a path value for a key, escaping if necessary to protect against8.29 + * shell-substitution on the round trip.8.30 + *8.31 + * @return the resultant config value.8.32 + */8.33 +const gchar *lxdream_set_global_config_path_value( int key, const gchar *value );8.34 +8.35 +/**8.36 * Construct a list of strings for the given config key - The caller is8.37 * responsible for freeing the list and its values.8.38 */8.39 @@ -106,6 +123,19 @@8.40 */8.41 gboolean lxdream_save_config( );8.43 +/**8.44 + * Escape a pathname if needed to prevent shell substitution.8.45 + * @return a newly allocated string (or NULL if the input is NULL)8.46 + */8.47 +gchar *get_escaped_path( const gchar *name );8.48 +8.49 +/**8.50 + * Expand a pathname according to standard shell substitution rules8.51 + * (excluding command substitutions).8.52 + * @return a newly allocated string (or NULL if the input is NULL)8.53 + */8.54 +gchar *get_expanded_path( const gchar *name );8.55 +8.56 #ifdef __cplusplus8.57 }8.58 #endif
9.1 --- a/src/dreamcast.c Wed Jun 24 05:10:25 2009 +00009.2 +++ b/src/dreamcast.c Wed Jun 24 06:06:40 2009 +00009.3 @@ -85,8 +85,8 @@9.4 */9.5 void dreamcast_configure( )9.6 {9.7 - const char *bios_path = lxdream_get_config_value(CONFIG_BIOS_PATH);9.8 - const char *flash_path = lxdream_get_config_value(CONFIG_FLASH_PATH);9.9 + char *bios_path = lxdream_get_global_config_path_value(CONFIG_BIOS_PATH);9.10 + char *flash_path = lxdream_get_global_config_path_value(CONFIG_FLASH_PATH);9.12 dreamcast_register_module( &eventq_module );9.13 /* Register the memory framework */9.14 @@ -118,23 +118,29 @@9.15 dreamcast_register_module( &aica_module );9.16 dreamcast_register_module( &maple_module );9.17 dreamcast_register_module( &ide_module );9.18 +9.19 + g_free(bios_path);9.20 + g_free(flash_path);9.21 }9.23 void dreamcast_config_changed(void)9.24 {9.25 - const char *bios_path = lxdream_get_config_value(CONFIG_BIOS_PATH);9.26 - const char *flash_path = lxdream_get_config_value(CONFIG_FLASH_PATH);9.27 + char *bios_path = lxdream_get_global_config_path_value(CONFIG_BIOS_PATH);9.28 + char *flash_path = lxdream_get_global_config_path_value(CONFIG_FLASH_PATH);9.29 dreamcast_has_bios = mem_load_rom( dc_boot_rom, bios_path, 2 MB, 0x89f2b1a1 );9.30 if( flash_path != NULL && flash_path[0] != '\0' ) {9.31 mem_load_block( flash_path, 0x00200000, 0x00020000 );9.32 }9.33 + g_free(bios_path);9.34 + g_free(flash_path);9.35 }9.37 void dreamcast_save_flash()9.38 {9.39 if( dreamcast_has_flash ) {9.40 - const char *file = lxdream_get_config_value(CONFIG_FLASH_PATH);9.41 + char *file = lxdream_get_global_config_path_value(CONFIG_FLASH_PATH);9.42 mem_save_block( file, 0x00200000, 0x00020000 );9.43 + g_free(file);9.44 }9.45 }
10.1 --- a/src/gdlist.c Wed Jun 24 05:10:25 2009 +000010.2 +++ b/src/gdlist.c Wed Jun 24 06:06:40 2009 +000010.3 @@ -116,7 +116,7 @@10.4 }10.5 }10.7 - lxdream_set_global_config_value( CONFIG_GDROM, disc_name );10.8 + lxdream_set_global_config_path_value( CONFIG_GDROM, disc_name );10.9 lxdream_save_config();10.11 CALL_HOOKS( gdrom_list_change_hook, list_changed, posn );
11.1 --- a/src/gtkui/gtk_ctrl.c Wed Jun 24 05:10:25 2009 +000011.2 +++ b/src/gtkui/gtk_ctrl.c Wed Jun 24 06:06:40 2009 +000011.3 @@ -249,8 +249,8 @@11.5 if( devclz == LOAD_VMU_TAG ) {11.6 devclz = NULL;11.7 - vmu_filename = open_file_dialog( _("Load VMU"), "*.vmu", "VMU Files",11.8 - lxdream_get_config_value(CONFIG_VMU_PATH) );11.9 + vmu_filename = open_file_dialog( _("Load VMU"), "*.vmu", "VMU Files",11.10 + CONFIG_VMU_PATH );11.11 if( vmu_filename != NULL ) {11.12 vmu_volume_t vol = vmu_volume_load( vmu_filename );11.13 if( vol != NULL ) {11.14 @@ -264,7 +264,7 @@11.15 } else if( devclz == CREATE_VMU_TAG ) {11.16 devclz = NULL;11.17 vmu_filename = save_file_dialog( _("Create VMU"), "*.vmu", "VMU Files",11.18 - lxdream_get_config_value(CONFIG_VMU_PATH) );11.19 + CONFIG_VMU_PATH );11.20 if( vmu_filename != NULL ) {11.21 devclz = &vmu_class;11.22 set_selection = TRUE;
12.1 --- a/src/gtkui/gtk_gd.c Wed Jun 24 05:10:25 2009 +000012.2 +++ b/src/gtkui/gtk_gd.c Wed Jun 24 06:06:40 2009 +000012.3 @@ -30,8 +30,7 @@12.4 static void gdrom_menu_open_image_callback( GtkWidget *widget, gpointer user_data )12.5 {12.6 if( !gdrom_menu_adjusting ) {12.7 - const gchar *dir = lxdream_get_config_value(CONFIG_DEFAULT_PATH);12.8 - open_file_dialog_cb( _("Open..."), gdrom_mount_image, NULL, NULL, dir );12.9 + open_file_dialog_cb( _("Open..."), gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );12.10 }12.11 }
13.1 --- a/src/gtkui/gtk_path.c Wed Jun 24 05:10:25 2009 +000013.2 +++ b/src/gtkui/gtk_path.c Wed Jun 24 06:06:40 2009 +000013.3 @@ -25,18 +25,7 @@13.4 #include "config.h"13.5 #include "gtkui/gtkui.h"13.7 -static const gchar *path_label[] = { N_("Bios rom"), N_("Flash rom"), N_("Default disc path"),13.8 - N_("Save state path"), N_("Bootstrap IP.BIN") };13.9 -static const int path_id[] = { CONFIG_BIOS_PATH, CONFIG_FLASH_PATH, CONFIG_DEFAULT_PATH,13.10 - CONFIG_SAVE_PATH, CONFIG_BOOTSTRAP };13.11 -static GtkFileChooserAction path_action[] = {13.12 - GTK_FILE_CHOOSER_ACTION_OPEN,13.13 - GTK_FILE_CHOOSER_ACTION_OPEN,13.14 - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,13.15 - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,13.16 - GTK_FILE_CHOOSER_ACTION_OPEN };13.17 -13.18 -static GtkWidget *path_entry[5];13.19 +static GtkWidget *path_entry[CONFIG_KEY_MAX];13.21 static gboolean path_file_button_clicked( GtkWidget *button, gpointer user_data )13.22 {13.23 @@ -46,14 +35,16 @@13.24 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,13.25 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,13.26 NULL );13.27 - const gchar *filename = gtk_entry_get_text(GTK_ENTRY(entry));13.28 + gchar *filename = get_expanded_path(gtk_entry_get_text(GTK_ENTRY(entry)));13.29 gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file), filename );13.30 gtk_window_set_modal( GTK_WINDOW(file), TRUE );13.31 gtk_widget_show_all( file );13.32 gint result = gtk_dialog_run(GTK_DIALOG(file));13.33 + g_free(filename);13.34 if( result == GTK_RESPONSE_ACCEPT ) {13.35 - filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );13.36 + filename = get_escaped_path(gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) ));13.37 gtk_entry_set_text(GTK_ENTRY(entry), filename);13.38 + g_free(filename);13.39 }13.40 gtk_widget_destroy(file);13.41 return TRUE;13.42 @@ -67,15 +58,17 @@13.43 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,13.44 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,13.45 NULL );13.46 - const gchar *filename = gtk_entry_get_text(GTK_ENTRY(entry));13.47 + gchar *filename = get_expanded_path(gtk_entry_get_text(GTK_ENTRY(entry)));13.48 gtk_file_chooser_set_action( GTK_FILE_CHOOSER(file), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER );13.49 gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file), filename );13.50 gtk_window_set_modal( GTK_WINDOW(file), TRUE );13.51 gtk_widget_show_all( file );13.52 gint result = gtk_dialog_run(GTK_DIALOG(file));13.53 + g_free(filename);13.54 if( result == GTK_RESPONSE_ACCEPT ) {13.55 - filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );13.56 + filename = get_escaped_path(gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) ));13.57 gtk_entry_set_text(GTK_ENTRY(entry), filename);13.58 + g_free(filename);13.59 }13.60 gtk_widget_destroy(file);13.61 return TRUE;13.62 @@ -83,27 +76,32 @@13.64 GtkWidget *path_panel_new(void)13.65 {13.66 - GtkWidget *table = gtk_table_new( 5, 3, FALSE );13.67 - int i;13.68 - for( i=0; i<5; i++ ) {13.69 - GtkWidget *text = path_entry[i] = gtk_entry_new();13.70 - GtkWidget *button = gtk_button_new();13.71 - gtk_table_attach( GTK_TABLE(table), gtk_label_new(Q_(path_label[i])), 0, 1, i, i+1,13.72 - GTK_SHRINK, GTK_SHRINK, 0, 0);13.73 - gtk_entry_set_text( GTK_ENTRY(text), lxdream_get_config_value(path_id[i]) );13.74 - gtk_entry_set_width_chars( GTK_ENTRY(text), 48 );13.75 - gtk_table_attach_defaults( GTK_TABLE(table), text, 1, 2, i, i+1 );13.76 - gtk_table_attach( GTK_TABLE(table), button, 2, 3, i, i+1, GTK_SHRINK, GTK_SHRINK, 0, 0 );13.77 - if( path_action[i] == GTK_FILE_CHOOSER_ACTION_OPEN ) {13.78 - GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);13.79 - gtk_button_set_image( GTK_BUTTON(button), image );13.80 - g_signal_connect( button, "clicked", G_CALLBACK(path_file_button_clicked), text );13.81 - } else {13.82 - GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);13.83 - gtk_button_set_image( GTK_BUTTON(button), image );13.84 - g_signal_connect( button, "clicked", G_CALLBACK(path_dir_button_clicked), text );13.85 + int i, y=0;13.86 + GtkWidget *table = gtk_table_new( CONFIG_KEY_MAX, 3, FALSE );13.87 + for( i=0; i<CONFIG_KEY_MAX; i++ ) {13.88 + const struct lxdream_config_entry *entry = lxdream_get_global_config_entry(i);13.89 + if( entry->label != NULL ) {13.90 + GtkWidget *text = path_entry[i] = gtk_entry_new();13.91 + GtkWidget *button = gtk_button_new();13.92 + gtk_table_attach( GTK_TABLE(table), gtk_label_new(Q_(entry->label)), 0, 1, y, y+1,13.93 + GTK_SHRINK, GTK_SHRINK, 0, 0);13.94 + gtk_entry_set_text( GTK_ENTRY(text), lxdream_get_global_config_value(i) );13.95 + gtk_entry_set_width_chars( GTK_ENTRY(text), 48 );13.96 + gtk_table_attach_defaults( GTK_TABLE(table), text, 1, 2, y, y+1 );13.97 + gtk_table_attach( GTK_TABLE(table), button, 2, 3, y, y+1, GTK_SHRINK, GTK_SHRINK, 0, 0 );13.98 + if( entry->type == CONFIG_TYPE_FILE ) {13.99 + GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);13.100 + gtk_button_set_image( GTK_BUTTON(button), image );13.101 + g_signal_connect( button, "clicked", G_CALLBACK(path_file_button_clicked), text );13.102 + } else {13.103 + GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);13.104 + gtk_button_set_image( GTK_BUTTON(button), image );13.105 + g_signal_connect( button, "clicked", G_CALLBACK(path_dir_button_clicked), text );13.106 + }13.107 + y++;13.108 }13.109 }13.110 + gtk_table_resize( GTK_TABLE(table), y, 3 );13.111 return table;13.113 }13.114 @@ -112,13 +110,16 @@13.115 {13.116 if( isOK ) {13.117 int i;13.118 - for(i=0; i<5; i++ ) {13.119 - const char *filename = gtk_entry_get_text( GTK_ENTRY(path_entry[i]) );13.120 - lxdream_set_global_config_value( path_id[i], filename );13.121 + for(i=0; i<CONFIG_KEY_MAX; i++ ) {13.122 + if( path_entry[i] != NULL ) {13.123 + const char *filename = gtk_entry_get_text( GTK_ENTRY(path_entry[i]) );13.124 + lxdream_set_global_config_value( i, filename );13.125 + }13.126 }13.128 lxdream_save_config();13.129 dreamcast_config_changed();13.130 + gui_config_paths_changed();13.131 gtk_gui_update();13.132 }13.133 }
14.1 --- a/src/gtkui/gtkcb.c Wed Jun 24 05:10:25 2009 +000014.2 +++ b/src/gtkui/gtkcb.c Wed Jun 24 06:06:40 2009 +000014.3 @@ -40,58 +40,74 @@14.4 }14.6 gchar *open_file_dialog( const char *title, const char *pattern, const char *patname,14.7 - const gchar *initial_dir )14.8 + int initial_dir_key )14.9 {14.10 GtkWidget *file;14.11 gchar *filename = NULL;14.12 - gchar *initial_path = get_absolute_path(initial_dir);14.13 +14.14 file = gtk_file_chooser_dialog_new( title, NULL,14.15 GTK_FILE_CHOOSER_ACTION_OPEN,14.16 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,14.17 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,14.18 NULL );14.19 add_file_pattern( GTK_FILE_CHOOSER(file), pattern, patname );14.20 - gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), initial_path );14.21 + if( initial_dir_key != -1 ) {14.22 + gchar *initial_path = get_absolute_path(gui_get_configurable_path(initial_dir_key));14.23 + gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), initial_path );14.24 + g_free(initial_path);14.25 + }14.26 gtk_window_set_modal( GTK_WINDOW(file), TRUE );14.27 gtk_dialog_set_default_response( GTK_DIALOG(file), GTK_RESPONSE_ACCEPT );14.28 int result = gtk_dialog_run( GTK_DIALOG(file) );14.29 if( result == GTK_RESPONSE_ACCEPT ) {14.30 filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );14.31 + if( initial_dir_key != -1 ) {14.32 + gchar *end_path = gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(file) );14.33 + gui_set_configurable_path(initial_dir_key,end_path);14.34 + g_free(end_path);14.35 + }14.36 }14.37 gtk_widget_destroy(file);14.38 - g_free(initial_path);14.40 return filename;14.41 }14.43 gchar *save_file_dialog( const char *title, const char *pattern, const char *patname,14.44 - const gchar *initial_dir )14.45 + int initial_dir_key )14.46 {14.47 GtkWidget *file;14.48 gchar *filename;14.49 - gchar *initial_path = get_absolute_path(initial_dir);14.50 +14.51 file = gtk_file_chooser_dialog_new( title, NULL,14.52 GTK_FILE_CHOOSER_ACTION_SAVE,14.53 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,14.54 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,14.55 NULL );14.56 add_file_pattern( GTK_FILE_CHOOSER(file), pattern, patname );14.57 - gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), initial_path );14.58 + if( initial_dir_key != -1 ) {14.59 + gchar *initial_path = get_absolute_path(gui_get_configurable_path(initial_dir_key));14.60 + gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(file), initial_path );14.61 + g_free(initial_path);14.62 + }14.63 gtk_window_set_modal( GTK_WINDOW(file), TRUE );14.64 gtk_dialog_set_default_response( GTK_DIALOG(file), GTK_RESPONSE_ACCEPT );14.65 int result = gtk_dialog_run( GTK_DIALOG(file) );14.66 if( result == GTK_RESPONSE_ACCEPT ) {14.67 filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );14.68 + if( initial_dir_key != -1 ) {14.69 + gchar *end_path = gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(file) );14.70 + gui_set_configurable_path(initial_dir_key,end_path);14.71 + g_free(end_path);14.72 + }14.73 }14.74 gtk_widget_destroy(file);14.75 - g_free(initial_path);14.76 return filename;14.77 }14.79 void open_file_dialog_cb( const char *title, file_callback_t action, const char *pattern, const char *patname,14.80 - const gchar *initial_dir )14.81 + int initial_dir_key )14.82 {14.83 - gchar *filename = open_file_dialog( title, pattern, patname, initial_dir );14.84 + gchar *filename = open_file_dialog( title, pattern, patname, initial_dir_key );14.85 if( filename != NULL ) {14.86 action( filename );14.87 g_free(filename);14.88 @@ -99,9 +115,9 @@14.89 }14.91 void save_file_dialog_cb( const char *title, file_callback_t action, const char *pattern, const char *patname,14.92 - const gchar *initial_dir )14.93 + int initial_dir_key )14.94 {14.95 - gchar *filename = save_file_dialog( title, pattern, patname, initial_dir );14.96 + gchar *filename = save_file_dialog( title, pattern, patname, initial_dir_key );14.97 if( filename != NULL ) {14.98 action(filename);14.99 g_free(filename);14.100 @@ -110,8 +126,7 @@14.102 void mount_action_callback( GtkAction *action, gpointer user_data)14.103 {14.104 - const gchar *dir = lxdream_get_config_value(CONFIG_DEFAULT_PATH);14.105 - open_file_dialog_cb( "Open...", gdrom_mount_image, NULL, NULL, dir );14.106 + open_file_dialog_cb( "Open...", gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );14.107 }14.108 void reset_action_callback( GtkAction *action, gpointer user_data)14.109 {14.110 @@ -130,8 +145,7 @@14.112 void load_binary_action_callback( GtkAction *action, gpointer user_data)14.113 {14.114 - const gchar *dir = lxdream_get_config_value(CONFIG_DEFAULT_PATH);14.115 - open_file_dialog_cb( "Open Binary...", file_load_magic, NULL, NULL, dir );14.116 + open_file_dialog_cb( "Open Binary...", file_load_magic, NULL, NULL, CONFIG_DEFAULT_PATH );14.117 }14.119 void load_state_preview_callback( GtkFileChooser *chooser, gpointer user_data )14.120 @@ -157,7 +171,7 @@14.121 {14.122 GtkWidget *file, *preview, *frame, *align;14.123 GtkRequisition size;14.124 - const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);14.125 + const gchar *dir = gui_get_configurable_path(CONFIG_SAVE_PATH);14.126 gchar *path = get_absolute_path(dir);14.127 file = gtk_file_chooser_dialog_new( _("Load state..."), NULL,14.128 GTK_FILE_CHOOSER_ACTION_OPEN,14.129 @@ -186,6 +200,9 @@14.130 int result = gtk_dialog_run( GTK_DIALOG(file) );14.131 if( result == GTK_RESPONSE_ACCEPT ) {14.132 gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) );14.133 + gchar *end_path = gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(file) );14.134 + gui_set_configurable_path(CONFIG_SAVE_PATH,end_path);14.135 + g_free(end_path);14.136 dreamcast_load_state( filename );14.137 }14.138 gtk_widget_destroy(file);14.139 @@ -194,8 +211,7 @@14.141 void save_state_action_callback( GtkAction *action, gpointer user_data)14.142 {14.143 - const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);14.144 - save_file_dialog_cb( "Save state...", dreamcast_save_state, "*.dst", _("lxDream Save State (*.dst)"), dir );14.145 + save_file_dialog_cb( "Save state...", dreamcast_save_state, "*.dst", _("lxDream Save State (*.dst)"), CONFIG_SAVE_PATH );14.146 }14.147 void about_action_callback( GtkAction *action, gpointer user_data)14.148 {14.149 @@ -269,8 +285,7 @@14.151 void save_scene_action_callback( GtkAction *action, gpointer user_data)14.152 {14.153 - const gchar *dir = lxdream_get_config_value(CONFIG_SAVE_PATH);14.154 - save_file_dialog_cb( _("Save next scene..."), pvr2_save_next_scene, "*.dsc", _("lxdream scene file (*.dsc)"), dir );14.155 + save_file_dialog_cb( _("Save next scene..."), pvr2_save_next_scene, "*.dsc", _("lxdream scene file (*.dsc)"), CONFIG_SAVE_PATH );14.156 }14.158 int debug_window_get_selected_row( debug_window_t data );
15.1 --- a/src/gtkui/gtkui.c Wed Jun 24 05:10:25 2009 +000015.2 +++ b/src/gtkui/gtkui.c Wed Jun 24 06:06:40 2009 +000015.3 @@ -544,17 +544,4 @@15.4 return keyval;15.5 }15.7 -gchar *get_absolute_path( const gchar *in_path )15.8 -{15.9 - char tmp[PATH_MAX];15.10 - if( in_path == NULL ) {15.11 - return NULL;15.12 - }15.13 - if( in_path[0] == '/' || in_path[0] == 0 ) {15.14 - return g_strdup(in_path);15.15 - } else {15.16 - getcwd(tmp, sizeof(tmp));15.17 - return g_strdup_printf("%s%c%s", tmp, G_DIR_SEPARATOR, in_path);15.18 - }15.19 -}
16.1 --- a/src/gtkui/gtkui.h Wed Jun 24 05:10:25 2009 +000016.2 +++ b/src/gtkui/gtkui.h Wed Jun 24 06:06:40 2009 +000016.3 @@ -89,13 +89,13 @@16.5 typedef gboolean (*file_callback_t)( const gchar *filename );16.6 gchar *open_file_dialog( const char *title, const char *pattern, const char *patname,16.7 - const gchar *initial_dir );16.8 + int initial_dir_key );16.9 gchar *save_file_dialog( const char *title, const char *pattern, const char *patname,16.10 - const gchar *initial_dir );16.11 + int initial_dir_key );16.12 void open_file_dialog_cb( const char *title, file_callback_t action, const char *pattern, const char *patname,16.13 - const gchar *initial_dir );16.14 + int initial_dir_key );16.15 void save_file_dialog_cb( const char *title, file_callback_t action, const char *pattern, const char *patname,16.16 - const gchar *initial_dir );16.17 + int initial_dir_key );16.18 /**16.19 * Extract the keyval of the key event if no modifier keys were pressed -16.20 * in other words get the keyval of the key by itself. The other way around16.21 @@ -114,13 +114,6 @@16.22 guint gdk_keycode_to_modifier( GdkDisplay *display, guint keycode );16.24 /**16.25 - * Return an absolute path for the given input path, as a newly allocated16.26 - * string. If the input path is already absolute, the returned string will16.27 - * be identical to the input string.16.28 - */16.29 -gchar *get_absolute_path( const gchar *path );16.30 -16.31 -/**16.32 * Construct a new pixbuf that takes ownership of the frame buffer16.33 */16.34 GdkPixbuf *gdk_pixbuf_new_from_frame_buffer( frame_buffer_t buffer );
17.1 --- a/src/gui.h Wed Jun 24 05:10:25 2009 +000017.2 +++ b/src/gui.h Wed Jun 24 06:06:40 2009 +000017.3 @@ -84,6 +84,29 @@17.4 */17.5 void gui_do_later( do_later_callback_t func );17.7 +17.8 +/******************* GUI helper functions *****************/17.9 +/* The following functions effectively track the current path for each of the17.10 + * 3 main categories (save, vmu, and disc/binary loading) independently. They17.11 + * default to the config values, but can be updated continuously without17.12 + * writing back to the config.17.13 + */17.14 +const gchar *gui_get_configurable_path(int key);17.15 +void gui_set_configurable_path( int key, const gchar *path );17.16 +17.17 +/**17.18 + * Notify the helper functions that the config paths have changed, in which17.19 + * event they will revert to the config-specified versions.17.20 + */17.21 +void gui_config_paths_changed();17.22 +17.23 +/**17.24 + * Return an absolute path for the given input path, as a newly allocated17.25 + * string. If the input path is already absolute, the returned string will17.26 + * be identical to the input string.17.27 + */17.28 +gchar *get_absolute_path( const gchar *path );17.29 +17.30 #ifdef __cplusplus17.31 }17.32 #endif
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +000018.2 +++ b/src/guiutil.c Wed Jun 24 06:06:40 2009 +000018.3 @@ -0,0 +1,66 @@18.4 +/**18.5 + * $Id$18.6 + *18.7 + * GUI helper functions that aren't specific to any particular implementation.18.8 + *18.9 + * Copyright (c) 2009 Nathan Keynes.18.10 + *18.11 + * This program is free software; you can redistribute it and/or modify18.12 + * it under the terms of the GNU General Public License as published by18.13 + * the Free Software Foundation; either version 2 of the License, or18.14 + * (at your option) any later version.18.15 + *18.16 + * This program is distributed in the hope that it will be useful,18.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of18.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the18.19 + * GNU General Public License for more details.18.20 + */18.21 +18.22 +#include <glib/gstrfuncs.h>18.23 +#include <glib/gutils.h>18.24 +18.25 +#include "gui.h"18.26 +#include "config.h"18.27 +18.28 +static gchar *gui_paths[CONFIG_KEY_MAX];18.29 +18.30 +gchar *get_absolute_path( const gchar *in_path )18.31 +{18.32 + char tmp[PATH_MAX];18.33 + if( in_path == NULL ) {18.34 + return NULL;18.35 + }18.36 + if( in_path[0] == '/' || in_path[0] == 0 ) {18.37 + return g_strdup(in_path);18.38 + } else {18.39 + getcwd(tmp, sizeof(tmp));18.40 + return g_strdup_printf("%s%c%s", tmp, G_DIR_SEPARATOR, in_path);18.41 + }18.42 +}18.43 +18.44 +const gchar *gui_get_configurable_path( int key )18.45 +{18.46 + if( gui_paths[key] == NULL ) {18.47 + gui_paths[key] = lxdream_get_global_config_path_value(key);18.48 + /* If no path defined, go with the current working directory */18.49 + if( gui_paths[key] == NULL ) {18.50 + gui_paths[key] = get_absolute_path(".");18.51 + }18.52 + }18.53 + return gui_paths[key];18.54 +}18.55 +18.56 +void gui_set_configurable_path( int key, const gchar *path )18.57 +{18.58 + g_free(gui_paths[key]);18.59 + gui_paths[key] = g_strdup(path);18.60 +}18.61 +18.62 +void gui_config_paths_changed()18.63 +{18.64 + int i;18.65 + for( i=0; i < CONFIG_KEY_MAX; i++ ) {18.66 + g_free(gui_paths[i]);18.67 + gui_paths[i] = NULL;18.68 + }18.69 +}
19.1 --- a/src/loader.c Wed Jun 24 05:10:25 2009 +000019.2 +++ b/src/loader.c Wed Jun 24 06:06:40 2009 +000019.3 @@ -107,17 +107,19 @@19.5 void file_load_postload( const gchar *filename, int pc )19.6 {19.7 - const gchar *bootstrap_file = lxdream_get_config_value(CONFIG_BOOTSTRAP);19.8 + gchar *bootstrap_file = lxdream_get_global_config_path_value(CONFIG_BOOTSTRAP);19.9 if( bootstrap_file != NULL && bootstrap_file[0] != '\0' ) {19.10 /* Load in a bootstrap before the binary, to initialize everything19.11 * correctly19.12 */19.13 if( mem_load_block( bootstrap_file, BOOTSTRAP_LOAD_ADDR, BOOTSTRAP_SIZE ) == 0 ) {19.14 dreamcast_program_loaded( filename, BOOTSTRAP_LOAD_ADDR+0x300 );19.15 + g_free(bootstrap_file);19.16 return;19.17 }19.18 }19.19 dreamcast_program_loaded( filename, pc );19.20 + g_free(bootstrap_file);19.21 }
20.1 --- a/src/main.c Wed Jun 24 05:10:25 2009 +000020.2 +++ b/src/main.c Wed Jun 24 06:06:40 2009 +000020.3 @@ -265,9 +265,10 @@20.4 }20.6 if( gdrom_get_current_disc() == NULL ) {20.7 - const gchar *disc_file = lxdream_get_config_value( CONFIG_GDROM );20.8 + gchar *disc_file = lxdream_get_global_config_path_value( CONFIG_GDROM );20.9 if( disc_file != NULL ) {20.10 gdrom_mount_image( disc_file );20.11 + g_free(disc_file);20.12 }20.13 }
.