iup-stack/iup/srclua5/scripter/iupluascripter_debugger.c

905 lines
31 KiB
C
Raw Normal View History

2023-02-20 16:44:45 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef WIN32
#include <unistd.h> /* for chdir */
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "iup.h"
#include "iup_scintilla.h"
#include "iup_config.h"
#include "iuplua.h"
#include "il.h"
#include "iup_object.h"
#include "iup_attrib.h"
#include "iup_str.h"
#include "iup_strmessage.h"
#include "iup_register.h"
#include "iup_childtree.h"
#include "iup_drvinfo.h"
#define BREAKPOINT_MARGIN "15"
#define FOLDING_MARGIN "20"
/********************************** Utilities *****************************************/
static Ihandle* get_current_multitext(lua_State *L)
{
iuplua_push_name(L, "DebuggerGetCurrentMultitext");
iuplua_call_raw(L, 0, 1);
return iuplua_checkihandle(L, -1);
}
static void debug_set_state(lua_State *L, const char* state)
{
iuplua_push_name(L, "DebuggerSetStateString");
lua_pushstring(L, state);
iuplua_call_raw(L, 1, 0);
}
static int debug_save_check(Ihandle* multitext, const char* filename, lua_State *L)
{
if (!filename || IupGetInt(multitext, "MODIFIED"))
{
if (IupMessageAlarm(IupGetDialog(multitext), "Attention!", "File must be saved for debugging.\n Save it now? (No will cancel debug)", "YESNO") == 1)
{
iuplua_push_name(L, "DebuggerSaveFile");
iuplua_call_raw(L, 0, 0);
}
else
return 0;
}
return 1;
}
static int debug_is_active(lua_State* L)
{
int ret;
iuplua_push_name(L, "DebuggerIsActive");
iuplua_call_raw(L, 0, 1);
ret = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove the result from the stack */
return ret;
}
/********************************** Callbacks *****************************************/
static int but_printlocal_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
if (IupGetInt(NULL, "SHIFTKEY"))
iuplua_push_name(L, "DebuggerPrintAllLocalVariables");
else
iuplua_push_name(L, "DebuggerPrintLocalVariable");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int but_setlocal_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerSetLocalVariable");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int tree_locals_action_cb(Ihandle *ih, int id, int v)
{
lua_State* L;
if (v == 0)
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerLocalVariablesTreeAction");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, id);
iuplua_call_raw(L, 2, 0);
return IUP_DEFAULT;
}
static int tree_locals_branchopen_cb(Ihandle *ih, int id)
{
lua_State* L;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerLocalVariablesBranchOpenAction");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, id);
iuplua_call_raw(L, 2, 0);
return IUP_DEFAULT;
}
static int tree_globals_action_cb(Ihandle *ih, int index, int v)
{
lua_State* L;
if (v == 0)
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerGlobalsTreeAction");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, index);
iuplua_call_raw(L, 2, 0);
return IUP_DEFAULT;
}
static int tree_globals_branchopen_cb(Ihandle *ih, int id)
{
lua_State* L;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerGlobalVariablesBranchOpenAction");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, id);
iuplua_call_raw(L, 2, 0);
return IUP_DEFAULT;
}
static int but_printglobal_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
if (IupGetInt(NULL, "SHIFTKEY"))
iuplua_push_name(L, "DebuggerPrintAllGlobalVariables");
else
iuplua_push_name(L, "DebuggerPrintGlobalVariable");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int but_setglobal_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerSetGlobalVariable");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int but_addglobal_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerAddGlobalVariable");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int but_removeglobal_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
if (IupGetInt(NULL, "SHIFTKEY"))
iuplua_push_name(L, "DebuggerRemoveAllGlobalVariable");
else
iuplua_push_name(L, "DebuggerRemoveGlobalVariable");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int list_stack_action_cb(Ihandle *ih, char *t, int index, int v)
{
lua_State* L;
(void)t;
if (v == 0)
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerStackListAction");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, index);
iuplua_call_raw(L, 2, 0);
return IUP_DEFAULT;
}
static int list_stack_dblclick_cb(Ihandle *ih, int index, char *t)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerStackListActivate");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, index);
iuplua_call_raw(L, 2, 0);
(void)t;
return IUP_DEFAULT;
}
static int but_printlevel_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
if (IupGetInt(NULL, "SHIFTKEY"))
iuplua_push_name(L, "DebuggerPrintAllStackLevel");
else
iuplua_push_name(L, "DebuggerPrintStackLevel");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int list_breaks_dblclick_cb(Ihandle *ih, int index, char *t)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerBreaksListActivate");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, index);
iuplua_call_raw(L, 2, 0);
(void)t;
return IUP_DEFAULT;
}
static int list_breaks_action_cb(Ihandle *ih, char *t, int index, int v)
{
lua_State* L;
(void)t;
if (v == 0)
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerBreaksListAction");
iuplua_pushihandle(L, ih);
lua_pushinteger(L, index);
iuplua_call_raw(L, 2, 0);
return IUP_DEFAULT;
}
static int but_togglebreak_cb(Ihandle *ih)
{
int lin, col;
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
Ihandle* multitext = get_current_multitext(L);
int pos = IupGetInt(multitext, "CARETPOS");
IupTextConvertPosToLinCol(multitext, pos, &lin, &col);
iuplua_push_name(L, "DebuggerToggleMarker"); /* this will trigger the MARKERCHANGED_CB callback too */
lua_pushinteger(L, lin);
iuplua_call_raw(L, 1, 0);
return IUP_DEFAULT;
}
static int but_addbreak_cb(Ihandle* ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerAddBreakpointList");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int item_removeallbreaks_cb(Ihandle *ih)
{
lua_State* L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerRemoveAllBreakpoints");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
static int but_removebreak_cb(Ihandle *ih)
{
if (IupGetInt(NULL, "SHIFTKEY"))
item_removeallbreaks_cb(ih);
else
{
lua_State* L;
Ihandle* listBreak = IupGetDialogChild(ih, "DEBUG_LIST_BREAK");
int index = IupGetInt(listBreak, "VALUE");
if (index == 0)
{
IupMessageError(IupGetDialog(ih), "Must select a breakpoint on the list.");
return IUP_DEFAULT;
}
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
iuplua_push_name(L, "DebuggerRemoveBreakpoint");
iuplua_pushihandle(L, listBreak);
lua_pushinteger(L, index);
iuplua_call_raw(L, 2, 0);
}
return IUP_DEFAULT;
}
static void set_arguments(lua_State* L, const char* data)
{
int i = 1, len = (int)strlen(data), value_len;
char value[100];
/* only positive indices will be set (non-zero) */
lua_createtable(L, 0, 0);
while (len > 0)
{
const char* next_value = iupStrNextValue(data, len, &value_len, ' ');
if (value_len)
{
if (data[0] == '\"' && data[value_len - 1] == '\"')
{
data++;
value_len -= 2;
}
memcpy(value, data, value_len);
value[value_len] = 0;
lua_pushstring(L, value);
lua_rawseti(L, -2, i);
i++;
}
data = next_value;
len -= value_len + 1;
}
lua_setglobal(L, "arg");
}
static int item_debug_action_cb(Ihandle* ih_item)
{
char* filename, *value;
Ihandle* multitext;
lua_State* L;
int end_debug = 1;
Ihandle* ih = IupGetDialog(ih_item);
if (!IupGetInt(IupGetDialogChild(ih, "DEBUG_ITM_DEBUG"), "ACTIVE")) /* can be called by the hot key in the dialog */
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
if (debug_is_active(L)) /* already active, just continue */
{
debug_set_state(L, "DEBUG_ACTIVE");
return IUP_DEFAULT;
}
if (IupGetInt(NULL, "SHIFTKEY"))
end_debug = 0;
multitext = get_current_multitext(L);
filename = IupGetAttribute(multitext, "FILENAME");
if (!debug_save_check(multitext, filename, L))
return IUP_DEFAULT;
iuplua_push_name(L, "DebuggerStartDebug");
if (end_debug)
lua_pushstring(L, filename);
else
lua_pushnil(L);
iuplua_call_raw(L, 1, 0);
value = IupGetAttribute(ih, "CURRENTDIRECTORY");
if (value && value[0] != 0) iupdrvSetCurrentDirectory(value);
value = IupGetAttribute(ih, "ARGUMENTS");
if (value && value[0] != 0) set_arguments(L, value);
iuplua_dofile(L, filename);
if (end_debug)
{
iuplua_push_name(L, "DebuggerEndDebug");
lua_pushboolean(L, 0);
iuplua_call_raw(L, 1, 0);
}
return IUP_DEFAULT;
}
static int item_run_action_cb(Ihandle *ih_item)
{
Ihandle* multitext;
lua_State* L;
char* filename, *value;
Ihandle* ih = IupGetDialog(ih_item);
if (!IupGetInt(IupGetDialogChild(ih, "DEBUG_ITM_RUN"), "ACTIVE")) /* can be called by the hot key in the dialog */
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih, "LUASTATE");
multitext = get_current_multitext(L);
filename = IupGetAttribute(multitext, "FILENAME");
value = IupGetAttribute(ih, "CURRENTDIRECTORY");
if (value) iupdrvSetCurrentDirectory(value);
value = IupGetAttribute(ih, "ARGUMENTS");
if (value && value[0] != 0) set_arguments(L, value);
if (filename && !IupGetInt(multitext, "MODIFIED"))
iuplua_dofile(L, filename);
else
{
char chunk_name[1024];
char* title = IupGetAttribute(ih, "TITLE");
if (!title)
title = "iup.dostring";
sprintf(chunk_name, "=%s", title);
value = IupGetAttribute(multitext, "VALUE");
iuplua_dostring(L, value, chunk_name);
}
return IUP_DEFAULT;
}
static int item_stop_action_cb(Ihandle *ih_item)
{
lua_State* L;
if (!IupGetInt(IupGetDialogChild(ih_item, "DEBUG_ITM_STOP"), "ACTIVE")) /* can be called by the hot key in the dialog */
{
L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
if (!debug_is_active(L))
item_debug_action_cb(ih_item);
return IUP_DEFAULT;
}
L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
debug_set_state(L, "DEBUG_STOPPED");
return IUP_DEFAULT;
}
static int item_pause_action_cb(Ihandle *ih_item)
{
lua_State* L;
if (!IupGetInt(IupGetDialogChild(ih_item, "DEBUG_ITM_PAUSE"), "ACTIVE")) /* can be called by the hot key in the dialog */
return IUP_IGNORE; /* to avoid garbage in Scintilla when pressing the hot key */
L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
debug_set_state(L, "DEBUG_PAUSED");
return IUP_DEFAULT;
}
static int item_stepinto_action_cb(Ihandle *ih_item)
{
lua_State* L;
if (!IupGetInt(IupGetDialogChild(ih_item, "DEBUG_ITM_STEPINTO"), "ACTIVE")) /* can be called by the hot key in the dialog */
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
debug_set_state(L, "DEBUG_STEP_INTO");
return IUP_DEFAULT;
}
static int item_stepover_action_cb(Ihandle *ih_item)
{
lua_State* L;
if (!IupGetInt(IupGetDialogChild(ih_item, "DEBUG_ITM_STEPOVER"), "ACTIVE")) /* can be called by the hot key in the dialog */
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
debug_set_state(L, "DEBUG_STEP_OVER");
return IUP_IGNORE; /* avoid system default behavior for F10 key */
}
static int item_stepout_action_cb(Ihandle *ih_item)
{
lua_State* L;
if (!IupGetInt(IupGetDialogChild(ih_item, "DEBUG_ITM_STEPOUT"), "ACTIVE")) /* can be called by the hot key in the dialog */
return IUP_DEFAULT;
L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
debug_set_state(L, "DEBUG_STEP_OUT");
return IUP_DEFAULT;
}
static int item_currentline_cb(Ihandle *ih_item)
{
lua_State* L = (lua_State*)IupGetAttribute(ih_item, "LUASTATE");
iuplua_push_name(L, "DebuggerShowCurrentLine");
iuplua_call_raw(L, 0, 0);
return IUP_DEFAULT;
}
/********************************** Main *****************************************/
void iupLuaScripterDebuggerAddMenuItems(Ihandle *lua_menu)
{
Ihandle *item_debug, *item_run, *item_stop, *item_pause, *item_stepinto,
*item_stepover, *item_stepout, *item_currentline, *item_togglebreakpoint,
*item_addbreakpoint, *item_removeallbreakpoints;
item_run = IupItem("&Run\tCtrl+F5", NULL);
IupSetAttribute(item_run, "NAME", "DEBUG_ITM_RUN");
IupSetCallback(item_run, "ACTION", (Icallback)item_run_action_cb);
IupSetAttribute(item_run, "IMAGE", "IUP_MediaPlay");
item_debug = IupItem("&Debug/Continue\tF5", NULL);
IupSetAttribute(item_debug, "NAME", "DEBUG_ITM_DEBUG");
IupSetCallback(item_debug, "ACTION", (Icallback)item_debug_action_cb);
IupSetAttribute(item_debug, "IMAGE", "IUP_MediaGoToEnd");
item_stop = IupItem("&Stop\tShift+F5", NULL);
IupSetAttribute(item_stop, "NAME", "DEBUG_ITM_STOP");
IupSetCallback(item_stop, "ACTION", (Icallback)item_stop_action_cb);
IupSetAttribute(item_stop, "ACTIVE", "NO");
IupSetAttribute(item_stop, "IMAGE", "IUP_MediaStop");
item_pause = IupItem("&Pause\tCtrl+Break", NULL);
IupSetAttribute(item_pause, "NAME", "DEBUG_ITM_PAUSE");
IupSetCallback(item_pause, "ACTION", (Icallback)item_pause_action_cb);
IupSetAttribute(item_pause, "ACTIVE", "NO");
IupSetAttribute(item_pause, "IMAGE", "IUP_MediaPause");
item_stepover = IupItem("Step &Over\tF10", NULL);
IupSetAttribute(item_stepover, "NAME", "DEBUG_ITM_STEPOVER");
IupSetCallback(item_stepover, "ACTION", (Icallback)item_stepover_action_cb);
IupSetAttribute(item_stepover, "ACTIVE", "NO");
IupSetAttribute(item_stepover, "IMAGE", "IUP_stepover");
item_stepinto = IupItem("Step &Into\tF11", NULL);
IupSetAttribute(item_stepinto, "NAME", "DEBUG_ITM_STEPINTO");
IupSetCallback(item_stepinto, "ACTION", (Icallback)item_stepinto_action_cb);
IupSetAttribute(item_stepinto, "ACTIVE", "NO");
IupSetAttribute(item_stepinto, "IMAGE", "IUP_stepinto");
item_stepout = IupItem("Step Ou&t\tShift+F11", NULL);
IupSetAttribute(item_stepout, "NAME", "DEBUG_ITM_STEPOUT");
IupSetCallback(item_stepout, "ACTION", (Icallback)item_stepout_action_cb);
IupSetAttribute(item_stepout, "ACTIVE", "NO");
IupSetAttribute(item_stepout, "IMAGE", "IUP_stepout");
item_currentline = IupItem("Show Current Line", NULL);
IupSetAttribute(item_currentline, "NAME", "DEBUG_ITM_CURRENTLINE");
IupSetCallback(item_currentline, "ACTION", (Icallback)item_currentline_cb);
IupSetAttribute(item_currentline, "ACTIVE", "NO");
IupSetAttribute(item_currentline, "IMAGE", "IUP_ArrowRight");
item_togglebreakpoint = IupItem("Toggle Breakpoint\tF9", NULL);
IupSetCallback(item_togglebreakpoint, "ACTION", (Icallback)but_togglebreak_cb);
item_addbreakpoint = IupItem("Add Breakpoint...", NULL);
IupSetCallback(item_addbreakpoint, "ACTION", (Icallback)but_addbreak_cb);
item_removeallbreakpoints = IupItem("Remove All Breakpoints", NULL);
IupSetCallback(item_removeallbreakpoints, "ACTION", (Icallback)item_removeallbreaks_cb);
IupInsert(lua_menu, NULL, IupSeparator());
IupInsert(lua_menu, NULL, item_removeallbreakpoints);
IupInsert(lua_menu, NULL, item_addbreakpoint);
IupInsert(lua_menu, NULL, item_togglebreakpoint);
IupInsert(lua_menu, NULL, IupSeparator());
IupInsert(lua_menu, NULL, item_currentline);
IupInsert(lua_menu, NULL, item_stepout);
IupInsert(lua_menu, NULL, item_stepinto);
IupInsert(lua_menu, NULL, item_stepover);
IupInsert(lua_menu, NULL, item_pause);
IupInsert(lua_menu, NULL, item_stop);
IupInsert(lua_menu, NULL, item_debug);
IupInsert(lua_menu, NULL, IupSeparator());
IupInsert(lua_menu, NULL, item_run);
}
void iupLuaScripterDebuggerAddHotKeys(Ihandle *ih)
{
IupSetCallback(ih, "K_F5", (Icallback)item_debug_action_cb);
IupSetCallback(ih, "K_cF5", (Icallback)item_run_action_cb);
IupSetCallback(ih, "K_sF5", (Icallback)item_stop_action_cb);
IupSetCallback(ih, "K_cPAUSE", (Icallback)item_pause_action_cb);
IupSetCallback(ih, "K_F10", (Icallback)item_stepover_action_cb);
IupSetCallback(ih, "K_F11", (Icallback)item_stepinto_action_cb);
IupSetCallback(ih, "K_sF11", (Icallback)item_stepout_action_cb);
IupSetCallback(ih, "K_F9", (Icallback)but_togglebreak_cb);
}
void iupLuaScripterDebuggerAddToolbarButtons(Ihandle *toolbar)
{
Ihandle *btn_debug, *btn_run, *btn_stop, *btn_pause, *btn_currentline;
Ihandle *btn_stepinto, *btn_stepover, *btn_stepout;
btn_debug = IupButton(NULL, NULL);
IupSetAttribute(btn_debug, "NAME", "DEBUG_BTN_DEBUG");
IupSetAttribute(btn_debug, "IMAGE", "IUP_MediaGoToEnd");
IupSetAttribute(btn_debug, "FLAT", "Yes");
IupSetCallback(btn_debug, "ACTION", (Icallback)item_debug_action_cb);
IupSetAttribute(btn_debug, "TIP", "Debug/Continue (F5)\nPress <Shift> to keep debug active after script finishes.");
IupSetAttribute(btn_debug, "CANFOCUS", "No");
btn_run = IupButton(NULL, NULL);
IupSetAttribute(btn_run, "NAME", "DEBUG_BTN_RUN");
IupSetAttribute(btn_run, "IMAGE", "IUP_MediaPlay");
IupSetAttribute(btn_run, "FLAT", "Yes");
IupSetCallback(btn_run, "ACTION", (Icallback)item_run_action_cb);
IupSetAttribute(btn_run, "TIP", "Run (Ctrl+F5)");
IupSetAttribute(btn_run, "CANFOCUS", "No");
btn_stop = IupButton(NULL, NULL);
IupSetAttribute(btn_stop, "NAME", "DEBUG_BTN_STOP");
IupSetAttribute(btn_stop, "ACTIVE", "NO");
IupSetAttribute(btn_stop, "IMAGE", "IUP_MediaStop");
IupSetAttribute(btn_stop, "FLAT", "Yes");
IupSetCallback(btn_stop, "ACTION", (Icallback)item_stop_action_cb);
IupSetAttribute(btn_stop, "TIP", "Stop (Shift+F5)");
IupSetAttribute(btn_stop, "CANFOCUS", "No");
btn_pause = IupButton(NULL, NULL);
IupSetAttribute(btn_pause, "NAME", "DEBUG_BTN_PAUSE");
IupSetAttribute(btn_pause, "ACTIVE", "NO");
IupSetAttribute(btn_pause, "IMAGE", "IUP_MediaPause");
IupSetAttribute(btn_pause, "FLAT", "Yes");
IupSetCallback(btn_pause, "ACTION", (Icallback)item_pause_action_cb);
IupSetAttribute(btn_pause, "TIP", "Pause (Ctrl+Break)");
IupSetAttribute(btn_pause, "CANFOCUS", "No");
btn_stepover = IupButton(NULL, NULL);
IupSetAttribute(btn_stepover, "NAME", "DEBUG_BTN_STEPOVER");
IupSetAttribute(btn_stepover, "ACTIVE", "NO");
IupSetAttribute(btn_stepover, "IMAGE", "IUP_stepover");
IupSetAttribute(btn_stepover, "FLAT", "Yes");
IupSetCallback(btn_stepover, "ACTION", (Icallback)item_stepover_action_cb);
IupSetAttribute(btn_stepover, "TIP", "Executes one step over the execution (F10).");
IupSetAttribute(btn_stepover, "CANFOCUS", "No");
btn_stepinto = IupButton(NULL, NULL);
IupSetAttribute(btn_stepinto, "NAME", "DEBUG_BTN_STEPINTO");
IupSetAttribute(btn_stepinto, "ACTIVE", "NO");
IupSetAttribute(btn_stepinto, "IMAGE", "IUP_stepinto");
IupSetAttribute(btn_stepinto, "FLAT", "Yes");
IupSetCallback(btn_stepinto, "ACTION", (Icallback)item_stepinto_action_cb);
IupSetAttribute(btn_stepinto, "TIP", "Executes one step into the execution (F11).");
IupSetAttribute(btn_stepinto, "CANFOCUS", "No");
btn_stepout = IupButton(NULL, NULL);
IupSetAttribute(btn_stepout, "NAME", "DEBUG_BTN_STEPOUT");
IupSetAttribute(btn_stepout, "ACTIVE", "NO");
IupSetAttribute(btn_stepout, "IMAGE", "IUP_stepout");
IupSetAttribute(btn_stepout, "FLAT", "Yes");
IupSetCallback(btn_stepout, "ACTION", (Icallback)item_stepout_action_cb);
IupSetAttribute(btn_stepout, "TIP", "Executes one step out of the execution (Shift+F11).");
IupSetAttribute(btn_stepout, "CANFOCUS", "No");
btn_currentline = IupButton(NULL, NULL);
IupSetAttribute(btn_currentline, "NAME", "DEBUG_BTN_CURRENTLINE");
IupSetAttribute(btn_currentline, "ACTIVE", "NO");
IupSetAttribute(btn_currentline, "IMAGE", "IUP_ArrowRight");
IupSetAttribute(btn_currentline, "FLAT", "Yes");
IupSetCallback(btn_currentline, "ACTION", (Icallback)item_currentline_cb);
IupSetAttribute(btn_currentline, "TIP", "Shows the debugger current line.");
IupSetAttribute(btn_currentline, "CANFOCUS", "No");
IupAppend(toolbar, IupSetAttributes(IupLabel(NULL), "SEPARATOR=VERTICAL"));
IupAppend(toolbar, btn_run);
IupAppend(toolbar, IupSetAttributes(IupLabel(NULL), "SEPARATOR=VERTICAL"));
IupAppend(toolbar, btn_debug);
IupAppend(toolbar, btn_stop);
IupAppend(toolbar, btn_pause);
IupAppend(toolbar, btn_stepover);
IupAppend(toolbar, btn_stepinto);
IupAppend(toolbar, btn_stepout);
IupAppend(toolbar, btn_currentline);
}
static Ihandle *buildTabDebug(void)
{
Ihandle *tree_local, *button_printLocal, *button_setLocal, *vbox_local, *frame_local;
Ihandle *list_stack, *button_printLevel, *vbox_stack, *frame_stack, *debug;
tree_local = IupTree();
IupSetAttribute(tree_local, "EXPAND", "YES");
IupSetAttribute(tree_local, "NAME", "DEBUG_TREE_LOCAL");
IupSetAttribute(tree_local, "TIP", "List of local variables at selected stack level (ordered by pos)");
IupSetAttribute(tree_local, "ADDROOT", "NO");
IupSetAttribute(tree_local, "HIDELINES", "YES");
IupSetAttribute(tree_local, "HIDEBUTTONS", "YES");
IupSetAttribute(tree_local, "IMAGELEAF", "IUP_TreeEmpty");
IupSetAttribute(tree_local, "IMAGEBRANCHCOLLAPSED", "IUP_TreePlus");
IupSetAttribute(tree_local, "IMAGEBRANCHEXPANDED", "IUP_TreeMinus");
IupSetAttribute(tree_local, "ADDEXPANDED", "NO");
IupSetCallback(tree_local, "SELECTION_CB", (Icallback)tree_locals_action_cb);
IupSetCallback(tree_local, "BRANCHOPEN_CB", (Icallback)tree_locals_branchopen_cb);
button_printLocal = IupButton(NULL, NULL);
IupSetAttribute(button_printLocal, "ACTIVE", "NO");
IupSetAttribute(button_printLocal, "FLAT", "Yes");
IupSetAttribute(button_printLocal, "IMAGE", "IUP_Print");
IupSetAttribute(button_printLocal, "TIP", "Prints in the console debug information about the selected local variable.\nPress <Shift> to print all variables.");
IupSetAttribute(button_printLocal, "NAME", "DEBUG_PRINT_LOCAL");
IupSetCallback(button_printLocal, "ACTION", (Icallback)but_printlocal_cb);
button_setLocal = IupButton(NULL, NULL);
IupSetAttribute(button_setLocal, "IMAGE", "IUP_FileProperties");
IupSetAttribute(button_setLocal, "FLAT", "Yes");
IupSetAttribute(button_setLocal, "ACTIVE", "NO");
IupSetAttribute(button_setLocal, "TIP", "Changes the value of the selected local variable.\nOnly strings, numbers and booleans can be changed.");
IupSetAttribute(button_setLocal, "NAME", "DEBUG_SET_LOCAL");
IupSetCallback(button_setLocal, "ACTION", (Icallback)but_setlocal_cb);
vbox_local = IupVbox(button_printLocal, button_setLocal, NULL);
IupSetAttribute(vbox_local, "MARGIN", "0x0");
IupSetAttribute(vbox_local, "GAP", "4");
IupSetAttribute(vbox_local, "NORMALIZESIZE", "HORIZONTAL");
frame_local = IupFrame(IupHbox(tree_local, vbox_local, NULL));
IupSetAttribute(frame_local, "MARGIN", "4x4");
IupSetAttribute(frame_local, "GAP", "4");
IupSetAttribute(frame_local, "TITLE", "Locals:");
list_stack = IupList(NULL);
IupSetAttribute(list_stack, "EXPAND", "YES");
IupSetAttribute(list_stack, "NAME", "DEBUG_LIST_STACK");
IupSetAttribute(list_stack, "TIP", "List of call stack (ordered by level)");
IupSetCallback(list_stack, "ACTION", (Icallback)list_stack_action_cb);
IupSetCallback(list_stack, "DBLCLICK_CB", (Icallback)list_stack_dblclick_cb);
IupSetAttribute(list_stack, "VISIBLELINES", "3");
button_printLevel = IupButton(NULL, NULL);
IupSetAttribute(button_printLevel, "FLAT", "Yes");
IupSetAttribute(button_printLevel, "IMAGE", "IUP_Print");
IupSetAttribute(button_printLevel, "TIP", "Prints in the console debug information about the selected call stack level.\nPress <Shift> to print all levels.");
IupSetAttribute(button_printLevel, "ACTIVE", "NO");
IupSetAttribute(button_printLevel, "NAME", "DEBUG_PRINT_LEVEL");
IupSetCallback(button_printLevel, "ACTION", (Icallback)but_printlevel_cb);
vbox_stack = IupVbox(button_printLevel, NULL);
IupSetAttribute(vbox_stack, "MARGIN", "0x0");
IupSetAttribute(vbox_stack, "GAP", "4");
IupSetAttribute(vbox_stack, "NORMALIZESIZE", "HORIZONTAL");
frame_stack = IupFrame(IupHbox(list_stack, vbox_stack, NULL));
IupSetAttribute(frame_stack, "MARGIN", "4x4");
IupSetAttribute(frame_stack, "GAP", "4");
IupSetAttribute(frame_stack, "TITLE", "Call Stack:");
debug = IupHbox(frame_local, frame_stack, NULL);
IupSetAttribute(debug, "MARGIN", "0x0");
IupSetAttribute(debug, "GAP", "4");
IupSetAttribute(debug, "TABTITLE", "Debug");
return debug;
}
static Ihandle *buildTabWatch(void)
{
Ihandle *tree_global, *button_printGlobal, *button_addGlobal,
*button_removeGlobal, *button_setGlobal, *vbox_global, *frame_global, *watch;
tree_global = IupTree();
IupSetAttribute(tree_global, "EXPAND", "YES");
IupSetAttribute(tree_global, "NAME", "DEBUG_TREE_GLOBAL");
IupSetAttribute(tree_global, "TIP", "List of globals variables or expressions");
IupSetAttribute(tree_global, "ADDROOT", "NO");
IupSetAttribute(tree_global, "HIDELINES", "YES");
IupSetAttribute(tree_global, "HIDEBUTTONS", "YES");
IupSetAttribute(tree_global, "IMAGELEAF", "IUP_TreeEmpty");
IupSetAttribute(tree_global, "IMAGEBRANCHCOLLAPSED", "IUP_TreeEmpty");
IupSetAttribute(tree_global, "ADDEXPANDED", "NO");
IupSetAttribute(tree_global, "IMAGEBRANCHEXPANDED", "IUP_TreeEmpty");
IupSetCallback(tree_global, "ACTION", (Icallback)tree_globals_action_cb);
IupSetCallback(tree_global, "BRANCHOPEN_CB", (Icallback)tree_globals_branchopen_cb);
button_printGlobal = IupButton(NULL, NULL);
IupSetAttribute(button_printGlobal, "FLAT", "Yes");
IupSetAttribute(button_printGlobal, "IMAGE", "IUP_Print");
IupSetAttribute(button_printGlobal, "ACTIVE", "NO");
IupSetAttribute(button_printGlobal, "TIP", "Prints in the console debug information about the selected global variable or expression.\nPress <Shift> to print all items.");
IupSetAttribute(button_printGlobal, "NAME", "DEBUG_PRINT_GLOBAL");
IupSetCallback(button_printGlobal, "ACTION", (Icallback)but_printglobal_cb);
button_setGlobal = IupButton(NULL, NULL);
IupSetAttribute(button_setGlobal, "IMAGE", "IUP_FileProperties");
IupSetAttribute(button_setGlobal, "FLAT", "Yes");
IupSetAttribute(button_setGlobal, "ACTIVE", "NO");
IupSetAttribute(button_setGlobal, "TIP", "Changes the value of the selected global variable.\nOnly strings, numbers and booleans can be changed.");
IupSetAttribute(button_setGlobal, "NAME", "DEBUG_SET_GLOBAL");
IupSetCallback(button_setGlobal, "ACTION", (Icallback)but_setglobal_cb);
button_addGlobal = IupButton(NULL, NULL);
IupSetAttribute(button_addGlobal, "FLAT", "Yes");
IupSetAttribute(button_addGlobal, "IMAGE", "IUP_plus");
IupSetAttribute(button_addGlobal, "TIP", "Add a global variable given its name.");
IupSetCallback(button_addGlobal, "ACTION", (Icallback)but_addglobal_cb);
button_removeGlobal = IupButton(NULL, NULL);
IupSetAttribute(button_removeGlobal, "FLAT", "Yes");
IupSetAttribute(button_removeGlobal, "IMAGE", "IUP_EditErase");
IupSetAttribute(button_removeGlobal, "NAME", "DEBUG_REMOVE_GLOBAL");
IupSetAttribute(button_removeGlobal, "TIP", "Removes the selected global variable or expression.\nPress <Shift> to remove all items.");
IupSetCallback(button_removeGlobal, "ACTION", (Icallback)but_removeglobal_cb);
vbox_global = IupVbox(button_printGlobal, button_setGlobal, button_addGlobal, button_removeGlobal, NULL);
IupSetAttribute(vbox_global, "MARGIN", "0x0");
IupSetAttribute(vbox_global, "GAP", "4");
IupSetAttribute(vbox_global, "NORMALIZESIZE", "HORIZONTAL");
frame_global = IupFrame(IupHbox(tree_global, vbox_global, NULL));
IupSetAttribute(frame_global, "MARGIN", "4x4");
IupSetAttribute(frame_global, "GAP", "4");
IupSetAttribute(frame_global, "TITLE", "Globals:");
watch = IupHbox(frame_global, NULL);
IupSetAttribute(watch, "MARGIN", "0x0");
IupSetAttribute(watch, "GAP", "4");
IupSetAttribute(watch, "TABTITLE", "Watch");
return watch;
}
static Ihandle *buildTabBreaks(void)
{
Ihandle *button_addbreak, *button_removebreak, *hbox, *list, *vbox, *frame, *button_togglebreak;
button_togglebreak = IupButton(NULL, NULL);
IupSetAttribute(button_togglebreak, "IMAGE", "IUP_MediaRecord");
IupSetAttribute(button_togglebreak, "FLAT", "Yes");
IupSetAttribute(button_togglebreak, "TIP", "Toggle a breakpoint at current line. (F9)");
IupSetCallback(button_togglebreak, "ACTION", (Icallback)but_togglebreak_cb);
button_addbreak = IupButton(NULL, NULL);
IupSetAttribute(button_addbreak, "TIP", "Adds a breakpoint at given function and line.");
IupSetAttribute(button_addbreak, "FLAT", "Yes");
IupSetAttribute(button_addbreak, "IMAGE", "IUP_plus");
IupSetCallback(button_addbreak, "ACTION", (Icallback)but_addbreak_cb);
button_removebreak = IupButton(NULL, NULL);
IupSetAttribute(button_removebreak, "FLAT", "Yes");
IupSetAttribute(button_removebreak, "IMAGE", "IUP_EditErase");
IupSetAttribute(button_removebreak, "TIP", "Removes the selected breakpoint.\nPress <Shift> to remove all breakpoints.");
IupSetCallback(button_removebreak, "ACTION", (Icallback)but_removebreak_cb);
IupSetAttribute(button_removebreak, "NAME", "DEBUG_REMOVE_BREAK");
IupSetAttribute(button_removebreak, "ACTIVE", "NO");
vbox = IupVbox(button_togglebreak, button_addbreak, button_removebreak, NULL);
IupSetAttribute(vbox, "MARGIN", "0x0");
IupSetAttribute(vbox, "GAP", "4");
IupSetAttribute(vbox, "NORMALIZESIZE", "HORIZONTAL");
list = IupList(NULL);
IupSetAttribute(list, "EXPAND", "YES");
IupSetAttribute(list, "NAME", "DEBUG_LIST_BREAK");
IupSetCallback(list, "ACTION", (Icallback)list_breaks_action_cb);
IupSetCallback(list, "DBLCLICK_CB", (Icallback)list_breaks_dblclick_cb);
IupSetAttribute(list, "VISIBLELINES", "3");
frame = IupFrame(IupHbox(list, vbox, NULL));
IupSetAttribute(frame, "MARGIN", "4x4");
IupSetAttribute(frame, "GAP", "4");
IupSetAttribute(frame, "TITLE", "Breakpoints:");
hbox = IupVbox(frame, NULL);
IupSetAttribute(hbox, "MARGIN", "0x0");
IupSetAttribute(hbox, "GAP", "4");
IupSetAttribute(hbox, "TABTITLE", "Breaks");
return hbox;
}
void iupLuaScripterDebuggerCreateTabs(Ihandle* panelTabs)
{
Ihandle *tabDebug, *tabBreaks, *tabWatch;
tabBreaks = buildTabBreaks();
tabDebug = buildTabDebug();
tabWatch = buildTabWatch();
IupAppend(panelTabs, tabBreaks);
IupAppend(panelTabs, tabDebug);
IupAppend(panelTabs, tabWatch);
}