From c1d084c70d3fa63eb787b57c5c6c3f511c95a357 Mon Sep 17 00:00:00 2001
From: Ian C <ianc@noddybox.co.uk>
Date: Fri, 16 Jan 2004 02:28:10 +0000
Subject: Added options to toggle individual breakpoints

---
 src/gfx.h     |   6 --
 src/gui.c     | 220 ++++++++++++++++++++++++++++++++++++++--------------------
 src/gui.h     |   8 +++
 src/main.c    |  12 ++--
 src/memmenu.c | 158 ++++++++++++++++++++++++++---------------
 src/memmenu.h |   4 +-
 6 files changed, 263 insertions(+), 145 deletions(-)

(limited to 'src')

diff --git a/src/gfx.h b/src/gfx.h
index 9b35868..6d051d8 100644
--- a/src/gfx.h
+++ b/src/gfx.h
@@ -55,12 +55,6 @@
 void		GFXInit(void);
 
 
-/* Size of the screen
-*/
-int		GFXHeight(void);
-int		GFXWidth(void);
-
-
 /* Get the SDL_Surface for the screen
 */
 SDL_Surface	*GFXGetSurface(void);
diff --git a/src/gui.c b/src/gui.c
index c922aba..05ebc49 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -98,6 +98,133 @@ static void Box(const char *title, int x, int y, int width, int height)
 }
 
 
+static int DoList(const char *title, int no, char * const list[], int *option)
+{
+    static const int max=GFX_HEIGHT/8-8;
+    SDL_Event *e;
+    int top;
+    int cur;
+    int done;
+    int f;
+
+    if (no==0)
+    	return -1;
+
+    top=0;
+    cur=0;
+
+    done=FALSE;
+
+    while(!done)
+    {
+	Box(title,7,7,GFX_WIDTH-14,GFX_HEIGHT-14);
+
+	if (option)
+	{
+	    Centre("Cursors to move, RETURN to accept",
+	    		GFX_HEIGHT-44,WHITE);
+	    Centre("SPACE toggles, I inverts all",
+	    		GFX_HEIGHT-36,WHITE);
+	    Centre("S select all, C clear all",
+	    		GFX_HEIGHT-28,WHITE);
+	}
+	else
+	    Centre("Cursors and RETURN to select",GFX_HEIGHT-28,WHITE);
+
+	Centre("ESCAPE to cancel",GFX_HEIGHT-20,WHITE);
+
+	for(f=0;f<max;f++)
+	{
+	    if (f+top<no)
+	    {
+		Uint32 pen,paper;
+
+		if (f+top==cur)
+		{
+		    pen=WHITE;
+		    paper=RED;
+		}
+		else
+		{
+		    pen=GREY;
+		    paper=BLACK;
+		}
+
+		if (option)
+		    GFXPrintPaper(16,20+f*8,pen,paper,"%c %-34.34s",
+				  option[f+top] ? FONT_TICK:' ',list[f+top]);
+		else
+		    GFXPrintPaper(16,20+f*8,pen,paper,"%-36.36s",list[f+top]);
+	    }
+	}
+
+	GFXEndFrame(FALSE);
+
+	e=GFXWaitKey();
+
+	switch(e->key.keysym.sym)
+	{
+	    case SDLK_RETURN:
+	    	done=TRUE;
+		break;
+
+	    case SDLK_SPACE:
+	    	if (option)
+		    option[cur]=!option[cur];
+		break;
+
+	    case SDLK_i:
+	    	if (option)
+		    for(f=0;f<no;f++)
+			option[f]=!option[f];
+		break;
+
+	    case SDLK_s:
+	    	if (option)
+		    for(f=0;f<no;f++)
+			option[f]=TRUE;
+		break;
+
+	    case SDLK_c:
+	    	if (option)
+		    for(f=0;f<no;f++)
+			option[f]=FALSE;
+		break;
+
+	    case SDLK_ESCAPE:
+		cur=-1;
+	    	done=TRUE;
+	    	break;
+
+	    case SDLK_UP:
+		if (cur>0)
+		{
+		    cur--;
+
+		    if (cur<top)
+		    	top=cur;
+		}
+	    	break;
+
+	    case SDLK_DOWN:
+		if (cur<no-1)
+		{
+		    cur++;
+
+		    if (cur>top+max-2)
+		    	top=cur-max+2;
+		}
+		break;
+
+	    default:
+		break;
+	}
+    }
+
+    return cur;
+}
+
+
 /* ---------------------------------------- EXPORTED INTERFACES
 */
 int GUIMessage(GUIBoxType type, const char *title, const char *format,...)
@@ -265,90 +392,33 @@ const char *GUIInputString(const char *prompt, const char *orig)
 
 int GUIListSelect(const char *title, int no, char * const list[])
 {
-    static const int max=GFX_HEIGHT/8-8;
-    SDL_Event *e;
-    int top;
-    int cur;
-    int done;
-    int f;
-
-    if (no==0)
-    	return -1;
-
-    top=0;
-    cur=0;
-
-    done=FALSE;
-
-    while(!done)
-    {
-	Box(title,7,7,GFX_WIDTH-14,GFX_HEIGHT-14);
-
-	Centre("Cursors and RETURN to select",GFX_HEIGHT-40,WHITE);
-	Centre("ESCAPE to cancel",GFX_HEIGHT-32,WHITE);
-
-	for(f=0;f<max;f++)
-	{
-	    if (f+top<no)
-	    {
-		Uint32 pen,paper;
-
-		if (f+top==cur)
-		{
-		    pen=WHITE;
-		    paper=RED;
-		}
-		else
-		{
-		    pen=GREY;
-		    paper=BLACK;
-		}
+    return DoList(title,no,list,NULL);
+}
 
-		GFXPrintPaper(16,20+f*8,pen,paper,"%-36.36s",list[f+top]);
-	    }
-	}
 
-	GFXEndFrame(FALSE);
-
-	e=GFXWaitKey();
+int GUIListOption(const char *title, int no, char * const list[], int option[])
+{
+    int *o;
+    int sel;
+    int f;
 
-	switch(e->key.keysym.sym)
-	{
-	    case SDLK_RETURN:
-	    	done=TRUE;
-		break;
+    if (no==0)
+    	return FALSE;
 
-	    case SDLK_ESCAPE:
-		cur=-1;
-	    	done=TRUE;
-	    	break;
+    o=Malloc(no * sizeof *o);
 
-	    case SDLK_UP:
-		if (cur>0)
-		{
-		    cur--;
+    for(f=0;f<no;f++)
+    	o[f]=option[f];
 
-		    if (cur<top)
-		    	top=cur;
-		}
-	    	break;
+    sel=DoList(title,no,list,o);
 
-	    case SDLK_DOWN:
-		if (cur<no-1)
-		{
-		    cur++;
+    if (sel!=-1)
+    	for(f=0;f<no;f++)
+	    option[f]=o[f];
 
-		    if (cur>top+max-2)
-		    	top=cur-max+2;
-		}
-		break;
-
-	    default:
-		break;
-	}
-    }
+    free(o);
 
-    return cur;
+    return sel!=-1;
 }
 
 
diff --git a/src/gui.h b/src/gui.h
index e1ad43a..efbb40c 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -58,6 +58,14 @@ const char	*GUIInputString(const char *prompt, const char *orig);
 int		GUIListSelect(const char *title, int no, char * const list[]);
 
 
+/* Allows options to be toggled in a list.  Returns FALSE for cancelled (in
+   which case option will be as it was.  TRUE if accepted, and option will be
+   updated.
+*/
+int		GUIListOption(const char *title,
+			      int no, char * const list[], int option[]);
+
+
 /* Select a file from the given directory.
 
    If load is TRUE then a new name cannot be entered.
diff --git a/src/main.c b/src/main.c
index a79464c..587e657 100644
--- a/src/main.c
+++ b/src/main.c
@@ -36,6 +36,7 @@ static const char id[]="$Id$";
 #include "memmenu.h"
 #include "config.h"
 #include "exit.h"
+#include "util.h"
 
 
 /* ---------------------------------------- MACROS
@@ -102,7 +103,7 @@ int main(int argc, char *argv[])
        TODO: Proper switch handling
     */
     if (argc>1 && strcmp(argv[1],"-m")==0)
-    	MemoryMenu(z80);
+    	quit=MemoryMenu(z80);
 
     while(!quit)
     {
@@ -129,16 +130,16 @@ int main(int argc, char *argv[])
 	if ((brk=Break()))
 	{
 	    GUIMessage(eMessageBox,"BREAKPOINT","%s",brk);
-	    MemoryMenu(z80);
+	    quit=MemoryMenu(z80);
 	}
 
-	while((e=GFXGetKey()))
+	while(!quit && (e=GFXGetKey()))
 	{
 	    switch (e->key.keysym.sym)
 	    {
 	    	case SDLK_ESCAPE:
 		    if (e->key.state==SDL_PRESSED)
-			quit=TRUE;
+			quit=GUIMessage(eYesNoBox,"QUIT","Sure?");
 		    break;
 
 		case SDLK_F1:
@@ -214,7 +215,8 @@ int main(int argc, char *argv[])
 
 		case SDLK_F11:
 		    if (e->key.state==SDL_PRESSED)
-		    	MemoryMenu(z80);
+		    	quit=MemoryMenu(z80);
+		    Debug("quit=%d\n");
 		    break;
 
 		case SDLK_F12:
diff --git a/src/memmenu.c b/src/memmenu.c
index 41a18b3..0d5053f 100644
--- a/src/memmenu.c
+++ b/src/memmenu.c
@@ -63,6 +63,7 @@ static const char ident_h[]=ESPEC_MEMMENU_H;
 typedef struct
 {
     int		no;
+    int		*active;
     char	**expr;
 } Breakpoint;
 
@@ -86,7 +87,7 @@ typedef struct
 /* ---------------------------------------- STATIC DATA
 */
 static FILE		*trace=NULL;
-static Breakpoint	bpoint={0,NULL};
+static Breakpoint	bpoint={0,NULL,NULL};
 static const char	*brk=NULL;
 static int		lodged=FALSE;
 
@@ -98,9 +99,21 @@ static int		Instruction(Z80 *z80, Z80Val data);
 
 /* ---------------------------------------- PRIVATE FUNCTIONS
 */
+static int BreaksActive(void)
+{
+    int f;
+    int ret=FALSE;
+
+    for(f=0;f<bpoint.no;f++)
+    	ret|=bpoint.active[f];
+
+    return ret;
+}
+
+
 static void SetCallback(Z80 *z80)
 {
-    if ((trace || bpoint.no) && !lodged)
+    if ((trace || BreaksActive()) && !lodged)
     {
 	Z80LodgeCallback(z80,eZ80_Instruction,Instruction);
 	lodged=TRUE;
@@ -110,7 +123,7 @@ static void SetCallback(Z80 *z80)
 
 static void ClearCallback(Z80 *z80)
 {
-    if (!trace && !bpoint.no && lodged)
+    if (!trace && !BreaksActive() && lodged)
     {
 	Z80RemoveCallback(z80,eZ80_Instruction,Instruction);
 	lodged=FALSE;
@@ -120,7 +133,7 @@ static void ClearCallback(Z80 *z80)
 
 static void Centre(const char *p, int y, Uint32 col)
 {
-    GFXPrint((320-strlen(p)*8)/2,y,col,"%s",p);
+    GFXPrint((GFX_WIDTH-strlen(p)*8)/2,y,col,"%s",p);
 }
 
 
@@ -128,16 +141,17 @@ static void DisplayMenu(void)
 {
     static const char *menu[]=
     {
-    	"1   - Disassemble/Hex dump ",
-    	"2   - Disassemble to file  ",
-	"3   - Start/Stop trace log ",
-	"4   - Playback trace log   ",
-	"5   - Add a new breakpoint ",
-	"6    -Clear a breakpoint   ",
-	"7   - Display breakpoints  ",
-	"8   - Clear all breakpoints",
-	"R   - Reset                ",
-    	"ESC - Return               ",
+    	"1   - Disassemble/Hex dump  ",
+    	"2   - Disassemble to file   ",
+	"3   - Start/Stop trace log  ",
+	"4   - Playback trace log    ",
+	"5   - Add a new breakpoint  ",
+	"6   - Set active breakpoints",
+	"7   - Remove a breakpoint   ",
+	"8   - Clear all breakpoints ",
+	"R   - Reset                 ",
+	"X   - Exit (without confirm)",
+    	"ESC - Return                ",
 	NULL
     };
 
@@ -458,15 +472,16 @@ static int Instruction(Z80 *z80, Z80Val data)
     }
 
     for(f=0;f<bpoint.no;f++)
-    {
-    	long l;
-
-	if (Z80Expression(z80,bpoint.expr[f],&l,NULL))
+	if (bpoint.active[f])
 	{
-	    if (l)
-		brk=bpoint.expr[f];
+	    long l;
+
+	    if (Z80Expression(z80,bpoint.expr[f],&l,NULL))
+	    {
+		if (l)
+		    brk=bpoint.expr[f];
+	    }
 	}
-    }
 
     return TRUE;
 }
@@ -720,63 +735,84 @@ static void DoAddBreakpoint(Z80 *z80)
     }
     else
     {
+	int f;
+
+	for(f=0;f<50;f++)
+	{
 	bpoint.no++;
 	bpoint.expr=Realloc(bpoint.expr,bpoint.no * sizeof(*bpoint.expr));
+	bpoint.active=Realloc(bpoint.active,bpoint.no * sizeof(*bpoint.active));
 
 	bpoint.expr[bpoint.no-1]=StrCopy(expr);
+	bpoint.active[bpoint.no-1]=TRUE;
+	}
 
 	SetCallback(z80);
     }
 }
 
 
-static void DoRemoveBreakpoint(Z80 *z80, int delete)
+static void DoActiveBreakpoint(Z80 *z80)
 {
     if (bpoint.no==0)
     {
-    	if (delete)
-	    GUIMessage(eMessageBox,"NOTICE","No breakpoints to delete");
-	else
-	    GUIMessage(eMessageBox,"NOTICE","No breakpoints to display");
-
+	GUIMessage(eMessageBox,"NOTICE","No breakpoints to set");
 	return;
     }
 
     GFXClear(BLACK);
 
-    if (delete)
-    {
-	int sel;
+    GUIListOption("SELECT ACTIVE BREAKPOINTS",
+		  bpoint.no,bpoint.expr,bpoint.active);
+}
 
-    	sel=GUIListSelect("BREAKPOINT TO DELETE",bpoint.no,bpoint.expr);
 
-	while (sel!=-1)
-	{
-	    int f;
+static void DoRemoveBreakpoint(Z80 *z80)
+{
+    int sel;
 
-	    free(bpoint.expr[sel]);
+    if (bpoint.no==0)
+    {
+	GUIMessage(eMessageBox,"NOTICE","No breakpoints to delete");
+	return;
+    }
 
-	    for(f=sel;f<bpoint.no-1;f++)
-	    	bpoint.expr[f]=bpoint.expr[f+1];
+    GFXClear(BLACK);
 
-	    bpoint.no--;
+    sel=GUIListSelect("BREAKPOINT TO DELETE",bpoint.no,bpoint.expr);
 
-	    if (bpoint.no==0)
-	    {
-	    	free(bpoint.expr);
-		bpoint.expr=NULL;
-	    }
-	    else
-		bpoint.expr=Realloc(bpoint.expr,
-				    bpoint.no * sizeof(*bpoint.expr));
+    while (sel!=-1)
+    {
+	int f;
+
+	free(bpoint.expr[sel]);
+
+	for(f=sel;f<bpoint.no-1;f++)
+	{
+	    bpoint.expr[f]=bpoint.expr[f+1];
+	    bpoint.active[f]=bpoint.active[f+1];
+	}
 
-	    ClearCallback(z80);
+	bpoint.no--;
 
-	    sel=GUIListSelect("BREAKPOINT TO DELETE",bpoint.no,bpoint.expr);
+	if (bpoint.no==0)
+	{
+	    free(bpoint.expr);
+	    bpoint.expr=NULL;
+	    bpoint.active=NULL;
 	}
+	else
+	{
+	    bpoint.expr=Realloc(bpoint.expr,
+				bpoint.no * sizeof(*bpoint.expr));
+	    bpoint.active=Realloc(bpoint.active,
+				  bpoint.no * sizeof(*bpoint.active));
+	}
+
+	ClearCallback(z80);
+
+	sel=GUIListSelect("BREAKPOINT TO DELETE",bpoint.no,bpoint.expr);
     }
-    else
-    	GUIListSelect("CURRENT BREAKPOINTS",bpoint.no,bpoint.expr);
 }
 
 
@@ -800,9 +836,10 @@ static void DoClearBreakpoint(Z80 *z80)
 
 /* ---------------------------------------- EXPORTED INTERFACES
 */
-void MemoryMenu(Z80 *z80)
+int MemoryMenu(Z80 *z80)
 {
     SDL_Event *e;
+    int done=FALSE;
     int quit=FALSE;
     Z80State s;
 
@@ -810,10 +847,10 @@ void MemoryMenu(Z80 *z80)
 
     GFXKeyRepeat(TRUE);
 
-    while(!quit)
+    while(!done)
     {
 	DisplayMenu();
-	DisplayState(z80);
+	DisplayZ80State(&s,GFX_HEIGHT-70,RED);
 	GFXEndFrame(FALSE);
 
 	e=GFXWaitKey();
@@ -845,11 +882,11 @@ void MemoryMenu(Z80 *z80)
 	    	break;
 
 	    case SDLK_6:
-		DoRemoveBreakpoint(z80,TRUE);
+		DoActiveBreakpoint(z80);
 	    	break;
 
 	    case SDLK_7:
-		DoRemoveBreakpoint(z80,FALSE);
+		DoRemoveBreakpoint(z80);
 	    	break;
 
 	    case SDLK_8:
@@ -864,16 +901,23 @@ void MemoryMenu(Z80 *z80)
 		}
 		break;
 
-	    case SDLK_ESCAPE:
+	    case SDLK_x:
+	    	done=TRUE;
 	    	quit=TRUE;
 		break;
 
+	    case SDLK_ESCAPE:
+	    	done=TRUE;
+		break;
+
 	    default:
 	    	break;
 	}
     }
 
     GFXKeyRepeat(FALSE);
+
+    return quit;
 }
 
 
@@ -882,7 +926,7 @@ void DisplayState(Z80 *z80)
     Z80State s;
 
     Z80GetState(z80,&s);
-    DisplayZ80State(&s,136,RED);
+    DisplayZ80State(&s,GFX_HEIGHT/2,RED);
 }
 
 
diff --git a/src/memmenu.h b/src/memmenu.h
index f04b6b8..4b818fd 100644
--- a/src/memmenu.h
+++ b/src/memmenu.h
@@ -30,9 +30,9 @@
 #include "z80.h"
 
 
-/* Memory menu
+/* Memory menu.  Returns TRUE if exit (from program) selected.
 */
-void		MemoryMenu(Z80 *z80);
+int		MemoryMenu(Z80 *z80);
 
 
 /* Display the state of the SPEC at the bottom of the screen
-- 
cgit v1.2.3