version 1.3, 2025/03/09 19:14:24
|
version 1.5, 2025/03/31 16:33:56
|
Line 24
|
Line 24
|
* along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
* along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
* |
* |
* $Log$ |
* $Log$ |
|
* Revision 1.5 2025/03/31 16:33:56 snw |
|
* Work on fmadm edit global |
|
* |
|
* Revision 1.4 2025/03/30 01:36:58 snw |
|
* Make it easier to bring back fma_gedit, fix double-free in global handler, limit $CHAR to 7-bit ASCII |
|
* |
* Revision 1.3 2025/03/09 19:14:24 snw |
* Revision 1.3 2025/03/09 19:14:24 snw |
* First phase of REUSE compliance and header reformat |
* First phase of REUSE compliance and header reformat |
* |
* |
Line 46
|
Line 52
|
#include "fmadm.h" |
#include "fmadm.h" |
#include "fma_globals.h" |
#include "fma_globals.h" |
|
|
#if defined HAVE_NCURSESW_CURSES_H |
#ifdef HAVE_LIBREADLINE |
# include <ncursesw/curses.h> |
# if defined(HAVE_READLINE_READLINE_H) |
#elif defined HAVE_NCURSESW_H |
# include <readline/readline.h> |
# include <ncursesw.h> |
# elif defined(HAVE_READLINE_H) |
#elif defined HAVE_NCURSES_CURSES_H |
# include <readline.h> |
# include <ncurses/curses.h> |
# else /* !defined(HAVE_READLINE_H) */ |
#elif defined HAVE_NCURSES_H |
extern char *readline (); |
# include <ncurses.h> |
# endif /* !defined(HAVE_READLINE_H) */ |
#elif defined HAVE_CURSES_H |
/*char *cmdline = NULL;*/ |
# include <curses.h> |
#else /* !defined(HAVE_READLINE_READLINE_H) */ |
#else |
/* no readline */ |
# error "SysV or X/Open-compatible Curses header file required" |
#endif /* HAVE_LIBREADLINE */ |
#endif |
|
|
#ifdef HAVE_READLINE_HISTORY |
|
# if defined(HAVE_READLINE_HISTORY_H) |
|
# include <readline/history.h> |
|
# elif defined(HAVE_HISTORY_H) |
|
# include <history.h> |
|
# else /* !defined(HAVE_HISTORY_H) */ |
|
extern void add_history (); |
|
extern int write_history (); |
|
extern int read_history (); |
|
# endif /* defined(HAVE_READLINE_HISTORY_H) */ |
|
/* no history */ |
|
#endif /* HAVE_READLINE_HISTORY */ |
|
|
|
|
|
|
#define GE_MXGBL 100 |
#define GE_MXGBL 100 |
|
|
Line 121 int ge_nextbuf;
|
Line 141 int ge_nextbuf;
|
int ge_rows; |
int ge_rows; |
int ge_columns; |
int ge_columns; |
|
|
WINDOW *wge_key; |
|
WINDOW *wge_key_border; |
|
WINDOW *wge_node; |
|
WINDOW *wge_node_border; |
|
WINDOW *wge_msg_border; |
|
WINDOW *wge_msg; |
|
WINDOW *wge_block_border; |
|
WINDOW *wge_block; |
|
WINDOW *wge_global_border; |
|
WINDOW *wge_global; |
|
WINDOW *wge_command; |
|
|
|
WINDOW *wge_cur; |
|
|
|
void ge_set_wintitle(WINDOW *border_window, char *title); |
|
void ge_wininit(void); |
|
void ge_update_gbl(void); |
void ge_update_gbl(void); |
void ge_select_buffer(int buf); |
void ge_select_buffer(int buf); |
short ge_select_block(int buf, long blocknum); |
short ge_select_block(int buf, long blocknum); |
Line 145 int ge_open_global(char *gblname);
|
Line 149 int ge_open_global(char *gblname);
|
void ge_init_buffers(void); |
void ge_init_buffers(void); |
void ge_eventloop(void); |
void ge_eventloop(void); |
void ge_decode_key(const char *key, char *buf); |
void ge_decode_key(const char *key, char *buf); |
void ge_win_next(void); |
void ge_describe_block(void); |
void ge_win_previous(void); |
|
|
|
#define SPC ' ' |
#define SPC ' ' |
|
|
|
|
|
void ge_describe_gbl(void) |
|
{ |
|
printf ("global %s [#%d]\n", ge_buffers[ge_curbuf].name, ge_curbuf); |
|
printf ("namespace %s\n", ge_buffers[ge_curbuf].namespace); |
|
printf ("block size %d bytes\n", BLOCKLEN); |
|
printf ("block count %d\n", ge_buffers[ge_curbuf].blockct); |
|
printf ("file size %d bytes\n", ge_buffers[ge_curbuf].gblsize); |
|
} |
|
|
|
void ge_update_gbl(void) |
|
{ |
|
printf ("fmadm: selected global %s into buffer %d\n", ge_buffers[ge_curbuf].name, ge_curbuf); |
|
} |
|
|
|
|
int fma_globals_edit(int optc, char **opts) |
int fma_globals_edit(int optc, char **opts) |
{ |
{ |
|
#define MODE_GBL 0 |
|
#define MODE_BLK 1 |
|
#if defined(HAVE_LIBREADLINE) && !defined(_AIX) |
int editbuf; |
int editbuf; |
|
char fmge_prompt[256]; |
|
char *cmdt = (char *) malloc (65535 * sizeof (char)); |
|
char *fmarl_buf; |
|
char **args; |
|
int mode = MODE_GBL; |
|
char *result = (char *) malloc (65535 * sizeof (char));; |
|
int argc; |
|
int tmpres; |
|
register int i; |
|
|
|
/* first dimension */ |
|
if ((args = (char **) malloc (FMA_MAXARGS * sizeof (char *))) == NULL) { |
|
fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n"); |
|
return 1; |
|
} |
|
|
|
/* second dimension */ |
|
for (i = 0; i < FMA_MAXARGS; i++) { |
|
if ((args[i] = (char *) malloc (STRLEN * sizeof (char *))) == NULL) { |
|
fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n"); |
|
return 1; |
|
} |
|
} |
|
|
|
|
ge_curbuf = 0; |
ge_curbuf = 0; |
ge_nextbuf = 0; |
ge_nextbuf = 0; |
|
ge_init_buffers (); |
ge_init_buffers (); |
|
initscr (); |
|
ge_wininit (); |
|
|
|
wge_cur = wge_command; |
|
|
|
wprintw (wge_msg, "FreeM Global Editor\n"); |
|
wprintw (wge_msg, " Copyright (C) 2023 Coherent Logic Development LLC\n\n"); |
|
|
|
wattron (wge_msg, A_BOLD); |
|
wprintw (wge_msg, "Left and right arrow keys navigate blocks; 'q' to quit.\n\n"); |
|
wattroff (wge_msg, A_BOLD); |
|
wrefresh (wge_msg); |
|
|
|
if (optc == 2) { |
if (optc == 2) { |
|
|
if ((editbuf = ge_open_global (opts[fma_base_opt])) == -1) { |
if ((editbuf = ge_open_global (opts[fma_base_opt])) == -1) { |
wprintw (wge_msg, "fmadm: cannot open global %s\n", opts[fma_base_opt]); |
fprintf (stderr, "fmadm: cannot open global %s\n", opts[fma_base_opt]); |
} |
} |
else { |
else { |
ge_select_buffer (editbuf); |
ge_select_buffer (editbuf); |
} |
} |
|
|
} |
} |
|
|
ge_eventloop (); |
|
|
|
endwin (); |
|
return 0; |
|
} |
|
|
|
void ge_win_next(void) |
|
{ |
|
|
|
/* |
while(1) { |
switch (wge_cur) { |
if (mode == MODE_GBL) { |
|
sprintf (fmge_prompt, "global edit %s [buf %d/%d]> ", |
case wge_key: |
ge_buffers[ge_curbuf].name, |
wge_cur = wge_node; |
ge_curbuf, |
break; |
GE_MXGBL); |
|
} |
case wge_node: |
else { |
wge_cur = wge_global; |
sprintf (fmge_prompt, "block edit %s [blk %d/%d]> ", |
break; |
ge_buffers[ge_curbuf].name, |
|
ge_buffers[ge_curbuf].blocknum, |
case wge_global: |
ge_buffers[ge_curbuf].blockct); |
wge_cur = wge_block; |
} |
break; |
|
|
fmarl_buf = readline (fmge_prompt); |
case wge_block: |
if (fmarl_buf == (char *) NULL) continue; |
wge_cur = wge_command; |
|
break; |
|
|
|
case wge_command: |
|
wge_cur = wge_msg; |
|
break; |
|
|
|
case wge_msg: |
|
wge_cur = wge_key; |
|
break; |
|
|
|
} |
|
*/ |
|
|
|
} |
|
|
|
|
|
void ge_win_previous(void) |
|
{ |
|
|
|
} |
|
|
|
|
|
void ge_eventloop(void) |
cmdt = strtok (fmarl_buf, " "); |
{ |
if (cmdt == (char *) NULL) continue; |
int c; |
|
short quit_flag; |
|
|
|
quit_flag = FALSE; |
i = 0; |
|
while ((result = strtok (NULL, " ")) != NULL) { |
|
strcpy (args[i++], result); |
|
} |
|
|
while (!quit_flag) { |
argc = i; |
|
|
|
for (i = 0; i < strlen (cmdt); i++) cmdt[i] = cmdt[i] | 0140; |
|
|
noecho (); |
if (strcmp (cmdt, "exit") == 0 || strcmp (cmdt, "quit") == 0) { |
c = wgetch (wge_command); |
return 0; |
echo (); |
|
|
|
switch (c) { |
|
|
|
case 'q': |
|
case 'Q': |
|
quit_flag = TRUE; |
|
break; |
|
|
|
case KEY_LEFT: |
|
if (ge_buffers[ge_curbuf].blocknum != 0) { |
|
ge_select_block (ge_curbuf, ge_buffers[ge_curbuf].blocknum - 1); |
|
} |
|
else { |
|
ge_select_block (ge_curbuf, ge_buffers[ge_curbuf].blockct - 1); |
|
} |
|
break; |
|
|
|
case KEY_RIGHT: |
|
if (ge_buffers[ge_curbuf].blocknum + 1 < ge_buffers[ge_curbuf].blockct) { |
|
ge_select_block (ge_curbuf, ge_buffers[ge_curbuf].blocknum + 1); |
|
} |
|
else { |
|
ge_select_block (ge_curbuf, 0); |
|
} |
|
break; |
|
|
|
} |
} |
|
else if (strcmp (cmdt, "block") == 0) { |
|
mode = MODE_BLK; |
|
} |
|
else if (strcmp (cmdt, "global") == 0) { |
|
mode = MODE_GBL; |
|
} |
|
else if (strcmp (cmdt, "describe") == 0) { |
|
if (mode == MODE_GBL) { |
|
ge_describe_gbl (); |
|
} |
|
else { |
|
ge_describe_block (); |
|
} |
|
} |
|
else if (strcmp (cmdt, "open") == 0) { |
|
if (mode == MODE_GBL) { |
|
printf ("TODO\n"); |
|
} |
|
else { |
|
long blknum; |
|
blknum = atoi (args[0]); |
|
ge_select_block (ge_curbuf, blknum); |
|
} |
|
} |
|
else { |
|
printf ("fmadm: command %s not recognized\n", cmdt); |
|
} |
|
|
|
|
} |
} |
|
#endif |
|
|
|
|
|
return 0; |
} |
} |
|
|
|
|
void ge_init_buffers(void) |
void ge_init_buffers(void) |
{ |
{ |
register int i; |
register int i; |
Line 296 void ge_init_buffers(void)
|
Line 306 void ge_init_buffers(void)
|
} |
} |
} |
} |
|
|
void ge_wininit(void) |
|
{ |
|
int half; |
|
|
|
getmaxyx (stdscr, ge_rows, ge_columns); |
|
|
|
half = ge_rows / 2; |
|
|
|
/* messages window */ |
|
wge_msg_border = newwin (10, ge_columns - 41, ge_rows - 12, 0); |
|
wge_msg = newwin (8, ge_columns - 43, ge_rows - 11, 1); |
|
ge_set_wintitle (wge_msg_border, "Messages"); |
|
wrefresh (wge_msg_border); |
|
wrefresh (wge_msg); |
|
|
|
/* global window */ |
|
wge_global_border = newwin (half, 40, 0, ge_columns - 40); |
|
wge_global = newwin (half - 2, 38, 1, ge_columns - 39); |
|
ge_set_wintitle (wge_global_border, "No Global Selected"); |
|
wrefresh (wge_global_border); |
|
|
|
/* block window */ |
|
wge_block_border = newwin (half - 1, 40, half, ge_columns - 40); |
|
wge_block = newwin (half - 3, 37, half + 1, ge_columns - 38); |
|
ge_set_wintitle (wge_block_border, "Block"); |
|
wrefresh (wge_block_border); |
|
|
|
/* command window */ |
|
wge_command = newwin (1, ge_columns, ge_rows - 1, 0); |
|
wrefresh (wge_command); |
|
|
|
scrollok (wge_msg, TRUE); |
|
keypad (wge_command, TRUE); |
|
keypad (wge_msg, TRUE); |
|
keypad (wge_global, TRUE); |
|
keypad (wge_block, TRUE); |
|
|
|
curs_set (0); |
|
} |
|
|
|
void ge_update_gbl(void) |
|
{ |
|
char wintit[4096]; |
|
|
|
wclear (wge_global); |
|
snprintf (wintit, 4095, "%s [#%d]", ge_buffers[ge_curbuf].name, ge_curbuf); |
|
ge_set_wintitle (wge_global_border, wintit); |
|
|
|
wattron (wge_global, A_BOLD); |
|
wprintw (wge_global, "GLOBAL: "); |
|
wattroff (wge_global, A_BOLD); |
|
wprintw (wge_global, "%s\n", ge_buffers[ge_curbuf].name); |
|
|
|
wattron (wge_global, A_BOLD); |
|
wprintw (wge_global, "NAMESPACE: "); |
|
wattroff (wge_global, A_BOLD); |
|
wprintw (wge_global, "%s\n", ge_buffers[ge_curbuf].namespace); |
|
|
|
wattron (wge_global, A_BOLD); |
|
wprintw (wge_global, "BLOCK SIZE: "); |
|
wattroff (wge_global, A_BOLD); |
|
wprintw (wge_global, "%d bytes\n", BLOCKLEN); |
|
|
|
wattron (wge_global, A_BOLD); |
|
wprintw (wge_global, "BLOCK COUNT: "); |
|
wattroff (wge_global, A_BOLD); |
|
wprintw (wge_global, "%d\n", ge_buffers[ge_curbuf].blockct); |
|
|
|
wattron (wge_global, A_BOLD); |
|
wprintw (wge_global, "FILE SIZE: "); |
|
wattroff (wge_global, A_BOLD); |
|
wprintw (wge_global, "%d bytes\n", ge_buffers[ge_curbuf].gblsize); |
|
|
|
wrefresh (wge_global); |
|
} |
|
|
|
|
|
void ge_select_buffer(int buf) |
void ge_select_buffer(int buf) |
{ |
{ |
wprintw (wge_msg, "Selected buffer %d\n", buf); |
printf ("fmadm: selected buffer %d\n", buf); |
wrefresh (wge_msg); |
|
|
|
ge_curbuf = buf; |
ge_curbuf = buf; |
|
|
Line 387 short ge_select_block(int buf, long bloc
|
Line 322 short ge_select_block(int buf, long bloc
|
{ |
{ |
ge_blockinfo *b; |
ge_blockinfo *b; |
char *br; |
char *br; |
char key[256]; |
char key[2056]; |
char decoded[4096]; |
char decoded[64096]; |
long i; |
long i; |
long j; |
long j; |
long k; |
long k; |
long length; |
long length; |
|
|
if ((blocknum < 0) || (blocknum > (ge_buffers[buf].blockct - 1))) { |
if ((blocknum < 0) || (blocknum > (ge_buffers[buf].blockct - 1))) { |
wprintw (wge_msg, "Block number for global %s must be between 0 and %d\n", ge_buffers[buf].name, ge_buffers[buf].blockct - 1); |
printf ("block number for global %s must be between 0 and %d\n", ge_buffers[buf].name, ge_buffers[buf].blockct - 1); |
return FALSE; |
return FALSE; |
} |
} |
|
|
Line 468 short ge_select_block(int buf, long bloc
|
Line 403 short ge_select_block(int buf, long bloc
|
key[k] = g_EOL; |
key[k] = g_EOL; |
|
|
ge_decode_key (key, decoded); |
ge_decode_key (key, decoded); |
decoded[stlen (decoded)] = '\0'; |
|
wprintw (wge_msg, "found key %s\n", decoded); |
printf ("found key %s\n", decoded); |
|
|
b->keyct++; |
b->keyct++; |
} |
} |
Line 548 void ge_decode_key(const char *key, char
|
Line 483 void ge_decode_key(const char *key, char
|
|
|
} |
} |
|
|
void ge_update_block(void) |
void ge_describe_block(void) |
{ |
{ |
char wintit[4096]; |
printf ("type = %s\n", ge_buffers[ge_curbuf].block.bt_desc); |
|
|
wclear (wge_block); |
|
snprintf (wintit, 4095, "Block %d of %d", ge_buffers[ge_curbuf].blocknum, ge_buffers[ge_curbuf].blockct); |
|
ge_set_wintitle (wge_block_border, wintit); |
|
|
|
wattron (wge_block, A_BOLD); |
|
wprintw (wge_block, "TYPE: "); |
|
wattroff (wge_block, A_BOLD); |
|
wprintw (wge_block, "%s\n", ge_buffers[ge_curbuf].block.bt_desc); |
|
|
|
if (ge_buffers[ge_curbuf].blocknum != ROOT) { |
if (ge_buffers[ge_curbuf].blocknum != ROOT) { |
wattron (wge_block, A_BOLD); |
printf ("llptr = %d\n", ge_buffers[ge_curbuf].block.llptr); |
wprintw (wge_block, "LEFT LINK POINTER: "); |
printf ("rlptr = %d\n", ge_buffers[ge_curbuf].block.rlptr); |
wattroff (wge_block, A_BOLD); |
|
wprintw (wge_block, "%d\n", ge_buffers[ge_curbuf].block.llptr); |
|
|
|
wattron (wge_block, A_BOLD); |
|
wprintw (wge_block, "RIGHT LINK POINTER: "); |
|
wattroff (wge_block, A_BOLD); |
|
wprintw (wge_block, "%d\n", ge_buffers[ge_curbuf].block.rlptr); |
|
} |
} |
else { |
else { |
wattron (wge_block, A_BOLD); |
printf ("block count = %d\n", ge_buffers[ge_curbuf].block.blockcount); |
wprintw (wge_block, "BLOCK COUNT: "); |
printf ("offset to free space = %d\n", ge_buffers[ge_curbuf].block.free_offset); |
wattroff (wge_block, A_BOLD); |
} |
wprintw (wge_block, "%d\n", ge_buffers[ge_curbuf].block.blockcount); |
|
|
printf ("key count = %d\n", ge_buffers[ge_curbuf].block.keyct); |
wattron (wge_block, A_BOLD); |
} |
wprintw (wge_block, "FREE OFFSET: "); |
|
wattroff (wge_block, A_BOLD); |
void ge_update_block(void) |
wprintw (wge_block, "%d\n", ge_buffers[ge_curbuf].block.free_offset); |
{ |
} |
|
|
printf ("fmadm: selected block %d of %d\n", ge_buffers[ge_curbuf].blocknum, ge_buffers[ge_curbuf].blockct); |
wattron (wge_block, A_BOLD); |
|
wprintw (wge_block, "KEY COUNT: "); |
|
wattroff (wge_block, A_BOLD); |
|
wprintw (wge_block, "%d\n", ge_buffers[ge_curbuf].block.keyct); |
|
|
|
wrefresh (wge_block); |
|
} |
} |
|
|
int ge_open_global(char *gblname) |
int ge_open_global(char *gblname) |
Line 602 int ge_open_global(char *gblname)
|
Line 516 int ge_open_global(char *gblname)
|
|
|
snprintf (gpath, 4095, "%s/%s", fma_global_path, gblname); |
snprintf (gpath, 4095, "%s/%s", fma_global_path, gblname); |
|
|
wprintw (wge_msg, "Opening global %s [path %s, namespace %s]... ", gblname, gpath, fma_namespace); |
printf ("fmadm: opening global %s [path %s, namespace %s]... ", gblname, gpath, fma_namespace); |
|
|
wrefresh (wge_msg); |
|
|
|
if ((ge_buffers[buf].fd = open (gpath, 0)) == -1) { |
if ((ge_buffers[buf].fd = open (gpath, 0)) == -1) { |
wprintw (wge_msg, "[FAIL]\n"); |
printf ("[FAIL]\n"); |
wrefresh (wge_msg); |
|
return -1; |
return -1; |
} |
} |
else { |
else { |
wprintw (wge_msg, "[OK]\n"); |
printf ("[OK]\n"); |
wrefresh (wge_msg); |
|
} |
} |
|
|
fstat (ge_buffers[buf].fd, &sb); |
fstat (ge_buffers[buf].fd, &sb); |
Line 635 int ge_open_global(char *gblname)
|
Line 545 int ge_open_global(char *gblname)
|
return buf; |
return buf; |
} |
} |
|
|
void ge_set_wintitle(WINDOW *border_window, char *title) |
|
{ |
|
box (border_window, 0, 0); |
|
wattron (border_window, A_BOLD); |
|
mvwprintw (border_window, 0, 3, title); |
|
wattroff (border_window, A_BOLD); |
|
wrefresh (border_window); |
|
} |
|