/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2023  Ladislav Vaiz <ok1zia@nagano.cz>
    and authors of web browser Links 0.96

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/
#include "header.h"

#include "adif.h"
#include "bfu.h"
#include "charsets.h"
#include "chart.h"
#include "control.h"
#include "zcor.h"
#include "cordata.h"
#include "cwdaemon.h"
#include "cwdb.h"
#include "dwdb.h"
#include "dxc.h"
#include "edi.h"
#include "excdb.h"
#include "fifo.h"
#include "html.h"
#include "inputln.h"
#include "kst.h"
#include "map.h"
#include "main.h"
#include "masterdb.h"
#include "menu.h"
#include "namedb.h"
#include "net.h"
#include "qrvdb.h"
#include "qsodb.h"
#include "rain.h"
#include "rotar.h"
#include "tsdl.h"
#include "session.h"
#include "ssbd.h"
#include "state.h"
#include "stats.h"
#include "subwin.h"
#include "svnversion.h"
#include "terminal.h"
#include "tregex.h"
#include "update.h"
//#include "vhfcontestnet.h"
#include "slovhfnet.h"
#include "sota.h"
#include "sota_spot.h"
#include "sota_upload.h"
#ifdef VOIP
#include "voip.h"
#endif
#include "wiki.h"

#include "misc.h"


void menu_support_paypal(void) {
    z_browser("https://www.paypal.com/donate?hosted_button_id=M295RS22XFZPJ");
}

void menu_support_buymeacoffee(void) {
    z_browser("https://www.buymeacoffee.com/ok1zia");
}

void menu_support_tucnak(void *arg)
{
    msg_box(NULL, TRANSLATE("Support Tucnak"), AL_CENTER, TRANSLATE("How do you want to support Tucnak development?"), NULL, 3, 
        TRANSLATE("PayPal"), menu_support_paypal, B_ENTER,
        TRANSLATE("buymeacoffee.com"), menu_support_buymeacoffee, 0,
        VTEXT(T_CANCEL), NULL, B_ESC);
}

void menu_about(void* arg)
{
    msg_box(NULL, VTEXT(T_ABOUT), AL_CENTER, VTEXT(T_TUCNAK__TACLOG_LIKE), NULL, 1, VTEXT(T_OK), NULL, B_ENTER | B_ESC);
}

void menu_copying(void *arg)
{
    msg_box(NULL, VTEXT(T_COPYING), AL_CENTER, VTEXT(T_COPYING_VER), NULL, 1, VTEXT(T_OK), NULL, B_ENTER | B_ESC);
}

void menu_version(void *arg)
{
    static char s[256];

    g_snprintf(s, sizeof(s), VTEXT(T_TUCNAK_SVN_LIBZIA_SVN), T_SVNVER, z_svnver());
    msg_box(NULL, VTEXT(T_VERSION), AL_CENTER, s, NULL, 1, VTEXT(T_OK), NULL, B_ENTER | B_ESC);
}

void menu_info(void *arg){
	GString *gs = g_string_sized_new(1024);

	sw_raise_or_new(SWT_LOG);
	info(gs);
	fifo_add_lines(glog, gs->str);
	g_string_free(gs, TRUE);
}

void menu_settings(void *arg){
	GString *gs = g_string_sized_new(1024);
	sw_raise_or_new(SWT_LOG);
	settings(gs);
	fifo_add_lines(glog, gs->str);
	g_string_free(gs, TRUE);
}

void menu_contest_new(void *arg)
{
    if (ctest){
        msg_box(NULL, VTEXT(T_WARNING), AL_CENTER,VTEXT(T_CTEST_ACTIVE), NULL,1, VTEXT(T_CANCEL), NULL, B_ENTER |B_ESC);
        return;
    }
    contest_options1_from_menu(arg);
}

void menu_contest_new_wizz(void *arg)
{
    if (ctest){
        msg_box(NULL, VTEXT(T_WARNING),AL_CENTER, VTEXT(T_CTEST_ACTIVE), NULL,1, VTEXT(T_CANCEL), NULL, B_ENTER |B_ESC);
        return;
    }
    menu_wizz(arg);
}


void menu_contest1_options_from_ctest(void *arg)
{
    contest_options1_from_ctest(arg);
}




static int select_dir_func(const char *dir, const struct dirent *de){
    struct stat st;
    gchar *f;
	int r;

    if (strcmp((char *)de->d_name, "00000000")==0) return 0;
    r = regcmp((char *)de->d_name, "^[0-9]{8}(\\.[0-9]+)?$");
    if (r) return 0;
    f = g_strconcat(logs_dir, "/", de->d_name, NULL);
    if (stat(f, &st)) {
        g_free(f);
        return 0;
    }
    g_free(f);
    if (!S_ISDIR(st.st_mode)) return 0;

    return 1;
}

/*int compare_dir_func(const struct dirent **pde1, const struct dirent **pde2){*/
static int compare_dir_func(const void *d1, const void *d2){
    const char *c1, *c2;
    int r, n1, n2;
    const struct dirent **pde1, **pde2;


    pde1=(const struct dirent **)d1;
    pde2=(const struct dirent **)d2;


    r = strncmp( (*pde1)->d_name, (*pde2)->d_name, 8);
    if (r!=0) return -r;

    c1 = strchr( (*pde1)->d_name , '.');
    c2 = strchr( (*pde2)->d_name , '.');

    n1 = c1 ? atoi(c1+1) : 0;
    n2 = c2 ? atoi(c2+1) : 0;

    return n2 - n1;
}

static struct menu_item no_contests[] = {
    {CTEXT(T_NO_CTESTS), "", M_BAR, NULL, NULL, 0, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

void menu_load_contest(void *dir, void * unused){
    /*dbg("menu_load_contest('%s')\n", dir);*/
	int x;
	gchar *date = (char*)dir;
	x = zst_start();
    load_contest_edi(date, 0);
	zst_stop(x, __FUNCTION__);
    redraw_later();
}

static struct dirent **namelist=NULL;
static int namelistlen = 0;



void contest_choose(void (*funcall)(struct menu *menu))
{
    int i, max=0;
    gchar *dir;
    struct menu_item *mi = NULL;
    char s[1025], *d;

    //dbg("open contest \n");
	progress(VTEXT(T_DIRECTORY_SCAN));

    free_namelist();

	dir = g_strdup(logs_dir);

    namelistlen = z_scandir(dir, &namelist, select_dir_func, compare_dir_func);
    if (namelistlen<=0){
		progress(NULL);
	    set_window_ptr(gses->win, (term->x-6-11)/2,(term->y-2)/2);
        do_menu(no_contests, NULL);
        return;
    }

    if (!(mi = new_menu(3))) return;
    for (i=0; i<namelistlen; i++){
        FILE *f;
        gchar *c;
        int locked;
        gchar **items;
		struct menu_item *ami;

		locked=0;

		c = g_strdup_printf("%s/%s/desc.lock", dir, namelist[i]->d_name);
		z_wokna(c);
	    f = fopen(c, "rt");
		if (f){
			if (z_lockf(fileno(f), F_TEST, 0, 1)) locked=1;
			fclose(f);
		}
		g_free(c);

        c=g_strdup_printf("%s/%s/desc", dir, namelist[i]->d_name);
        memset(s, 0, sizeof(s));
        d = NULL;
		z_wokna(c);
        f = fopen(c, "rt");
        if (f){
            if (z_lockf(fileno(f), F_TEST, 0, 1)) locked=1;
            if (fgets(s, 1024,f) != NULL){
                if (strlen(s)>0 && s[strlen(s)-1]=='\n') s[strlen(s)-1]='\0';
                if (strlen(s)>0 && s[strlen(s)-1]=='\r') s[strlen(s)-1]='\0';
                d = strchr(s,' ');
                if (d) d++;
            }
            fclose(f);
        }
        g_free(c);

        if (!d) d=s;
        if (strlen(d)>50) d[50]='\0';

        items=g_strsplit(d, " ", 2);
        if (items && items[0] && items[1]){
            c = g_strdup_printf("%-12s%-6s  %s", namelist[i]->d_name, items[0], items[1]);
        }else{
            c = g_strdup_printf("%-12s%s", namelist[i]->d_name, d);
        }
        if (items) g_strfreev(items);



        if (strlen(c)>max) max=strlen(c);
        ami = add_to_menu(&mi,
                g_strdup(c),
                locked? "!":"", "",
                menu_load_contest, namelist[i]->d_name, 0);
		if (funcall){
			ami->checkbox = 1;
			ami->funcall = funcall;
		}
        g_free(c);
    }
    g_free(dir);

	progress(NULL);
    set_window_ptr(gses->win, (term->x-6-max)/2,(term->y-2-i)/2);

    do_menu(mi, NULL);
}

void free_namelist(){
	z_free_namelist(&namelist, &namelistlen);
}

void menu_contest_open(void *arg){
	contest_choose(NULL);
}

static void really_close_ctest(void)
{
    rel_write_all("CL\n");
    save_all_bands_txt(0);
    free_ctest();

	update_hw();
	qrv_recalc_qrbqtf(qrv);
	qrv_recalc_gst(qrv);
#ifdef Z_HAVE_SDL
	map_recalc_cors();
	maps_reload();
	maps_update_showwwls();
	rain_reload();
#endif   
	chart_reload();
#ifdef OCT8TOR
	oct8tor_send_band(goct8tor, NULL);
#endif
}

void menu_save_all(void *arg){
    save_all_bands_txt(0);
}

void menu_export_edi(void *arg){
    export_all_bands_edi();
}

void menu_export_adif(void *arg){
    export_all_bands_adif();
}

void menu_export_cbr(void *arg){
    export_all_bands_cbr();
}

void menu_export_stf(void *arg){
    export_all_bands_stf();
}

void menu_export_sota(void *arg){
    export_all_bands_sota();
}

void menu_export_report(void *arg){
    export_all_bands_report();
}

void menu_export_html(void *arg){
    export_all_bands_html();
}

void menu_export_stats(void *arg) {
	export_stats_fifo();
}

void menu_export_titlpage(void *arg) {
	export_all_bands_titlpage();
}

void menu_export_wiki(void *arg){
    export_all_bands_wiki();
}

void menu_sota_upload(void *arg){
    sota_upload();
}

void menu_send_sota_spot(void *arg){
    sota_spot_push();

//    static char qrgstr[256];
//    struct sota_spot_data ssd;
//
//    if (!ctest)
//    {
//        log_addf("No active contest");
//        return;
//    }

//	//int rignr = GPOINTER_TO_INT(itdata);
//    
//    //g_snprintf(qrgstr, EQSO_LEN, "%1.0f", gtrigs->qrg);
//	z_qrg_format(qrgstr, sizeof(qrgstr), gtrigs->qrg); 
//
//    input_field(NULL, CTEXT(T_FIXQRG), CTEXT(T_ENTER_QRG) ,
//               CTEXT(T_OK), CTEXT(T_CANCEL), itdata, 
//               NULL, 20, qrgstr, 0, 0, NULL,
//               /*(void (*)(void *, char *))*/ fixqrg, NULL, 0);

}

void menu_import_edi(void *arg){
    char *pwd;

    pwd=getcwd(NULL, 0);
    if (
#ifdef Z_HAVE_SDL
            !sdl ||
#endif
            zfiledlg_open(zfiledlg, zsel, import_edi, NULL, "", "edi") < 0){
        input_field(NULL, VTEXT(T_IMPORT_EDI), VTEXT(T_FILENAME),
                   VTEXT(T_OK), VTEXT(T_CANCEL), gses,
                   NULL, 150, pwd, 0, 0, NULL,
                   import_edi, NULL, 1);
    }
    if (pwd) free(pwd);
}

void menu_import_adif(void *arg){
    char *pwd;

    pwd=getcwd(NULL, 0);
    if (
#ifdef Z_HAVE_SDL
            !sdl ||
#endif
            zfiledlg_open(zfiledlg, zsel, import_adif, NULL, "", "adi*") < 0){
        input_field(NULL, VTEXT(T_IMPORT_ADIF), VTEXT(T_FILENAME),
                   VTEXT(T_OK), VTEXT(T_CANCEL), gses,
                   NULL, 150, pwd, 0, 0, NULL,
                   import_adif, NULL, 1);
    }
    if (pwd) free(pwd);
}

void menu_import_swap(void *arg){
    char *pwd;

    pwd=getcwd(NULL, 0);
    if (
#ifdef Z_HAVE_SDL
            !sdl ||
#endif
            zfiledlg_open(zfiledlg, zsel, import_swap, NULL, "", "swp*") < 0){
        input_field(NULL, VTEXT(T_IMPORT_SWAP), VTEXT(T_FILENAME),
                   VTEXT(T_OK), VTEXT(T_CANCEL), gses,
                   NULL, 150, pwd, 0, 0, NULL,
                   import_swap, NULL, 1);
    }
    if (pwd) free(pwd);
}

void menu_import_list(void *arg){
    char *pwd;

    pwd=getcwd(NULL, 0);
    if (
#ifdef Z_HAVE_SDL
            !sdl ||
#endif
            zfiledlg_open(zfiledlg, zsel, import_list, NULL, "", "*") < 0){
        input_field(NULL, VTEXT(T_IMPORT_LIST), VTEXT(T_FILENAME),
                   VTEXT(T_OK), VTEXT(T_CANCEL), gses,
                   NULL, 150, pwd, 0, 0, NULL,
                   import_list, NULL, 1);
    }
    if (pwd) free(pwd);
}





void menu_contest_close(void *arg)
{
    if (!ctest){
        msg_box(NULL, VTEXT(T_WARNING),AL_CENTER,VTEXT(T_NO_CCLOSE),NULL,1, VTEXT(T_CANCEL), NULL, B_ENTER |B_ESC);
        return;
    }
    msg_box(NULL, VTEXT(T_REALLY), AL_CENTER,
            VTEXT(T_CLOSE_CTEST),gses, 2,
            VTEXT(T_YES), (void (*)(void *))really_close_ctest, B_ENTER,
            VTEXT(T_NO), NULL, B_ESC);
}






   /****************************************************************************/

static void really_exit_prog(void)
{
    //zselect_bh_new(zsel, destroy_terminal, NULL);
	zselect_terminate(zsel);
}

static void dont_exit_prog(void)
{
    gses->exit_query = 0;
}

static void query_exit(void)
{
    gses->exit_query = 1;
   msg_box(NULL, VTEXT(T_EXIT_TUCNAK), AL_CENTER,
           VTEXT(T_DO_YOU_REALLY_WANT_TO_EXIT_TUCNAK), gses, 2, VTEXT(T_YES), (void (*)(void *))really_exit_prog, B_ENTER, VTEXT(T_NO), dont_exit_prog, B_ESC);
}

void exit_prog(void *arg)
{
    if (!gses) {
        //zselect_bh_new(zsel, destroy_terminal, NULL);
		zselect_terminate(zsel);
        return;
    }
    query_exit();
}


void refresh(struct refresh *r)
{
    struct refresh rr;
    r->timer = -1;
    memcpy(&rr, r, sizeof(struct refresh));
    delete_window(r->win);
    rr.fn(rr.data);
	redraw_later();
}

static void end_refresh(struct refresh *r)
{
    if (r->timer != -1) zselect_timer_kill(zsel, r->timer);
    g_free(r);
}

void refresh_abort(struct dialog_data *dlg)
{
    end_refresh((struct refresh*)dlg->dlg->udata2);
}



/*static void memory_cld(struct terminal *term, void *d)
{
#ifdef LEAK_DEBUG
    last_mem_amount = mem_amount;
#endif
} */

/* FIXME! overflow */
#define MSG_BUF 4000
#define MSG_W   100
#define LEN    30

void memory_info(void *arg)
{
    char message[MSG_BUF];
    char *p;
    struct refresh *r;
    FILE *f;
    char s[1026], *c1, *c2, *c3;
    int cnt=1;
    char *act_sbrk;

    if (!(r = (struct refresh *)g_malloc(sizeof(struct refresh)))) return;
    r->win = NULL;
    r->fn = memory_info;
    r->data = arg;
    r->timer = -1;
    p = message;
#ifdef LEAK_DEBUG
    p += sprintf(p, VTEXT(T_GUI_LD), mem_amount);
    if (last_mem_amount != -1) p += sprintf(p, ", %s %ld, %s %ld", VTEXT(T_LAST), last_mem_amount, VTEXT(T_DIFFERENCE), mem_amount - last_mem_amount);
#endif

    p += sprintf(p, VTEXT(T_CWI), get_cw_size(cw), get_wc_size(cw), cw->latest);
    p += sprintf(p, VTEXT(T_EXC), excdb->excname, get_exc_size(excdb), get_cxe_size(excdb), excdb->latest);
    p += sprintf(p, VTEXT(T_VEXC), get_vexc_size(excdb));
    p += sprintf(p, VTEXT(T_DWI), get_pd_size(dw), get_dw_size(dw), get_wd_size(dw));
    p += sprintf(p, VTEXT(T_NAMES), get_namedb_size(namedb));
    p += sprintf(p, VTEXT(T_MASTER), get_masterdb_size(masterdb));

    f = fopen("/proc/self/status", "rt");
    if (f){
        p+=sprintf(p,VTEXT(T_MEMS), 0xf00l);
        while (fgets(s, 1024, f)!=NULL){
/*            dbg("%s", s);*/
            if (regmatch(s, "Vm(.*):. *([0-9 a-zA-Z]+)", &c1, &c2, &c3, NULL)==0){
/*                dbg("match '%s' '%s' \n", c2, c3);*/
                p+=sprintf(p, " %s=%s ", c2, c3);
                cnt++;
                if (cnt==3){
                    cnt=0;
                    p+=sprintf(p, "\n");
                }
                g_free(c1);g_free(c2);g_free(c3);
            }

        }

        fclose(f);
    }
    p += sprintf(p, "\n");
#if defined(Z_UNIX_ANDROID) && !defined(Z_MACOS)
    act_sbrk = (char *)sbrk(0);
    p += sprintf(p, VTEXT(T_SBRK), act_sbrk-starting_sbrk);
#endif

    if (!(p = g_strdup(message))) {
        g_free(r);
        return;
    }
    msg_box(getml(p, NULL), VTEXT(T_MEMORY_INFO), AL_LEFT, p, r, 1, VTEXT(T_OK), NULL, B_ENTER | B_ESC);
    r->win = term->windows.next;
    ((struct dialog_data *)r->win->data)->dlg->abort = refresh_abort;
    r->timer = zselect_timer_new(zsel, RESOURCE_INFO_REFRESH, (void (*)(void *))refresh, r);
}

void net_info(void *arg);

void net_reload_ifaces(void *data, struct dialog_item_data *di){
	free_net_ifaces(gnet);
	init_net_ifaces(gnet, 1);
	net_info(NULL);
}


void net_info(void *arg)
{
    char message[MSG_BUF];
    char *p;
    struct refresh *r;
    int i;
    time_t now;
    char bytes[LEN];
    char hms[LEN];


    if (!(r = (struct refresh*)g_malloc(sizeof(struct refresh)))) return;

    now = time(NULL);
    r->win = NULL;
    r->fn = net_info;
    r->data = arg;
    r->timer = -1;
    p = message;
    
    p += sprintf(p, "%s", VTEXT(T_NMY));
    if (!gnet->v3compatibility) p += sprintf(p, "%d/", cfg->net_masterpriority); 
    p += sprintf(p, "%s:%d", inet_ntoa(gnet->my.sin_addr), ntohs(gnet->my.sin_port));
    if (gnet->v3compatibility) p += sprintf(p, "%s", VTEXT(T_V3_COMPATIBILITY));
    p += sprintf(p, "\n");
    
    p += sprintf(p, "%s", VTEXT(T_NGLOBAL));
    if (!gnet->v3compatibility) p += sprintf(p, "%d/", gnet->global_priority);
    p += sprintf(p, "%s:%d\n", inet_ntoa(gnet->global.sin_addr), ntohs(gnet->global.sin_port));

    if (gnet->master){
        p += sprintf(p, "%s %s %s %s:%d %s up %s %s %s\n",
                VTEXT(T_NMASTER),
                ns_desc[gnet->master->state],
                gnet->master->operator_?gnet->master->operator_:"",
                inet_ntoa(gnet->master->sin.sin_addr),
                ntohs(gnet->master->sin.sin_port),
                gnet->master->is_same_ctest?"OK":"--",
                z_format_hms(hms, LEN, now - gnet->master->start),
                z_format_bytes(bytes, LEN, gnet->master->rx + gnet->master->tx),
                get_timer_str(gnet->master));
    }
    if (gnet->remote){
        p += sprintf(p, "%s %s %s %s:%d %s up %s %s %s\n",
                VTEXT(T_NREMOTE), ns_desc[gnet->remote->state],
                gnet->remote->operator_?gnet->remote->operator_:"",
                inet_ntoa(gnet->remote->sin.sin_addr),
                ntohs(gnet->remote->sin.sin_port),
                gnet->remote->is_same_ctest?"OK":"--",
                z_format_hms(hms, LEN, now - gnet->remote->start),
                z_format_bytes(bytes, LEN, gnet->remote->rx + gnet->remote->tx),
                get_timer_str(gnet->remote));
    }
    if (gnet->peers->len>0){
        p += sprintf(p, VTEXT(T_NSLAVES), 0xf001);
    }
    for (i=0;i<gnet->peers->len; i++){
        struct conn *conn;

        conn = (struct conn*)g_ptr_array_index(gnet->peers, i);
        /*p += sprintf(p, "%s %s:%d\n", ns_desc[conn->state], inet_ntoa(conn->sin.sin_addr), ntohs(conn->sin.sin_port)); */
        p += sprintf(p, "%s %-6s %s %s up %s %s %s\n",
                ns_desc[conn->state],
                conn->operator_?conn->operator_:"",
                conn->remote_id,
                conn->is_same_ctest?"OK":"--",
                z_format_hms(hms, LEN, now - conn->start),
                z_format_bytes(bytes, LEN, conn->rx + conn->tx),
                get_timer_str(conn));
    }

    if (!(p = g_strdup(message))) {
        g_free(r);
        return;
    }
    //msg_box(getml(p, NULL), VTEXT(T_NINFO), AL_LEFT, p, r, 1, VTEXT(T_OK), NULL, B_ENTER | B_ESC);
    msg_box(getml(p, NULL), VTEXT(T_NINFO), AL_LEFT, p, r, 2, VTEXT(T_OK), NULL, B_ENTER | B_ESC, VTEXT(T_RELOAD_INTERFACES), net_reload_ifaces, 0);
    r->win = term->windows.next;
    ((struct dialog_data *)r->win->data)->dlg->abort = refresh_abort;
    r->timer = zselect_timer_new(zsel, RESOURCE_INFO_REFRESH, (void (*)(void *))refresh, r);
}


void crash_test(void *a, void *b){
#ifdef Z_MSC
	struct state *state;
	state = init_state();
	state_save(state);
#endif

    {
		int *pi = NULL;
		*pi = 0;
	}
}

void internal_test(void *a, void *b){
    zinternal("Simulation of internal error");
}


static struct menu_item no_bands_qrv_menu[] = {
    {CTEXT(T_NO_BANDS_QRV), "", M_BAR, NULL, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
	{TRANSLATE("Set mode"), "M", "M", menu_set_mode, NULL, 0, 0},
    {NULL, NULL, 0, NULL, NULL, 0, 0}
};

static struct menu_item no_bands_configured_menu[] = {
    {CTEXT(T_NO_BANDS_CONF), "", M_BAR, NULL, NULL, 0, 0},
    {NULL, NULL, 0, NULL, NULL, 0, 0},
};

void menu_activate_band(void *arg){
    struct band *b;
    char *pband;

    pband=(char*)arg;
    /*dbg("menu_activate_band(term=%p, pband='%s', ses=%p)\n",term,pband,ses);*/

    b=find_band_by_pband(pband);
    activate_band(b);

}



void menu_setup_band(void *arg){
    /* cba.charp=pband */
    band_settings(arg, 0);
}

void menu_bands(void *arg)
{
    struct menu_item *mi = NULL;
    int i, sel = 0;

    if (!ctest || !ctest->bands->len) {
/*            void *arg2;
        cba2.menu_item=no_bands_qrv_menu;*/
        do_menu(no_bands_qrv_menu, NULL);
        return;
    }

    for (i=0;i<ctest->bands->len;i++){
        struct band *b;
        static char *bandstrs[]={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};

        b = (struct band *)g_ptr_array_index(ctest->bands,i);

        if (!mi) if (!(mi = new_menu(3))) return;
        if (b == aband) sel = i;

        add_to_menu(&mi,
			    g_strdup_printf("%-7s%s", b->bandname, b->readonly ? " (ro)" : ""),
                bandstrs[b->bi],
                bandstrs[b->bi],
                MENU_FUNC arg, b->pband, 0);
    }

    add_to_menu(&mi, g_strdup(""), "", M_BAR, NULL, NULL, 0);
    add_to_menu(&mi, g_strdup(VTEXT(T_SET_READONLY)), "S", "S", MENU_FUNC robands, NULL, 0);
    add_to_menu(&mi, g_strdup(TRANSLATE("Set mode")), "M", "M", menu_set_mode, NULL, 0);
    do_menu_selected(mi, NULL, sel);
}

void menu_cfg_bands(void *arg)
{
    struct menu_item *mi = NULL;
    int i;


    if (!cfg || !cfg->bands->len) {
        do_menu(no_bands_configured_menu, NULL);
        return;
    }

    for (i=0;i<cfg->bands->len;i++){
        struct config_band *b;
        static char *bandstrs[]={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};

        b = (struct config_band *)g_ptr_array_index(cfg->bands,i);
        if (!b->qrv) continue;

        if (!mi) if (!(mi = new_menu(3))) return;
//            dbg("add_to_menu(%c,'%s','%s')\n", b->bandchar1, b->pband, bandstrs[zupcase(b->bandchar)-'A']);
        add_to_menu(&mi,
                g_strdup(b->pband),
                bandstrs[b->bandchar-'A'],
                bandstrs[b->bandchar-'A'],
                MENU_FUNC arg, b->pband, 0);
    }

    if (mi) add_to_menu(&mi, g_strdup(""), "", M_BAR, NULL, NULL, 0);

    for (i=0;i<cfg->bands->len;i++){
        struct config_band *b;
        static char *bandstrs[]={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};

        b = (struct config_band *)g_ptr_array_index(cfg->bands,i);
        if (b->qrv) continue;

        if (!mi) if (!(mi = new_menu(3))) return;
        add_to_menu(&mi,
                g_strdup(b->pband),
                bandstrs[b->bandchar-'A'],
                bandstrs[b->bandchar-'A'],
                MENU_FUNC arg, b->pband, 0);
    }
    do_menu(mi, NULL);
}

/*static struct menu_item not_available[] = {
    {CTEXT(T_NOT_AVAILABLE), "", M_BAR, NULL, NULL, 0, 0},
    {NULL, NULL, 0, NULL, NULL, 0, 0}
};*/



void menu_activate_subwin(void *arg){
    /*dbg("menu_activate_subwin %d\n", (int)ddd);*/

	int n = GPOINTER_TO_INT(arg);
    if (sw_set_ontop(n, 0)){
        if (gses->focused){
            sw_set_focus();
            il_unset_focus(INPUTLN(aband));
        }else{
            sw_unset_focus();
            il_set_focus(INPUTLN(aband));
        }
        redraw_later();
    }
}

void menu_kill_connection(void *arg, void *arg2){
    struct subwin *sw = (struct subwin *)arg;
    switch (sw->type){
        case SWT_KST:
            sw_kst_disconnect(sw);
            break;
        case SWT_DXC:
            sw_dxc_disconnect(sw);
            break;
        default:
            break;
    }
}

void menu_send_ctrlc(void *arg, void *arg2){
    struct subwin *sw = (struct subwin *)arg;
    sw_shell_enter(sw, "\x03", 0);
}

void subwins_menu(void *arg)
{
    struct menu_item *mi = NULL;
    int i, sep = 0;
    char s[16];

    /*if (!ctest) {
        do_menu(not_available, NULL);
        return;
    }     */

    if (!(mi = new_menu(0x02 | 0x04))) return;
    add_to_menu(&mi, g_strdup(VTEXT(T_ADD_SUBWIN)), g_strdup(""), VTEXT(T_HK_ADD_SUBWIN), MENU_FUNC menu_add_subwin, GINT_TO_POINTER(0), 0);
    add_to_menu(&mi, g_strdup(VTEXT(T_CLOSE_SUBWIN)), g_strdup(""), VTEXT(T_HK_CLOSE_SUBWIN), MENU_FUNC menu_close_subwin, NULL, 0);
    add_to_menu(&mi, g_strdup(VTEXT(T_CHANGE_TYPE)), g_strdup(""), VTEXT(T_HK_CHANGE_TYPE), MENU_FUNC menu_add_subwin, GINT_TO_POINTER(1), 0);	  // TODO text


    if (arg == NULL) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);
    for (i = 0; i < gses->subwins->len; i++){
        struct subwin *sw = (struct subwin *)g_ptr_array_index(gses->subwins, i);
        if (sw != gses->ontop) continue;

        switch (sw->type){
            case SWT_KST:
			    if (arg != NULL && sep == 0) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_OPEN_CONNECTION)), g_strdup(""), VTEXT(T_HK_OPEN_CONNECTION), kst_open_connection, sw, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_KILL_CONNECTION)), g_strdup(""), VTEXT(T_HK_KILL_CONNECTION), menu_kill_connection, sw, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_EXPORT_TO_TEXT_FILE)), g_strdup(""), VTEXT(T_HK_EXPORT_TO_TEXT_FILE), kst_export_text, sw, 0);
				//add_to_menu(&mi, g_strdup("OK1MZM: >>>> Press HERE <<<<"), "", "D", kst_dump_skip, sw, 0);
                sep = 1;
                break;
            case SWT_DXC:
			    if (arg != NULL && sep == 0) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_OPEN_CONNECTION)), g_strdup(""), VTEXT(T_HK_OPEN_CONNECTION), dxc_open_connection, sw, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_KILL_CONNECTION)), g_strdup(""), VTEXT(T_HK_KILL_CONNECTION), menu_kill_connection, sw, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_EXPORT_TO_TEXT_FILE)), g_strdup(""), CTEXT(T_HK_EXPORT_TO_TEXT_FILE), dxc_export_text, sw, 0);
                sep = 1;
                break;
            case SWT_SHELL:
			    if (arg != NULL && sep == 0) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_KILL_CONNECTION)), g_strdup(""), VTEXT(T_HK_KILL_CONNECTION), menu_send_ctrlc, sw, 0);
                sep = 1;
                break;
			case SWT_CHART:
				if (arg != NULL && sep == 0) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_ADD_CONTEST)), g_strdup(""), VTEXT(T_HK_ADD_CONTEST), menu_chart_add_contest, sw, 0);
				add_to_menu(&mi, g_strdup(VTEXT(T_ADD_FILES)), g_strdup(""), VTEXT(T_HK_ADD_FILES), menu_chart_add_files, sw, 0);
                sep = 1;
				break;
			case SWT_QRV:
				if (arg != NULL && sep == 0) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);
                add_to_menu(&mi, g_strdup(VTEXT(T_ADD_CONTESTS)), g_strdup(""), VTEXT(T_HK_ADD_CONTESTS), menu_qrv_add_contest, sw, 0);
				sep = 1;
				break;
            default:
                break;
        }
    }

	if (arg == NULL) {
	    if (sep) add_to_menu(&mi, g_strdup(""), g_strdup(""), M_BAR, NULL, NULL, 0);

		for (i = 0; i < gses->subwins->len; i++){
			struct subwin *sw;
			char *rtext;

			sw = (struct subwin *)g_ptr_array_index(gses->subwins,i);

            if (i <= 9)
                rtext = g_strdup_printf(VTEXT(T_ALTC), '0' + ((i + 1) % 10));
            else if (i <= 19 && zsdl_get())
                rtext = g_strdup_printf(VTEXT(T_CTRLC), '0' + ((i + 1) % 10));
            else
                rtext = g_strdup("");


			sprintf(s,"%d", i);
			add_to_menu(&mi,
					g_strdup(sw->title),
					rtext,
					"",
					MENU_FUNC menu_activate_subwin, GINT_TO_POINTER(i), 0);
		}
	}
    do_menu(mi, NULL);
}


static char phase_str[EQSO_LEN];

void menu_confirm_phase(void *xxx, char *phase){
	int ph = atoi(phase);
	if (ph >= 1) ctest->phase = ph;
	save_all_bands_txt(0);
	
	char s[100];
	g_snprintf(s, 100, "PH %d\n", ph);
	rel_write_all(s);

    qrv_recalc_wkd(qrv);
}


void menu_phase(void){
	g_snprintf(phase_str, EQSO_LEN, "%d", ctest->phase);
	input_field(NULL, VTEXT(T_PHASE), VTEXT(T_ENTER_PHASE),
		VTEXT(T_OK), VTEXT(T_CANCEL), gses,
		NULL, EQSO_LEN, phase_str, 1, 9, NULL,
		menu_confirm_phase, NULL, 0);
}




/****************** NETWORK ********************************************/

void display_codepage(void *arg)
{
    int cp = GPOINTER_TO_INT(arg);
    struct term_spec *t = new_term_spec(term->term);
    if (t) t->charset = cp;
    redraw_terminal_cls();
}

void charset_list(void *arg)
{
    int i, sel;
    char *n;
    struct menu_item *mi;

    if (!(mi = new_menu(1))) return;
    for (i = 0; (n = get_cp_name(i)); i++) {
        if (is_cp_special(i)) continue;

        add_to_menu(&mi, get_cp_name(i), "", "", MENU_FUNC display_codepage, GINT_TO_POINTER(i), 0);
    }
    sel = term->spec->charset;
    if (sel < 0) sel = 0;
    do_menu_selected(mi, NULL, sel);
}

/*void set_val(cba_t *ip, cba_t *d)
{
    *d = (vint)ip;
}

void charset_sel_list(void *arg)
{
    int i, sel;
    char *n;
    struct menu_item *mi;
    if (!(mi = new_menu(1))) return;
    for (i = 0; (n = get_cp_name(i)); i++) {
        void *arg2;

        cba2.int_=i;
        add_to_menu(&mi, get_cp_name(i), "", "", MENU_FUNC set_val, cba2, 0);
    }
    sel = *ptr;
    if (sel < 0) sel = 0;
    do_menu_selected(term, mi, ptr, sel);
}  */

static void terminal_options_ok(void *p)
{
    redraw_terminal_cls();

#ifdef AUTOSAVE
    menu_save_rc(NULL);
#endif
}

static char *td_labels[] = { CTEXT(T_NO_FRAMES), CTEXT(T_VT_100_FRAMES), CTEXT(T_LINUX_OR_OS2_FRAMES), CTEXT(T_KOI8R_FRAMES), CTEXT(T_USE_11M), CTEXT(T_RESTRICT_FRAMES_IN_CP850_852), CTEXT(T_BLOCK_CURSOR), CTEXT(T_COLOR), CTEXT(T_UTF_8_IO), NULL };

void terminal_options(void *arg)
{
    struct dialog *d;
    struct term_spec *ts = new_term_spec(term->term);
    if (!ts) return;
    if (!(d = (struct dialog *)g_malloc(sizeof(struct dialog) + 12 * sizeof(struct dialog_item)))) return;
    memset(d, 0, sizeof(struct dialog) + 12 * sizeof(struct dialog_item));
    d->title = VTEXT(T_TERMINAL_OPTIONS);
    d->fn = checkbox_list_fn;
    d->udata = td_labels;
    d->refresh = (void (*)(void *))terminal_options_ok;
    d->items[0].type = D_CHECKBOX;
    d->items[0].gid = 1;
    d->items[0].gnum = TERM_DUMB;
    d->items[0].dlen = sizeof(int);
    d->items[0].data = (char *)&ts->mode;
    d->items[1].type = D_CHECKBOX;
    d->items[1].gid = 1;
    d->items[1].gnum = TERM_VT100;
    d->items[1].dlen = sizeof(int);
    d->items[1].data = (char *)&ts->mode;
    d->items[2].type = D_CHECKBOX;
    d->items[2].gid = 1;
    d->items[2].gnum = TERM_LINUX;
    d->items[2].dlen = sizeof(int);
    d->items[2].data = (char *)&ts->mode;
    d->items[3].type = D_CHECKBOX;
    d->items[3].gid = 1;
    d->items[3].gnum = TERM_KOI8;
    d->items[3].dlen = sizeof(int);
    d->items[3].data = (char *)&ts->mode;
    d->items[4].type = D_CHECKBOX;
    d->items[4].gid = 0;
    d->items[4].dlen = sizeof(int);
    d->items[4].data = (char *)&ts->m11_hack;
    d->items[5].type = D_CHECKBOX;
    d->items[5].gid = 0;
    d->items[5].dlen = sizeof(int);
    d->items[5].data = (char *)&ts->restrict_852;
    d->items[6].type = D_CHECKBOX;
    d->items[6].gid = 0;
    d->items[6].dlen = sizeof(int);
    d->items[6].data = (char *)&ts->block_cursor;
    d->items[7].type = D_CHECKBOX;
    d->items[7].gid = 0;
    d->items[7].dlen = sizeof(int);
    d->items[7].data = (char *)&ts->col;
    d->items[8].type = D_CHECKBOX;
    d->items[8].gid = 0;
    d->items[8].dlen = sizeof(int);
    d->items[8].data = (char *)&ts->utf_8_io;
    d->items[9].type = D_BUTTON;
    d->items[9].gid = B_ENTER;
    d->items[9].fn = ok_dialog;
    d->items[9].text = VTEXT(T_OK);
    d->items[10].type = D_BUTTON;
    d->items[10].gid = B_ESC;
    d->items[10].fn = cancel_dialog;
    d->items[10].text = VTEXT(T_CANCEL);
    d->items[11].type = D_END;
    do_dialog(d, getml(d, NULL));
}

#ifndef Z_MSC_MINGW
void menu_shell(void *arg)
{
    char *sh;
    if (!(sh = GETSHELL)) sh = DEFAULT_SHELL;
    exec_on_terminal(sh, "", 1);
}
#endif

void menu_set_language(void *arg)
{
    set_language(GPOINTER_TO_INT(arg));
    redraw_terminal_cls();

#ifdef AUTOSAVE
    menu_save_rc(NULL);
#endif
}

void menu_language_list(void *arg)
{
    int i, sel;
    char *n;
    struct menu_item *mi;
    if (!(mi = new_menu(1))) return;
    for (i = 0; i < n_languages(); i++) {
        n = language_name(i);
        add_to_menu(&mi, n, "", "", MENU_FUNC menu_set_language, GINT_TO_POINTER(i), 0);
    }
    sel = current_language;
    do_menu_selected(mi, NULL, sel);
}



static struct menu_item file_menu22[] = {
/*  "", "", M_BAR, NULL, NULL, 0, 0,*/
#ifdef HAVE_SNDFILE
    {CTEXT(T_PLAY_LAST), CTEXT(T_CTRLP), CTEXT(T_HK_PLAY_LAST), MENU_FUNC menu_play_last, NULL, 0, 0},
    {CTEXT(T_BREAK_RECORD), "", CTEXT(T_HK_BREAK_RECORD), MENU_FUNC menu_break_record, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
#endif
    {CTEXT(T_MEMORY_INFO), "", CTEXT(T_HK_MEMORY_INFO), MENU_FUNC memory_info, NULL, 0, 0},
    {CTEXT(T_NINFO), "", CTEXT(T_HK_NINFO), MENU_FUNC net_info, NULL, 0, 0},
//	{CTEXT(T_CRASH_TEST), "", CTEXT(T_HK_CRASH_TEST), crash_test, NULL, 0, 0},
//	{CTEXT(T_INTERROR_TEST), "", CTEXT(T_HK_INTERNAL_TEST), internal_test, NULL, 0, 0},
	//{CTEXT(T_DUMP_RW_BANDS), "", CTEXT(T_HK_DUMP_RW_BANDS), dump_rw, NULL, 0, 0},
	{CTEXT(T_UPDATE), "", CTEXT(T_HK_UPDATE), update_tucnak, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0}
};

static struct menu_item file_menu3[] = {
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_EXIT), "", CTEXT(T_HK_EXIT), MENU_FUNC exit_prog, NULL, 0, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

void do_file_menu(void *arg)
{
    int x,file_menu1_size;
    struct menu_item *file_menu, *e, *f;

    file_menu1_size=0;

    if (!(file_menu = (struct menu_item*)g_malloc0(file_menu1_size +
                                sizeof(file_menu22) +
                                sizeof(file_menu3) +
                                3 * sizeof(struct menu_item)))) return;
    e = file_menu;
    memcpy(e, file_menu22, sizeof(file_menu22));
    e += sizeof(file_menu22) / sizeof(struct menu_item);
    x = 1;
#ifdef Z_HAVE_SDL
    if (sdl) {
/*	    e->text = VTEXT(T_OS_SHELL);
        e->rtext = "";
        e->hotkey = VTEXT(T_HK_OS_SHELL);
        e->data = NULL;
        e->in_m = 0;
        e->free_i = 0;
        e++;
        x = 0; */
	}else
#endif
	{
#ifndef Z_MSC_MINGW
        e->text = VTEXT(T_OS_SHELL);
        e->rtext = "";
        e->hotkey = VTEXT(T_HK_OS_SHELL);
        e->func = MENU_FUNC menu_shell;
        e->data = NULL;
        e->in_m = 0;
        e->free_i = 0;
        e++;
        x = 0;
#endif
    }
    memcpy(e, file_menu3 + x, sizeof(file_menu3) - x * sizeof(struct menu_item));
    e += sizeof(file_menu3) / sizeof(struct menu_item);
    for (f = file_menu; f < e; f++) f->free_i = 1;
    do_menu(file_menu, NULL);
}
#ifndef Z_HAVE_SDL
#undef sdl
#endif


static struct menu_item help_menu[] = {
    {TRANSLATE("Support Tucnak"), "", CTEXT(T_HK_ABOUT), MENU_FUNC menu_support_tucnak, NULL, 0, 0},
    {CTEXT(T_ABOUT), "", CTEXT(T_HK_ABOUT), MENU_FUNC menu_about, NULL, 0, 0},
    {CTEXT(T_COPYING), "", CTEXT(T_HK_COPYING), MENU_FUNC menu_copying, NULL, 0, 0},
    {CTEXT(T_VERSION), "", CTEXT(T_HK_VERSION), MENU_FUNC menu_version, NULL, 0, 0},
    {CTEXT(T_INFO), "", CTEXT(T_HK_INFO), MENU_FUNC menu_info, NULL, 0, 0},
    {CTEXT(T_SETTINGS), "", CTEXT(T_HK_SETTINGS), MENU_FUNC menu_settings, NULL, 0, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};



/************************* CONTEST MENU *********************************/

static struct menu_item ctest_menu1[] = {
    {CTEXT(T_NEW),        "", CTEXT(T_HK_NEW), MENU_FUNC menu_contest_new, NULL, 0, 0},
    {CTEXT(T_NEW_WIZZ),   ">", CTEXT(T_HK_NEW_WIZZ), MENU_FUNC menu_contest_new_wizz, NULL, 1, 0},
	{CTEXT(T_NEW_NET),    "", CTEXT(T_HK_NEW_NET), MENU_FUNC menu_discover_peers3, open_from_net3, 0, 0},
    //{"New from net old",    "", "O", MENU_FUNC menu_contest_config_from_peer, send_contest_config_request, 0, 0},
    {CTEXT(T_OPEN),       "F3 >", CTEXT(T_HK_OPEN), MENU_FUNC menu_contest_open, NULL, 1, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

static struct menu_item ctest_menu2[] = {
    {CTEXT(T_SAVE),           "F2", CTEXT(T_HK_SAVE), MENU_FUNC menu_save_all, NULL, 0, 0},
	{CTEXT(T_FILLOP),         "", CTEXT(T_HK_FILLOP), MENU_FUNC menu_fillop, GINT_TO_POINTER(1), 0, 0},
    {CTEXT(T_QSO_CHECK),      "", CTEXT(T_HK_QSO_CHECK), MENU_FUNC menu_qso_check, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_EXPORT_EDI),     "",  CTEXT(T_HK_EXPORT_EDI), MENU_FUNC menu_export_edi, NULL, 0, 0},
	{CTEXT(T_UPLOAD_TO_SLOVHF), "", CTEXT(T_HK_UPLOAD_TO_SLOVHF), MENU_FUNC slovhfnet_upload, NULL, 0, 0},
	//{CTEXT(T_UPLOAD_TO_VHFNET), "", CTEXT(T_HK_UPLOAD_TO_VHFNET), MENU_FUNC vhfcontestnet_upload, NULL, 0, 0},
    {CTEXT(T_EXPORT_REPORT),  "",  CTEXT(T_HK_EXPORT_REPORT), MENU_FUNC menu_export_report, NULL, 0, 0},
    {CTEXT(T_EXPORT_ADIF),    "",  CTEXT(T_HK_EXPORT_ADIF), MENU_FUNC menu_export_adif, NULL, 0, 0},
    {CTEXT(T_EXPORT_HTML),    "",  CTEXT(T_HK_EXPORT_HTML), MENU_FUNC menu_export_html, NULL, 0, 0},
    {CTEXT(T_EXPORT_STATS),   "",  CTEXT(T_HK_EXPORT_STATS), MENU_FUNC menu_export_stats, NULL, 0 , 0},
    {CTEXT(T_EXPORT_TITLPAGE),"",  CTEXT(T_HK_EXPORT_TITLPAGE), MENU_FUNC menu_export_titlpage, NULL, 0 , 0},
    {CTEXT(T_EXPORT_CBR),     "",  CTEXT(T_HK_EXPORT_CBR), MENU_FUNC menu_export_cbr, NULL, 0, 0},
    {CTEXT(T_EXPORT_STF),     "",  CTEXT(T_HK_EXPORT_STF), MENU_FUNC menu_export_stf, NULL, 0, 0},
    {CTEXT(T_EXPORT_SOTA),     "",  CTEXT(T_HK_EXPORT_SOTA), MENU_FUNC menu_export_sota, NULL, 0, 0},
    {CTEXT(T_EXPORT_WIKI),    "",  CTEXT(T_HK_EXPORT_WIKI), MENU_FUNC menu_export_wiki, NULL, 0, 0},
	{CTEXT(T_MEDIAWIKI_UPLOAD), "", CTEXT(T_HK_MEDIAWIKI_UPLOAD), MENU_FUNC wiki_upload, NULL, 0, 0},
    {CTEXT(T_SOTA_UPLOAD_LOG),     "",  CTEXT(T_HK_SOTA_UPLOAD_LOG), MENU_FUNC menu_sota_upload, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_SEND_SOTA_SPOT),     "",  CTEXT(T_HK_SEND_SOTA_SPOT), MENU_FUNC menu_send_sota_spot, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_IMPORT_EDI),     "",  CTEXT(T_HK_IMPORT_EDI),  MENU_FUNC menu_import_edi,  NULL, 0, 0},
    {CTEXT(T_IMPORT_ADIF),    "",  CTEXT(T_HK_IMPORT_ADIF), MENU_FUNC menu_import_adif, NULL, 0, 0},
    {CTEXT(T_IMPORT_SWAP),    "",  CTEXT(T_HK_IMPORT_SWAP), MENU_FUNC menu_import_swap, NULL, 0, 0},
    {CTEXT(T_IMPORT_LIST),    "",  CTEXT(T_HK_IMPORT_LIST), MENU_FUNC menu_import_list, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_CONTEST_OP),  "",  CTEXT(T_HK_CONTEST_OP), MENU_FUNC menu_contest1_options_from_ctest, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_CLOSE_CONTEST),     "",  CTEXT(T_HK_CLOSE_CONTEST), MENU_FUNC menu_contest_close, NULL, 0, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

void do_contest_menu(void *arg)
{
    if (!ctest) do_menu(ctest_menu1, NULL);
    else        do_menu(ctest_menu2, NULL);
}
/************************* EDIT MENU *********************************/

static struct menu_item edit_menu[] = {
    {CTEXT(T_RUN_MODE), "", CTEXT(T_HK_RUN_MODE), MENU_FUNC menu_runmode, NULL, 0, 0},
	{CTEXT(T_SP_MODE), "", CTEXT(T_HK_SP_MODE), MENU_FUNC menu_spmode, NULL, 0, 0},
	{CTEXT(T_PHASE), "", CTEXT(T_HK_PHASE), MENU_FUNC menu_phase, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_1ST), "", CTEXT(T_HK_1ST), MENU_FUNC menu_extcq, GINT_TO_POINTER(EC_1ST), 0, 0},
    {CTEXT(T_2ND), "", CTEXT(T_HK_2ND), MENU_FUNC menu_extcq, GINT_TO_POINTER(EC_2ND), 0, 0},
    {CTEXT(T_ODD), "", CTEXT(T_HK_ODD), MENU_FUNC menu_extcq, GINT_TO_POINTER(EC_ODD), 0, 0},
    {CTEXT(T_EVEN), "", CTEXT(T_HK_EVEN), MENU_FUNC menu_extcq, GINT_TO_POINTER(EC_EVEN), 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_ROTAR), "Alt+R", CTEXT(T_HK_ROTAR), MENU_FUNC menu_rotar, NULL, 0, 0},
    {CTEXT(T_ADD_ERROR), "", CTEXT(T_HK_ADD_ERROR),  MENU_FUNC menu_add_error, NULL, 0, 0},
    {CTEXT(T_CHOP), "Alt+O", CTEXT(T_HK_CHOP),  MENU_FUNC menu_chop, NULL, 0, 0},
    {CTEXT(T_CALL_INFO), "Alt+I", CTEXT(T_HK_CALL_INFO), MENU_FUNC call_info, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_SKED_QRG), "Alt+F", CTEXT(T_HK_SKED_QRG),  MENU_FUNC menu_skedqrg, NULL, 0, 0},
//    {CTEXT(T_GRAB_BAND), "Alt+G", CTEXT(T_HK_GRAB_BAND),  MENU_FUNC menu_grabband, NULL, 0, 0},
//    {CTEXT(T_FORCE_RUN), "", CTEXT(T_HK_FORCE_RUN),  MENU_FUNC menu_forcerun, NULL, 0, 0},
#ifdef HAVE_HAMLIB
    {CTEXT(T_FIXQRG), "", CTEXT(T_HK_FIXQRG),  menu_fixqrg, NULL, 0, 0},
#endif
    {CTEXT(T_CH_SPY), "", CTEXT(T_HK_CH_SPY), menu_discover_peers3, spy3, 0, 0},
    {CTEXT(T_CH_ENDSPY), "", CTEXT(T_HK_CH_ENDSPY), MENU_FUNC menu_endspy, NULL, 0},
#ifdef VOIP
#ifdef HAVE_SNDFILE
    {CTEXT(T_VOIP_SPY), "", CTEXT(T_HK_VOIP_SPY), menu_discover_peers3, voip_spy, 0, 0},
    {CTEXT(T_END_VOIP_SPY), "", CTEXT(T_HK_END_VOIP_SPY), voip_end_spy, NULL, 0, 0},
#endif
#endif

    {"", "", M_BAR, NULL, NULL, 0, 0},
//    {CTEXT(T_RECAQRB), "", CTEXT(T_HK_RECAQRB),  MENU_FUNC menu_recalc_qrb, NULL, 0, 0},
    {CTEXT(T_CW_CTEST), "", CTEXT(T_HK_CW_CTEST),  MENU_FUNC menu_cw_update_contest, NULL, 0, 0},
    {CTEXT(T_CW_BAND), "", CTEXT(T_HK_CW_BAND),  MENU_FUNC menu_cw_update_band, NULL, 0, 0},
    {CTEXT(T_EXC_CTEST), "", CTEXT(T_HK_EXC_CTEST),  MENU_FUNC menu_exc_update_contest, NULL, 0, 0},
    {CTEXT(T_EXC_BAND), "", CTEXT(T_HK_EXC_BAND),  MENU_FUNC menu_exc_update_band, NULL, 0, 0},
    {CTEXT(T_IMPORT_MMM), "", CTEXT(T_HK_IMPORT_MMM),  MENU_FUNC menu_import_mmm, NULL, 0, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

static struct menu_item edit_menu2[] = {
    {CTEXT(T_ROTAR), "Alt+R", CTEXT(T_HK_ROTAR), MENU_FUNC menu_rotar, NULL, 0, 0},
    {CTEXT(T_CALL_INFO), "Alt+I", CTEXT(T_HK_CALL_INFO), MENU_FUNC call_info, NULL, 0, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
#ifdef HAVE_HAMLIB
    {CTEXT(T_FIXQRG), "", CTEXT(T_HK_FIXQRG),  menu_fixqrg, NULL, 0, 0},
#endif
#ifdef VOIP
#ifdef HAVE_SNDFILE
    {CTEXT(T_VOIP_SPY), "", CTEXT(T_HK_VOIP_SPY), menu_discover_peers3, voip_spy, 0, 0},
    {CTEXT(T_END_VOIP_SPY), "", CTEXT(T_HK_END_VOIP_SPY), voip_end_spy, NULL, 0, 0},
#endif
#endif
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_IMPORT_MMM), "", CTEXT(T_HK_IMPORT_MMM),  MENU_FUNC menu_import_mmm, NULL, 0, 0},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

void do_edit_menu(void *arg)
{
    if (!ctest || !aband) do_menu(edit_menu2, NULL);
    else                  do_menu(edit_menu, NULL);
}

/************************** SETUP MENU ************************************/

void menu_save_rc(void *arg){
	gchar *filename;
	gchar *c;
	int ret;

	if (opt_tucnakrc)
		filename = g_strdup(opt_tucnakrc);
	else
		filename = g_strconcat(tucnak_dir, "/tucnakrc", NULL);

	z_wokna(filename);
    ret=save_rc_file(filename);
    if (ret) {
        c = g_strdup_printf(VTEXT(T_CANT_WRITE_S), filename);
        errbox(c, ret);
        g_free(c);
//#ifndef AUTOSAVE
    }else{
        log_addf(VTEXT(T_SAVED_S), filename);
//#endif
    }

    g_free(filename);

}

void do_peer_menu(void (* func)(void *arg)){
    int i,max;
    struct menu_item *mi = NULL;
    gchar **items;

    items = g_strsplit(gnet->allpeers,";",0);
    max=0;
    for (i=0; items[i]!=NULL;i++){
        if (strcmp(items[i],gnet->myid)==0) continue;
        if (strlen(items[i])==0) continue;

        if (!mi) if (!(mi = new_menu(3))) return;
        if (strlen(items[i])>max) max=strlen(items[i]);
        add_to_menu(&mi,g_strdup(items[i]),"", "", MENU_FUNC func, GINT_TO_POINTER(i), 0);
    }
    g_strfreev(items);

    if (mi){
        set_window_ptr(gses->win, (term->x-max)/2,(term->y-2-i)/2);
        do_menu(mi, NULL);
    }else
        errbox(VTEXT(T_NO_PEERS),0);
    return;

}

void do_peer_operators_menu(void (* func)(void *arg)){
    int i,max;
    struct menu_item *mi = NULL;
    gchar **items,*c;

    items = g_strsplit(gnet->allpeers,";",0);
    max=0;
    for (i=0; items[i]!=NULL && items[i+1]!=NULL;i+=2){

        if (strcmp(items[i],gnet->myid)==0) continue;
        if (strlen(items[i])==0) continue;

        if (!mi) if (!(mi = new_menu(3))) return;
        c=g_strdup_printf("%-8s %s", items[i+1], items[i]);
        if (strlen(c)>max) max=strlen(c);
        add_to_menu(&mi,g_strdup(c),"", "", MENU_FUNC func, GINT_TO_POINTER(i), 0);
        g_free(c);
    }
    g_strfreev(items);

    if (mi){
        set_window_ptr(gses->win, (term->x-max)/2,(term->y-2-i)/2);
        do_menu(mi, NULL);
    }else
        errbox(VTEXT(T_NO_PEERS),0);
    return;
}

void menu_load_from_peer(void *arg){
    GString *gs;
    char *op;

    /*dbg("menu_load_from_peer\n"); */

    if (cmp_sin(&gnet->global, &gnet->my)==0) { /* i'm master */
        int i;
        struct conn *conn;

        /* LOOK ALSO net.c rel_write, dommand DO */

        CONDGFREE(gnet->allpeers);
        gs=g_string_sized_new(100);
        for (i=0;i<gnet->peers->len;i++){
            conn = (struct conn *)g_ptr_array_index(gnet->peers,i);

            if (!conn_prod_state(conn)) continue;
            op="---";
            if (ctest && aband && conn->operator_) op=conn->operator_;
            g_string_append_printf(gs,"%s;%s;", conn->remote_id, op);
        }
        gnet->allpeers=g_strdup(gs->str);
        g_string_free(gs,TRUE);
        do_peer_operators_menu(arg); /* todo */
        return;
    }

    /* i'm slave */
    if (!conn_prod_state(gnet->master)){
        errbox(VTEXT(T_NO_MASTER),0);
        return;
    }

    gnet->peerfunc = (PEER_FUNC)arg;
    rel_write(gnet->master, "DO\n");
}


void do_spy_peer_menu(void (* func)(void *arg)){
    int i,max,menui;
    struct menu_item *mi = NULL;
    gchar **items,*c, *d;
    GString *gs;

    dbg("do_spy_peer_menu() rwbpeers='%s'\n", gnet->rwbpeers);
    items = g_strsplit(gnet->rwbpeers,";",0);
    gs = g_string_sized_new(200);
    max=0;
    menui=0;
    for (i=0;
         items[i]!=NULL && items[i+1]!=NULL && items[i+2]!=NULL;
         i+=3){

        if (strcmp(items[i],gnet->myid)==0) continue;
        if (strlen(items[i])==0) continue;

        for (d=items[i+2]; *d!='\0'; d++){
            if (!mi) if (!(mi = new_menu(3))) return;
            c=g_strdup_printf("%-6s %c   %s", items[i+1], *d, items[i]);
            if (strlen(c)>max) max=strlen(c);
            add_to_menu(&mi,g_strdup(c),"", "", MENU_FUNC func, GINT_TO_POINTER(menui), 0);
			dbg("add_to_menu(%s) menui=%d\n", c, menui);
            g_free(c);
            g_string_append_printf(gs, "%s;%s;%c;", items[i], items[i+1], *d);
			menui++;
        }
    }
    g_strfreev(items);
    CONDGFREE(gnet->bpeers);
    gnet->bpeers = g_strdup(gs->str);
    g_string_free(gs, TRUE);
    dbg("do_spy_peer_menu() bpeers='%s' menui=%d\n", gnet->bpeers, menui);

    if (mi){
        set_window_ptr(gses->win, (term->x-max)/2,(term->y-2-i)/2);
        do_menu(mi, NULL);
    }else
        errbox(VTEXT(T_NO_PEERS),0);
    return;
}

void menu_spy_from_peer(void *arg){
    GString *gs;
    char *op;
    char *rwb;

    /*dbg("menu_load_from_peer\n"); */

    if (cmp_sin(&gnet->global, &gnet->my)==0) { /* i'm master */
        int i;
        struct conn *conn;

        /* LOOK ALSO net.c rel_write, dommand DO */

        CONDGFREE(gnet->rwbpeers);
        gs=g_string_sized_new(100);
        for (i=0;i<gnet->peers->len;i++){
            conn = (struct conn *)g_ptr_array_index(gnet->peers,i);

            if (!conn_prod_state(conn)) continue;
            op="---";
            if (ctest && aband && conn->operator_) op=conn->operator_;
            rwb="";
            if (conn->rwbands) rwb=conn->rwbands;
            g_string_append_printf(gs,"%s;%s;%s;", conn->remote_id, op, rwb);
        }
        gnet->rwbpeers=g_strdup(gs->str);
        g_string_free(gs,TRUE);
        do_spy_peer_menu((void (*)(void*))arg);
        return;
    }

    /* i'm slave */
    if (!conn_prod_state(gnet->master)){
        errbox(VTEXT(T_NO_MASTER),0);
        return;
    }

    gnet->peerfunc = (PEER_FUNC)arg;
    rel_write(gnet->master, "DR\n");
}



void select_open_from_net3(void *itarg, void *menuarg){
	load_from_net(itarg);


}

void open_from_net3(void *xxx){
	int tok = 0, max = 0, menui = 0;
	char *peer, *id, *op, *s, *cdate, *pcall, *tname;
	struct menu_item *mi = NULL;
	char *peers3;

	progress(NULL);
	peers3 = g_strdup(gnet->peers3->str);
	while ((peer = z_tokenize(peers3, &tok)) != NULL){
		int tok2 = 0;
		id = z_tokenize(peer, &tok2);
		op = z_tokenize(peer, &tok2);
		/*rwbands =*/ z_tokenize(peer, &tok2);
		cdate = z_tokenize(peer, &tok2);
		pcall = z_tokenize(peer, &tok2);
		tname = z_tokenize(peer, &tok2);
        if (!tname) continue;

		if (!mi) mi = new_menu(3);
		s = g_strdup_printf("%21s %s %s (%s) %s", id, cdate, pcall, op, tname);
		if (strlen(s) > max) max = strlen(s);
		add_to_menu(&mi, s, "", "", select_open_from_net3, GINT_TO_POINTER(menui), 0);
        menui++;
	}
    g_free(peers3);
    dbg("menui=%d\n");
	if (mi){
        set_window_ptr(gses->win, (term->x-max)/2,(term->y-2-menui)/2);
        do_menu(mi, NULL);
    }else
        errbox(VTEXT(T_NO_PEERS),0);
}

void select_spy3(void *itarg, void *menuarg){
    char *peers3, *peer, *id, *rwbands, *c;
    int tok = 0, menui = 0, no = GPOINTER_TO_INT(itarg);

    dbg("select_spy3(%p, %p)\n", itarg, menuarg);

    peers3 = g_strdup(gnet->peers3->str);
	while ((peer = z_tokenize(peers3, &tok)) != NULL){
		int tok2 = 0;
		id = z_tokenize(peer, &tok2);
		/*op =*/ z_tokenize(peer, &tok2);
		rwbands = z_tokenize(peer, &tok2);
        if (!rwbands) continue;

		if (menui == no){
			spypeer_add(id, '*', 1);
			return;
		}
		menui++;

		for (c = rwbands; *c != '\0'; c++){
            if (menui == no){
                spypeer_add(id, *c, 1);
                return;
            }
            menui++;
		}
	}
    g_free(peers3);

}

void spy3(void *xxx){
	int tok = 0, max = 0, menui = 0;
	char *peer, *id, *op, *rwbands, *c, *s;
	struct menu_item *mi = NULL;
	char *peers3;

	progress(NULL);

	if (ctest->oldcontest) {
		msg_box(NULL, VTEXT(T_ERROR),AL_CENTER,/*VTEXT*/VTEXT(T_OLD_TEST_NO_SPY),NULL,1, VTEXT(T_OK), NULL, B_ENTER |B_ESC);
		return;
	}

	peers3 = g_strdup(gnet->peers3->str);
	while ((peer = z_tokenize(peers3, &tok)) != NULL){
		int tok2 = 0;
		id = z_tokenize(peer, &tok2);
		op = z_tokenize(peer, &tok2);
		rwbands = z_tokenize(peer, &tok2);
        if (!rwbands) continue;

		if (!mi) mi = new_menu(3);
		s = g_strdup_printf("%-21s %7s %s", id, "*", op);
		if (strlen(s) > max) max = strlen(s);
		add_to_menu(&mi, s, "", "", select_spy3, GINT_TO_POINTER(menui), 0);
		menui++;

		for (c = rwbands; *c != '\0'; c++){
			struct band *b = find_band_by_bandchar(*c);
			if (!b) continue;
			if (!mi) mi = new_menu(3);

			s = g_strdup_printf("%-21s %7s %s", id, b->bandname, op);
			if (strlen(s) > max) max = strlen(s);
			add_to_menu(&mi, s, "", "", select_spy3, GINT_TO_POINTER(menui), 0);
            menui++;
		}
	}
    g_free(peers3);
    dbg("menui=%d\n");
	if (mi){
        set_window_ptr(gses->win, (term->x-max)/2,(term->y-2-menui)/2);
        do_menu(mi, NULL);
    }else
        errbox(VTEXT(T_NO_PEERS),0);
}

void menu_discover_peers3(void *itarg, void *menuarg){
	if (gnet->peers3) g_string_free(gnet->peers3, TRUE);
	gnet->peers3 = g_string_sized_new(256);
	progress(VTEXT(T_NETWORK_SCAN));
	rel_write_all("D3 \n");
	gnet->timer3_id = zselect_timer_new(zsel, 2000, (void (*)(void *))itarg, NULL);
}


void menu_contest_config_from_peer(void *arg){
    GString *gs;

    dbg("menu_contest_config_from_peer\n");

    if (cmp_sin(&gnet->global, &gnet->my)==0) { /* i'm master */
        int i;
        struct conn *tmpconn;
        struct zstring *zs;
        char *cdate, *pcall, *tname;

        /* LOOK ALSO net.c rel_write, dommand DC */

        CONDGFREE(gnet->allpeers);
        gs=g_string_sized_new(100);
        for (i=0;i<gnet->peers->len;i++){
            tmpconn = (struct conn *)g_ptr_array_index(gnet->peers,i);
            dbg("conn[%d]=%p %s\n", i, tmpconn, tcp_state_s(tmpconn));

            if (!conn_prod_state(tmpconn)) continue;
            if (!tmpconn->remote_ac) continue;
            dbg("remote_ac=%s\n", tmpconn->remote_ac);
            zs = zstrdup(tmpconn->remote_ac);
            cdate = ztokenize(zs, 1);
            pcall = ztokenize(zs, 0);
            tname = ztokenize(zs, 0);
            if (tname && *tname)
                g_string_append_printf(gs,"%s;%s %s %s;", tmpconn->remote_id, cdate, pcall, tname);
            zfree(zs);
        }
        dbg("allpeers=%s\n", gs->str);
        gnet->allpeers=g_strdup(gs->str);
        g_string_free(gs,TRUE);
        do_peer_operators_menu((void (*)(void*))arg);
        return;
    }

    /* i'm slave */
    if (!conn_prod_state(gnet->master)){
        errbox(VTEXT(T_NO_MASTER),0);
        return;
    }

    gnet->peerfunc = (PEER_FUNC)arg;
    rel_write(gnet->master, "DC\n");
}




static struct menu_item setup_menu[] = {
    {CTEXT(T_CTEST_DEF), "", CTEXT(T_HK_CTEST_DEF), MENU_FUNC contest_def, GINT_TO_POINTER(0), 0, 0},
    {CTEXT(T_BAND_DEF), ">", CTEXT(T_HK_BAND_DEF), MENU_FUNC menu_cfg_bands, menu_setup_band, 1, 0},
    {CTEXT(T_RESPOP), "", CTEXT(T_HK_RESPOP), MENU_FUNC menu_responsible_op, NULL, 0, 0},
    {CTEXT(T_CW_DAEMON), "", CTEXT(T_HK_CW_DAEMON), MENU_FUNC menu_cwda, NULL, 0, 0},
#ifdef HAVE_SNDFILE
    {CTEXT(T_AUDIO), "", CTEXT(T_HK_AUDIO), MENU_FUNC menu_ssbd, NULL, 0, 0},
#endif
    {CTEXT(T_CW_CQ), ">", CTEXT(T_HK_CW_CQ), MENU_FUNC menu_cq_cw, NULL, 1, 0},
    {CTEXT(T_SSB_CQ), ">", CTEXT(T_HK_SSB_CQ), MENU_FUNC menu_cq_ssb, NULL, 1, 0},
#ifdef HAVE_HAMLIB
    {CTEXT(T_RIGOPTS), ">", CTEXT(T_HK_RIGOPTS), MENU_FUNC menu_rigs, NULL, 1, 0},
#endif
    {CTEXT(T_ROTAROPTS), ">", CTEXT(T_HK_ROTAROPTS), MENU_FUNC menu_rotars, NULL, 1, 0},
    {CTEXT(T_NETWORK), "", CTEXT(T_HK_NETWORK), MENU_FUNC menu_network, NULL, 0, 0},
    {CTEXT(T_MISCOPTS), "", CTEXT(T_HK_MISCOPTS), MENU_FUNC misc_opts, NULL, 0, 0},
    //{CTEXT(T_TERMINAL_OPTIONS), "", CTEXT(T_HK_TERMINAL_OPTIONS), MENU_FUNC terminal_options, NULL, 0, 0},
    {CTEXT(T_HTTPD_OPTIONS)/*CTEXT(T_TERMINAL_OPTIONS)*/, "", CTEXT(T_HK_HTTP_OPTIONS)/*CTEXT(T_HK_TERMINAL_OPTIONS)*/, MENU_FUNC menu_httpd_opts, NULL, 0, 0},
    {CTEXT(T_AC_OPTIONS)/*CTEXT(T_TERMINAL_OPTIONS)*/, "", CTEXT(T_HK_AC_OPTIONS)/*CTEXT(T_HK_TERMINAL_OPTIONS)*/, MENU_FUNC menu_ac_opts, NULL, 0, 0},
#if defined(HAVE_ALSA) || defined (HAVE_PORTAUDIO)
    {CTEXT(T_SDR_OPTIONS)/*CTEXT(T_TERMINAL_OPTIONS)*/, "", CTEXT(T_HK_SDR_OPTIONS)/*CTEXT(T_HK_TERMINAL_OPTIONS)*/, MENU_FUNC menu_sdr_opts, NULL, 0, 0},
#endif
    {CTEXT(T_RAIN_OPTIONS), "", CTEXT(T_HK_RAIN_OPTIONS), menu_rain_opts, NULL, 0, 0},
    {CTEXT(T_LANGUAGE), ">", CTEXT(T_HK_LANGUAGE), MENU_FUNC menu_language_list, NULL, 1, 0},
    //{CTEXT(T_CHARACTER_SET), ">", CTEXT(T_HK_CHARACTER_SET), MENU_FUNC charset_list, GINT_TO_POINTER(1), 1, 0},
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_LOAD_CFG_NET), "", CTEXT(T_HK_LOAD_CFG_NET), MENU_FUNC menu_load_from_peer, send_config_request, 0, 0},/* todo */
    {CTEXT(T_LOAD_CW_NET), "", CTEXT(T_HK_LOAD_CW_NET), MENU_FUNC menu_load_from_peer, send_cwdb_request, 0, 0},/* todo */
#ifndef AUTOSAVE
    {"", "", M_BAR, NULL, NULL, 0, 0},
    {CTEXT(T_SAVE_CFG), "", CTEXT(T_HK_SAVE_CFG), MENU_FUNC menu_save_rc, NULL, 0, 0},
#endif
    {NULL, NULL, 0, NULL, NULL, 0, 0}
};

void do_setup_menu(void *arg)
{
    do_menu(setup_menu, NULL);
}

static struct menu_item main_menu[] = {
    {CTEXT(T_CONTEST), "", CTEXT(T_HK_CONTEST), MENU_FUNC do_contest_menu, NULL, 1, 1},
    {CTEXT(T_FILE), "", CTEXT(T_HK_FILE), MENU_FUNC do_file_menu, NULL, 1, 1},
    {CTEXT(T_EDIT), "", CTEXT(T_HK_EDIT), MENU_FUNC do_edit_menu, NULL, 1, 1},
    {CTEXT(T_BANDS), "", CTEXT(T_HK_BANDS), MENU_FUNC menu_bands, menu_activate_band, 1, 1},
    {CTEXT(T_SUBWINS), "", CTEXT(T_HK_SUBWINS), MENU_FUNC subwins_menu, NULL, 1, 1},
    {CTEXT(T_SETUP), "", CTEXT(T_HK_SETUP), MENU_FUNC do_setup_menu, NULL, 1, 1},
    {CTEXT(T_HELP), "", CTEXT(T_HK_HELP), MENU_FUNC do_menu, help_menu, 1, 1},
    {NULL, NULL, NULL, NULL, NULL, 0, 0}
};

void activate_bfu_technology(int item)
{
#ifdef Z_HAVE_SDL
    if (sdl) fill_lastarea(gses->ontop->x - 1, gses->ontop->y - 1, gses->ontop->w + 2, gses->ontop->h + 2, 0);
#endif
    do_mainmenu(main_menu, NULL, item);
}

/*struct history file_history = { 0, {&file_history.items, &file_history.items} };
struct history search_history = { 0, {&search_history.items, &search_history.items} };
  */
static struct history load_swap_history = { 0, {&load_swap_history.items, &load_swap_history.items }};


void free_history_lists(void)
{
   /* free_list(file_history.items);
    free_list(search_history.items);*/

    free_list(load_swap_history.items);
}


/***************************** LOAD SWAP ***********************************/

#if 0

void load_swap(char *text){
    FILE *f;

    f = fopen(text, "rt");
    if (!f){
        msg_box(term, NULL, VTEXT(T_ERROR), AL_CENTER, VTEXT(T_CANT_READ),
                NULL, 1, VTEXT(T_OK), NULL, B_ENTER | B_ESC);
        return;
    }

    add_qsos_from_swap(aband, f);
    fclose(f);

}


void menu_load_swap(void *arg){
    input_field(ses->term, NULL, "Load swap", "Enter filename",
            VTEXT(T_OK), VTEXT(T_CANCEL), ses, &load_swap_history,
            MAX_INPUT_URL_LEN, "", 0, 0, NULL,
            load_swap, NULL);
}
#endif


#ifdef HAVE_SNDFILE
void menu_play_last(void *arg){
    ssbd_play_last_sample(gssbd, NULL);
}
#endif

void menu_break_record(void *arg){
    cq_abort(1);
}


void menu_extcq(void *arg){
    if (!gses) return;
    gses->extcq = (enum extcq)GPOINTER_TO_INT(arg);
}

