// ---------------------------------------------------------------------------- // // fl_digi.cxx // // Copyright (C) 2006 // Dave Freese, W1HKJ // // This file is part of fldigi. // // fldigi is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // fldigi is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with fldigi; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ---------------------------------------------------------------------------- #include #include #ifndef __CYGWIN__ # include # include #endif #ifdef __CYGWIN__ # include #endif #include #include #include "gettext.h" #include "fl_digi.h" #include #include #include #include #include #include #include #include #include #include #include #include "waterfall.h" #include "raster.h" #include "progress.h" #include "afcind.h" #include "rigdialog.h" #include "main.h" #include "threads.h" #include "trx.h" #if USE_HAMLIB #include "hamlib.h" #endif #include "rigio.h" #include "rigMEM.h" #include "psk.h" #include "cw.h" #include "mfsk.h" #include "mt63.h" #include "rtty.h" #include "olivia.h" #include "thor.h" #include "dominoex.h" #include "feld.h" #include "throb.h" #include "wwv.h" #include "analysis.h" #include "ascii.h" #include "globals.h" #include "misc.h" //#include "help.h" #include "confdialog.h" #include "configuration.h" #include "colorsfonts.h" #include "status.h" #include "macros.h" #include "macroedit.h" #include "logger.h" #include "lookupcall.h" #include "font_browser.h" #include "icons.h" #include "status.h" #include "rigsupport.h" #include "qrunner.h" #include "Viewer.h" #include "soundconf.h" #include "htmlstrings.h" #if USE_XMLRPC # include "xmlrpc.h" #endif #include "debug.h" #include "re.h" #include "network.h" #include "spot.h" Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0; Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)0; Fl_Double_Window *scopeview = (Fl_Double_Window *)0; MixerBase* mixer = 0; //bool useCheckButtons; Fl_Group *mnuFrame; Fl_Menu_Bar *mnu; Fl_Light_Button *btnAutoSpot = (Fl_Light_Button *)0; Fl_Light_Button *btnTune = (Fl_Light_Button *)0; Fl_Light_Button *btnRSID = (Fl_Light_Button *)0; Fl_Button *btnMacroTimer; Fl_Button *btnMacroDummy; Fl_Tile_check *TiledGroup = 0; FTextView *ReceiveText = 0; FTextEdit *TransmitText = 0; Raster *FHdisp; Fl_Box *StatusBar = (Fl_Box *)0; Fl_Box *Status2 = (Fl_Box *)0; Fl_Box *Status1 = (Fl_Box *)0; Fl_Box *WARNstatus = (Fl_Box *)0; Fl_Button *MODEstatus = (Fl_Button *)0; Fl_Button *btnMacro[NUMMACKEYS]; Fl_Button *btnAltMacros; Fl_Button *btn_afconoff; Fl_Button *btn_sqlonoff; Fl_Input *inpFreq; Fl_Input *inpTime; Fl_Input *inpCall; Fl_Input *inpName; Fl_Input *inpRstIn; Fl_Input *inpRstOut; Fl_Input *inpQth; Fl_Input *inpLoc; Fl_Input *inpCnty; Fl_Input *inpSerNo; Fl_Input *inpVEprov; Fl_Multiline_Input *inpNotes; Fl_Input *inpAZ; // WA5ZNU Fl_Button *qsoTime; Fl_Button *qsoClear; Fl_Button *qsoSave; Fl_Box *txtRigName = (Fl_Box *)0; cFreqControl *qsoFreqDisp = (cFreqControl *)0; Fl_ComboBox *qso_opMODE = (Fl_ComboBox *)0; Fl_ComboBox *qso_opBW = (Fl_ComboBox *)0; Fl_Button *qso_opPICK = (Fl_Button *)0; Fl_Group *TopFrame = (Fl_Group *)0; Fl_Group *RigControlFrame = (Fl_Group *)0; Fl_Group *RigViewerFrame = (Fl_Group *)0; Fl_Group *QsoInfoFrame = (Fl_Group *)0; Fl_Group *QsoInfoFrame1 = (Fl_Group *)0; Fl_Group *QsoInfoFrameLeft = (Fl_Group *)0; Fl_Group *QsoInfoFrameCenter = (Fl_Group *)0; Fl_Group *QsoInfoFrameRight = (Fl_Group *)0; Fl_Group *QsoInfoFrame2 = (Fl_Group *)0; Fl_Group *QsoButtonFrame = (Fl_Group *)0; Fl_Browser *qso_opBrowser = (Fl_Browser *)0; Fl_Button *qso_btnAddFreq = (Fl_Button *)0; Fl_Button *qso_btnSelFreq = (Fl_Button *)0; Fl_Button *qso_btnDelFreq = (Fl_Button *)0; Fl_Button *qso_btnClearList = (Fl_Button *)0; Fl_Button *btnQRZ; Fl_Group *MixerFrame; Fl_Value_Slider *valRcvMixer; Fl_Value_Slider *valXmtMixer; AFCind *AFCindicator; #define FREQWIDTH 172 // FREQWIDTH should be a multiple of 9 + 10 #define FREQHEIGHT 30 #define BTNWIDTH 30 int pad = 1; //wSpace; int x_qsoframe = BTNWIDTH; int w_inpFreq = 80; int w_inpTime = 38; int w_qsoTime = 24; int w_inpCall = 120; int w_inpName = 60; int w_inpRstIn = 30; int w_inpRstOut = 30; int w_inpSerNo = 40; int wf1 = pad + w_inpFreq + pad + w_inpTime + w_qsoTime + pad + w_inpCall + pad + w_inpName + pad + w_inpRstIn + pad + w_inpRstOut + pad + w_inpSerNo; int w_fm1 = 25; int w_fm2 = 20; int w_fm3 = 20; int w_fm4 = 25; int w_fm5 = 20; int w_inpCnty = 90; int w_inpProv = 30; int w_inpLOC = 65; int w_inpAZ = 30; int w_inpQth = wf1 - w_fm1 - w_fm2 - w_fm3 - w_fm4 - w_fm5 - w_inpCnty - w_inpProv - w_inpLOC - w_inpAZ; int qh = Hqsoframe / 2; int rig_control_width = FREQWIDTH + 4; int altMacros = 0; bool bSaveFreqList = false; string strMacroName[NUMMACKEYS]; waterfall *wf = (waterfall *)0; Digiscope *digiscope = (Digiscope *)0; Digiscope *wfscope = (Digiscope *)0; Fl_Slider *sldrSquelch = (Fl_Slider *)0; Progress *pgrsSquelch = (Progress *)0; Fl_RGB_Image *feld_image = 0; Fl_Pixmap *addrbookpixmap = 0; Fl_Pixmap *closepixmap = 0; #if !defined(__APPLE__) && !defined(__CYGWIN__) Pixmap fldigi_icon_pixmap; #endif int IMAGE_WIDTH; int Hwfall; int HNOM; int WNOM; int Wwfall; bool clean_exit(void); void cb_init_mode(Fl_Widget *, void *arg); void cb_oliviaA(Fl_Widget *w, void *arg); void cb_oliviaB(Fl_Widget *w, void *arg); void cb_oliviaC(Fl_Widget *w, void *arg); void cb_oliviaCustom(Fl_Widget *w, void *arg); void cb_rtty45(Fl_Widget *w, void *arg); void cb_rtty50(Fl_Widget *w, void *arg); void cb_rtty75(Fl_Widget *w, void *arg); void cb_rttyCustom(Fl_Widget *w, void *arg); Fl_Widget *modem_config_tab; Fl_Menu_Item *quick_change; Fl_Menu_Item quick_change_psk[] = { { mode_info[MODE_BPSK31].name, 0, cb_init_mode, (void *)MODE_BPSK31 }, { mode_info[MODE_PSK63].name, 0, cb_init_mode, (void *)MODE_PSK63 }, { mode_info[MODE_PSK125].name, 0, cb_init_mode, (void *)MODE_PSK125 }, { mode_info[MODE_PSK250].name, 0, cb_init_mode, (void *)MODE_PSK250 }, { 0 } }; Fl_Menu_Item quick_change_qpsk[] = { { mode_info[MODE_QPSK31].name, 0, cb_init_mode, (void *)MODE_QPSK31 }, { mode_info[MODE_QPSK63].name, 0, cb_init_mode, (void *)MODE_QPSK63 }, { mode_info[MODE_QPSK125].name, 0, cb_init_mode, (void *)MODE_QPSK125 }, { mode_info[MODE_QPSK250].name, 0, cb_init_mode, (void *)MODE_QPSK250 }, { 0 } }; Fl_Menu_Item quick_change_mfsk[] = { { mode_info[MODE_MFSK4].name, 0, cb_init_mode, (void *)MODE_MFSK4 }, { mode_info[MODE_MFSK8].name, 0, cb_init_mode, (void *)MODE_MFSK8 }, { mode_info[MODE_MFSK16].name, 0, cb_init_mode, (void *)MODE_MFSK16 }, { mode_info[MODE_MFSK11].name, 0, cb_init_mode, (void *)MODE_MFSK11 }, { mode_info[MODE_MFSK22].name, 0, cb_init_mode, (void *)MODE_MFSK22 }, { mode_info[MODE_MFSK31].name, 0, cb_init_mode, (void *)MODE_MFSK31 }, { mode_info[MODE_MFSK32].name, 0, cb_init_mode, (void *)MODE_MFSK32 }, { mode_info[MODE_MFSK64].name, 0, cb_init_mode, (void *)MODE_MFSK64 }, { 0 } }; Fl_Menu_Item quick_change_mt63[] = { { mode_info[MODE_MT63_500].name, 0, cb_init_mode, (void *)MODE_MT63_500 }, { mode_info[MODE_MT63_1000].name, 0, cb_init_mode, (void *)MODE_MT63_1000 }, { mode_info[MODE_MT63_2000].name, 0, cb_init_mode, (void *)MODE_MT63_2000 }, { 0 } }; Fl_Menu_Item quick_change_thor[] = { { mode_info[MODE_THOR4].name, 0, cb_init_mode, (void *)MODE_THOR4 }, { mode_info[MODE_THOR5].name, 0, cb_init_mode, (void *)MODE_THOR5 }, { mode_info[MODE_THOR8].name, 0, cb_init_mode, (void *)MODE_THOR8 }, { mode_info[MODE_THOR11].name, 0, cb_init_mode, (void *)MODE_THOR11 }, { mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16 }, { mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22 }, { 0 } }; Fl_Menu_Item quick_change_domino[] = { { mode_info[MODE_DOMINOEX4].name, 0, cb_init_mode, (void *)MODE_DOMINOEX4 }, { mode_info[MODE_DOMINOEX5].name, 0, cb_init_mode, (void *)MODE_DOMINOEX5 }, { mode_info[MODE_DOMINOEX8].name, 0, cb_init_mode, (void *)MODE_DOMINOEX8 }, { mode_info[MODE_DOMINOEX11].name, 0, cb_init_mode, (void *)MODE_DOMINOEX11 }, { mode_info[MODE_DOMINOEX16].name, 0, cb_init_mode, (void *)MODE_DOMINOEX16 }, { mode_info[MODE_DOMINOEX22].name, 0, cb_init_mode, (void *)MODE_DOMINOEX22 }, { 0 } }; Fl_Menu_Item quick_change_feld[] = { { mode_info[MODE_FELDHELL].name, 0, cb_init_mode, (void *)MODE_FELDHELL }, { mode_info[MODE_SLOWHELL].name, 0, cb_init_mode, (void *)MODE_SLOWHELL }, { mode_info[MODE_HELLX5].name, 0, cb_init_mode, (void *)MODE_HELLX5 }, { mode_info[MODE_HELLX9].name, 0, cb_init_mode, (void *)MODE_HELLX9 }, { mode_info[MODE_FSKHELL].name, 0, cb_init_mode, (void *)MODE_FSKHELL }, { mode_info[MODE_FSKH105].name, 0, cb_init_mode, (void *)MODE_FSKH105 }, { mode_info[MODE_HELL80].name, 0, cb_init_mode, (void *)MODE_HELL80 }, { 0 } }; Fl_Menu_Item quick_change_throb[] = { { mode_info[MODE_THROB1].name, 0, cb_init_mode, (void *)MODE_THROB1 }, { mode_info[MODE_THROB2].name, 0, cb_init_mode, (void *)MODE_THROB2 }, { mode_info[MODE_THROB4].name, 0, cb_init_mode, (void *)MODE_THROB4 }, { mode_info[MODE_THROBX1].name, 0, cb_init_mode, (void *)MODE_THROBX1 }, { mode_info[MODE_THROBX2].name, 0, cb_init_mode, (void *)MODE_THROBX2 }, { mode_info[MODE_THROBX4].name, 0, cb_init_mode, (void *)MODE_THROBX4 }, { 0 } }; Fl_Menu_Item quick_change_olivia[] = { { "8/500", 0, cb_oliviaA, (void *)MODE_OLIVIA }, { "16/500", 0, cb_oliviaB, (void *)MODE_OLIVIA }, { "32/1000", 0, cb_oliviaC, (void *)MODE_OLIVIA }, { "Custom", 0, cb_oliviaCustom, (void *)MODE_OLIVIA }, { 0 } }; Fl_Menu_Item quick_change_rtty[] = { { "RTTY-45", 0, cb_rtty45, (void *)MODE_RTTY }, { "RTTY-50", 0, cb_rtty50, (void *)MODE_RTTY }, { "RTTY-75", 0, cb_rtty75, (void *)MODE_RTTY }, { "Custom", 0, cb_rttyCustom, (void *)MODE_RTTY }, { 0 } }; void set_olivia_tab_widgets() { mnuOlivia_Bandwidth->value(progdefaults.oliviabw); mnuOlivia_Tones->value(progdefaults.oliviatones); } void cb_oliviaA(Fl_Widget *w, void *arg) { progdefaults.oliviatones = 2; progdefaults.oliviabw = 2; set_olivia_tab_widgets(); cb_init_mode(w, arg); } void cb_oliviaB(Fl_Widget *w, void *arg) { progdefaults.oliviatones = 3; progdefaults.oliviabw = 2; set_olivia_tab_widgets(); cb_init_mode(w, arg); } void cb_oliviaC(Fl_Widget *w, void *arg) { progdefaults.oliviatones = 4; progdefaults.oliviabw = 3; set_olivia_tab_widgets(); cb_init_mode(w, arg); } void cb_oliviaCustom(Fl_Widget *w, void *arg) { modem_config_tab = tabOlivia; tabsConfigure->value(tabModems); tabsModems->value(modem_config_tab); dlgConfig->show(); cb_init_mode(w, arg); } void set_rtty_tab_widgets() { progdefaults.rtty_parity = 0; progdefaults.rtty_stop = 1; selShift->value(progdefaults.rtty_shift); selBits->value(progdefaults.rtty_bits); selBaud->value(progdefaults.rtty_baud); selParity->value(progdefaults.rtty_parity); selStopBits->value(progdefaults.rtty_stop); } void cb_rtty45(Fl_Widget *w, void *arg) { progdefaults.rtty_baud = 1; progdefaults.rtty_bits = 0; progdefaults.rtty_shift = 3; set_rtty_tab_widgets(); cb_init_mode(w, arg); } void cb_rtty50(Fl_Widget *w, void *arg) { progdefaults.rtty_baud = 2; progdefaults.rtty_bits = 0; progdefaults.rtty_shift = 3; set_rtty_tab_widgets(); cb_init_mode(w, arg); } void cb_rtty75(Fl_Widget *w, void *arg) { progdefaults.rtty_baud = 4; progdefaults.rtty_bits = 0; progdefaults.rtty_shift = 9; set_rtty_tab_widgets(); cb_init_mode(w, arg); } void cb_rttyCustom(Fl_Widget *w, void *arg) { modem_config_tab = tabRTTY; tabsConfigure->value(tabModems); tabsModems->value(modem_config_tab); dlgConfig->show(); cb_init_mode(w, arg); } void startup_modem(modem *m) { trx_start_modem(m); restoreFocus(); FL_LOCK_D(); if (m == feld_modem || m == feld_slowmodem || m == feld_x5modem || m == feld_x9modem || m == feld_FMmodem || m == feld_FM105modem || m == feld_80modem ) { ReceiveText->hide(); FHdisp->show(); sldrHellBW->value(m->get_bandwidth()); progdefaults.HELL_BW = m->get_bandwidth(); } else { ReceiveText->show(); FHdisp->hide(); } if (m->get_cap() & modem::CAP_AFC) { btn_afconoff->value(progStatus.afconoff); btn_afconoff->activate(); } else { btn_afconoff->value(0); btn_afconoff->deactivate(); } wf->btnRev->value(wf->Reverse()); if (m->get_cap() & modem::CAP_REV) { wf->btnRev->value(wf->Reverse()); wf->btnRev->activate(); } else { wf->btnRev->value(0); wf->btnRev->deactivate(); } FL_UNLOCK_D(); FL_AWAKE_D(); } void cb_mnuOpenMacro(Fl_Menu_*, void*) { macros.openMacroFile(); restoreFocus(); } void cb_mnuSaveMacro(Fl_Menu_*, void*) { macros.saveMacroFile(); restoreFocus(); } void cb_E(Fl_Menu_*, void*) { fl_digi_main->do_callback(); } void cb_wMain(Fl_Widget*, void*) { if (!clean_exit()) return; // hide all shown windows Fl::first_window(fl_digi_main); for (Fl_Window* w = Fl::next_window(fl_digi_main); w; w = Fl::next_window(w)) { w->do_callback(); w = fl_digi_main; } // this will make Fl::run return fl_digi_main->hide(); } void init_modem(trx_mode mode) { ENSURE_THREAD(FLMAIN_TID); quick_change = 0; modem_config_tab = tabsModems->child(0); switch (mode) { case MODE_NEXT: if ((mode = active_modem->get_mode() + 1) == NUM_MODES) mode = 0; return init_modem(mode); case MODE_PREV: if ((mode = active_modem->get_mode() - 1) < 0) mode = NUM_MODES - 1; return init_modem(mode); case MODE_CW: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new cw); modem_config_tab = tabCW; break; case MODE_THOR4: case MODE_THOR5: case MODE_THOR8: case MODE_THOR11:case MODE_THOR16: case MODE_THOR22: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new thor(mode)); quick_change = quick_change_thor; modem_config_tab = tabTHOR; break; case MODE_DOMINOEX4: case MODE_DOMINOEX5: case MODE_DOMINOEX8: case MODE_DOMINOEX11: case MODE_DOMINOEX16: case MODE_DOMINOEX22: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new dominoex(mode)); quick_change = quick_change_domino; modem_config_tab = tabDomEX; break; case MODE_FELDHELL: case MODE_SLOWHELL: case MODE_HELLX5: case MODE_HELLX9: case MODE_FSKHELL: case MODE_FSKH105: case MODE_HELL80: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new feld(mode)); quick_change = quick_change_feld; modem_config_tab = tabFeld; break; case MODE_MFSK4: case MODE_MFSK11: case MODE_MFSK22: case MODE_MFSK31: case MODE_MFSK64: case MODE_MFSK8: case MODE_MFSK16: case MODE_MFSK32: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new mfsk(mode)); quick_change = quick_change_mfsk; break; case MODE_MT63_500: case MODE_MT63_1000: case MODE_MT63_2000 : startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new mt63(mode)); quick_change = quick_change_mt63; modem_config_tab = tabMT63; break; case MODE_BPSK31: case MODE_PSK63: case MODE_PSK125: case MODE_PSK250: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new psk(mode)); quick_change = quick_change_psk; modem_config_tab = tabPSK; break; case MODE_QPSK31: case MODE_QPSK63: case MODE_QPSK125: case MODE_QPSK250: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new psk(mode)); quick_change = quick_change_qpsk; modem_config_tab = tabPSK; break; case MODE_OLIVIA: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new olivia); modem_config_tab = tabOlivia; quick_change = quick_change_olivia; break; case MODE_RTTY: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new rtty(mode)); modem_config_tab = tabRTTY; quick_change = quick_change_rtty; break; case MODE_THROB1: case MODE_THROB2: case MODE_THROB4: case MODE_THROBX1: case MODE_THROBX2: case MODE_THROBX4: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new throb(mode)); quick_change = quick_change_throb; break; case MODE_WWV: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new wwv); break; case MODE_ANALYSIS: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new anal); break; default: LOG_ERROR("Unknown mode: %" PRIdPTR, mode); return init_modem(MODE_BPSK31); } clear_StatusMessages(); progStatus.lastmode = mode; if (wf->xmtlock->value() == 1 && !mailserver) { wf->xmtlock->value(0); wf->xmtlock->damage(); active_modem->set_freqlock(false); } } void init_modem_sync(trx_mode m) { ENSURE_THREAD(FLMAIN_TID); if (trx_state != STATE_RX) TRX_WAIT(STATE_RX, abort_tx()); TRX_WAIT(STATE_RX, init_modem(m)); REQ_FLUSH(TRX_TID); } void cb_init_mode(Fl_Widget *, void *mode) { init_modem(reinterpret_cast(mode)); } void restoreFocus() { FL_LOCK_D(); TransmitText->take_focus(); FL_UNLOCK_D(); FL_AWAKE_D(); } void macro_cb(Fl_Widget *w, void *v) { stopMacroTimer(); int b = (int)(reinterpret_cast (v)); b += altMacros * NUMMACKEYS; int mouse = Fl::event_button(); if (mouse == 1 && !macros.text[b].empty()) macros.execute(b); else if (mouse == 3) editMacro(b); restoreFocus(); } void colorize_macro(int i) { if (progdefaults.useGroupColors == true) { if (i < NUMKEYROWS){ btnMacro[i]->color(fl_rgb_color( progdefaults.btnGroup1.R, progdefaults.btnGroup1.G, progdefaults.btnGroup1.B)); } else if (i < 8) { btnMacro[i]->color(fl_rgb_color( progdefaults.btnGroup2.R, progdefaults.btnGroup2.G, progdefaults.btnGroup2.B)); } else { btnMacro[i]->color(fl_rgb_color( progdefaults.btnGroup3.R, progdefaults.btnGroup3.G, progdefaults.btnGroup3.B)); } btnMacro[i]->labelcolor( fl_rgb_color( progdefaults.btnFkeyTextColor.R, progdefaults.btnFkeyTextColor.G, progdefaults.btnFkeyTextColor.B )); } else { btnMacro[i]->color(FL_BACKGROUND_COLOR); btnMacro[i]->labelcolor(FL_FOREGROUND_COLOR); } } void colorize_macros() { FL_LOCK_D(); for (int i = 0; i < NUMMACKEYS; i++) { colorize_macro(i); btnMacro[i]->redraw_label(); } FL_UNLOCK_D(); } void altmacro_cb(Fl_Widget *w, void *v) { static char alt_text[NUMKEYROWS]; intptr_t arg = reinterpret_cast(v); if (arg) altMacros += arg; else altMacros = altMacros + (Fl::event_button() == FL_RIGHT_MOUSE ? -1 : 1); altMacros = WCLAMP(altMacros, 0, 3); snprintf(alt_text, sizeof(alt_text), "%d", altMacros + 1); FL_LOCK_D(); for (int i = 0; i < NUMMACKEYS; i++) btnMacro[i]->label(macros.name[i + (altMacros * NUMMACKEYS)].c_str()); btnAltMacros->label(alt_text); btnAltMacros->redraw_label(); FL_UNLOCK_D(); restoreFocus(); } void cb_mnuConfigOperator(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabOperator); dlgConfig->show(); } void cb_mnuConfigWaterfall(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabWaterfall); dlgConfig->show(); } void cb_mnuConfigID(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabID); dlgConfig->show(); } void cb_mnuConfigQRZ(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabQRZ); dlgConfig->show(); } void cb_mnuConfigMisc(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabMisc); dlgConfig->show(); } void cb_mnuUI(Fl_Menu_*, void *) { progdefaults.loadDefaults(); tabsConfigure->value(tabUI); dlgConfig->show(); } void cb_mnuConfigRigCtrl(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabRig); dlgConfig->show(); } void cb_mnuConfigSoundCard(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabSoundCard); dlgConfig->show(); } void cb_mnuConfigModems(Fl_Menu_*, void*) { progdefaults.loadDefaults(); tabsConfigure->value(tabModems); dlgConfig->show(); } #if USE_SNDFILE bool capval = false; bool genval = false; bool playval = false; void cb_mnuCapture(Fl_Widget *w, void *d) { Fl_Menu_Item *m = (Fl_Menu_Item *)(((Fl_Menu_*)w)->mvalue()); if (!scard) return; if (playval || genval) { m->flags &= ~FL_MENU_VALUE; return; } capval = m->value(); if(!scard->Capture(capval)) { m->flags &= ~FL_MENU_VALUE; capval = false; } } void cb_mnuGenerate(Fl_Widget *w, void *d) { Fl_Menu_Item *m = (Fl_Menu_Item *)(((Fl_Menu_*)w)->mvalue()); if (!scard) return; if (capval || playval) { m->flags &= ~FL_MENU_VALUE; return; } genval = m->value(); if (!scard->Generate(genval)) { m->flags &= ~FL_MENU_VALUE; genval = false; } } void cb_mnuPlayback(Fl_Widget *w, void *d) { Fl_Menu_Item *m = (Fl_Menu_Item *)(((Fl_Menu_*)w)->mvalue()); if (!scard) return; if (capval || genval) { m->flags &= ~FL_MENU_VALUE; return; } playval = m->value(); if(!scard->Playback(playval)) { m->flags &= ~FL_MENU_VALUE; playval = false; } else if (btnAutoSpot->value()) { put_status("Spotting disabled", 3.0); btnAutoSpot->value(0); btnAutoSpot->do_callback(); } } #endif // USE_SNDFILE void cb_mnuConfigFonts(Fl_Menu_*, void *) { selectColorsFonts(); } void cb_mnuSaveConfig(Fl_Menu_ *, void *) { progdefaults.saveDefaults(); restoreFocus(); } void cb_mnuVisitURL(Fl_Widget*, void* arg) { const char* url = reinterpret_cast(arg); #ifndef __CYGWIN__ # ifdef __APPLE__ const char* browsers[] = { "open" }; # else const char* browsers[] = { "xdg-open", getenv("BROWSER"), "sensible-brower", "firefox", "mozilla" }; # endif switch (fork()) { case 0: for (size_t i = 0; i < sizeof(browsers)/sizeof(browsers[0]); i++) if (browsers[i]) execlp(browsers[i], browsers[i], url, (char*)0); LOG_PERROR("Could not execute a web browser"); exit(EXIT_FAILURE); case -1: fl_alert(_("Could not run a web browser:\n%s\n\n" "Open this URL manually:\n%s"), strerror(errno), url); } #else // gurgle... gurgle... HOWL // "The return value is cast as an HINSTANCE for backward // compatibility with 16-bit Windows applications. It is // not a true HINSTANCE, however. The only thing that can // be done with the returned HINSTANCE is to cast it to an // int and compare it with the value 32 or one of the error // codes below." (Error codes omitted to preserve sanity). if ((int)ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL) <= 32) fl_alert(_("Could not open url:\n%s\n"), url); #endif restoreFocus(); } void cb_mnuVisitPSKRep(Fl_Widget*, void*) { cb_mnuVisitURL(0, (void*)string("http://pskreporter.info/pskmap?").append(progdefaults.myCall).c_str()); } void html_help( const string &Html) { if (!help_dialog) help_dialog = new Fl_Help_Dialog; help_dialog->value(Html.c_str()); help_dialog->show(); restoreFocus(); } void cb_mnuBeginnersURL(Fl_Widget*, void*) { string deffname = HomeDir; deffname.append("beginners.html"); ofstream f(deffname.c_str()); if (!f) return; f << szBeginner; f.close(); #ifndef __CYGWIN__ cb_mnuVisitURL(NULL, (void *)deffname.insert(0, "file://").c_str()); #else cb_mnuVisitURL(NULL, (void *)deffname.c_str()); #endif } void cb_mnuCheckUpdate(Fl_Widget* w, void*) { struct { const char* url; const char* re; string version_str; long version; } sites[] = { { PACKAGE_HOME, "fldigi-distro/fldigi-([0-9.]+).tar.gz", "", 0 }, { PACKAGE_PROJ, "fldigi/fldigi-([0-9.]+).tar.gz", "", 0 } }, *latest; string reply; w->window()->cursor(FL_CURSOR_WAIT); put_status(_("Checking for updates...")); for (size_t i = 0; i < sizeof(sites)/sizeof(*sites); i++) { // fetch .url, grep for .re Fl::check(); reply.clear(); if (!fetch_http(sites[i].url, reply, 20.0)) continue; re_t re(sites[i].re, REG_EXTENDED | REG_ICASE | REG_NEWLINE); if (!re.match(reply.c_str()) || re.nsub() != 2) continue; sites[i].version = ver2int((sites[i].version_str = re.submatch(1)).c_str()); } w->window()->cursor(FL_CURSOR_DEFAULT); put_status(""); latest = sites[1].version > sites[0].version ? &sites[1] : &sites[0]; if (sites[0].version == 0 && sites[1].version == 0) { fl_message(_("Could not check for updates:\n%s"), reply.c_str()); return; } if (latest->version > ver2int(PACKAGE_VERSION)) { switch (fl_choice(_("Version %s is available at\n\n%s\n\nWhat would you like to do?"), _("Close"), _("Visit URL"), _("Copy URL"), latest->version_str.c_str(), latest->url)) { case 1: cb_mnuVisitURL(NULL, (void*)latest->url); break; case 2: size_t n = strlen(latest->url); Fl::copy(latest->url, n, 0); Fl::copy(latest->url, n, 1); } } else fl_message(_("You are running the latest version")); } void cb_mnuAboutURL(Fl_Widget*, void*) { if (!help_dialog) help_dialog = new Fl_Help_Dialog; help_dialog->value(szAbout); help_dialog->show(); restoreFocus(); } void fldigi_help(const string& theHelp) { string htmlHelp = "" "" "" PACKAGE " Help" "" "" "" "

"; for (size_t i = 0; i < theHelp.length(); i++) { if (theHelp[i] == '\n') { if (theHelp[i+1] == '\n') { htmlHelp += "

"; i++; } else htmlHelp += "
"; } else if (theHelp[i] == ' ' && theHelp[i+1] == ' ') { htmlHelp += "  "; i++; } else htmlHelp += theHelp[i]; } htmlHelp += "

" "" ""; html_help(htmlHelp); } void cb_mnuCmdLineHelp(Fl_Widget*, void*) { extern string option_help; fldigi_help(option_help); restoreFocus(); } void cb_mnuBuildInfo(Fl_Widget*, void*) { extern string version_text; fldigi_help(version_text); restoreFocus(); } void cb_mnuDebug(Fl_Widget*, void*) { debug::show(); } #ifndef NDEBUG void cb_mnuFun(Fl_Widget*, void*) { fl_message(_("Sunspot creation underway!")); } #endif void cb_mnuAudioInfo(Fl_Widget*, void*) { if (progdefaults.btnAudioIOis != SND_IDX_PORT) { fl_alert(_("Audio device information is only available for the PortAudio backend")); return; } #if USE_PORTAUDIO size_t ndev; string devtext[2], headers[2]; SoundPort::devices_info(devtext[0], devtext[1]); if (devtext[0] != devtext[1]) { headers[0] = "Capture device"; headers[1] = "Playback device"; ndev = 2; } else { headers[0] = "Capture and playback devices"; ndev = 1; } string audio_info; for (size_t i = 0; i < ndev; i++) { audio_info.append("

").append(headers[i]).append("

\n\n"); string::size_type j, n = 0; while ((j = devtext[i].find(": ", n)) != string::npos) { audio_info.append("") .append(""); if ((n = devtext[i].find('\n', j)) == string::npos) { devtext[i] += '\n'; n = devtext[i].length() - 1; } audio_info.append("") .append("\n"); } audio_info.append("
") .append(devtext[i].substr(n, j-n)) .append("") .append(devtext[i].substr(j+2, n-j-2)) .append("

\n"); } fldigi_help(audio_info); #endif } void cb_ShowConfig(Fl_Widget*, void*) { cb_mnuVisitURL(0, (void*)HomeDir.c_str()); } void cbTune(Fl_Widget *w, void *) { Fl_Button *b = (Fl_Button *)w; if (active_modem == wwv_modem || active_modem == anal_modem) { b->value(0); return; } if (b->value() == 1) { b->labelcolor(FL_RED); trx_tune(); } else { b->labelcolor(FL_FOREGROUND_COLOR); trx_receive(); } restoreFocus(); } void cbRSID(Fl_Widget *w, void *) { if (trx_state == STATE_TX || trx_state == STATE_TUNE) { btnRSID->value(0); return; } if (progdefaults.rsid == true) { progdefaults.rsid = false; wf->xmtrcv->activate(); btnTune->activate(); } else { ReedSolomon->reset(); progdefaults.rsid = true; wf->xmtrcv->deactivate(); btnTune->deactivate(); } restoreFocus(); } void cbAutoSpot(Fl_Widget* w, void*) { progStatus.spot_recv = static_cast(w)->value(); } void toggleRSID() { btnRSID->value(0); cbRSID(NULL, NULL); } void cb_mnuDigiscope(Fl_Menu_ *w, void *d) { if (scopeview) scopeview->show(); } void cb_mnuRig(Fl_Menu_ *, void *) { if (!rigcontrol) createRigDialog(); rigcontrol->show(); } void cb_mnuViewer(Fl_Menu_ *, void *) { openViewer(); } void cb_mnuPicViewer(Fl_Menu_ *, void *) { if (picRxWin) { picRx->redraw(); picRxWin->show(); } } void closeRigDialog() { rigcontrol->hide(); } void cb_sldrSquelch(Fl_Slider* o, void*) { progStatus.sldrSquelchValue = o->value(); restoreFocus(); } const char *zuluTime() { time_t t; struct tm tm; static char logtime[5]; if ((t = time(NULL)) != (time_t)-1 && gmtime_r(&t, &tm) && strftime(logtime, sizeof(logtime), "%H%M", &tm)) return logtime; else return NULL; } bool oktoclear = true; void qsoTime_cb(Fl_Widget *b, void *) { string qsotime = zuluTime(); LOG_INFO(qsotime.c_str()); inpTime->value(qsotime.c_str()); // inpTime->value(zuluTime()); // oktoclear = false; restoreFocus(); } void clearQSO() { Fl_Input* in[] = { inpCall, inpName, inpRstIn, inpRstOut, inpQth, inpNotes, inpLoc, inpAZ, inpSerNo, inpVEprov, inpCnty }; for (size_t i = 0; i < sizeof(in)/sizeof(*in); i++) in[i]->value(""); inpTime->value(zuluTime()); } void cb_log(Fl_Widget*, void*) { oktoclear = false; } void showsizes() { std::cout << fl_digi_main->w() << std::endl; std::cout << fl_digi_main->h() << std::endl; std::cout << wf1 << std::endl; std::cout << QsoInfoFrame->x() << ", " << QsoInfoFrame->w() << std::endl; std::cout << QsoInfoFrame1->x() << ", " << QsoInfoFrame1->w() << std::endl; std::cout << QsoInfoFrame2->x() << ", " << QsoInfoFrame2->w() << std::endl; } void qsoClear_cb(Fl_Widget *b, void *) { // showsizes(); if (progdefaults.NagMe) { if (oktoclear || fl_choice(_("Clear log fields?"), _("Cancel"), _("OK"), NULL) == 1) { clearQSO(); oktoclear = true; } } else { clearQSO(); oktoclear = true; } restoreFocus(); } void qsoSave_cb(Fl_Widget *b, void *) { submit_log(); if (progdefaults.ClearOnSave) clearQSO(); oktoclear = true; restoreFocus(); } void cb_QRZ(Fl_Widget *b, void *) { if (!*inpCall->value()) return; switch (Fl::event_button()) { case FL_LEFT_MOUSE: CALLSIGNquery(); oktoclear = false; break; case FL_RIGHT_MOUSE: if (quick_choice(string("Spot \"").append(inpCall->value()).append("\"?").c_str(), false)) spot_manual(inpCall->value(), inpLoc->value()); break; default: break; } } void status_cb(Fl_Widget *b, void *arg) { if (Fl::event_button() == FL_RIGHT_MOUSE) { progdefaults.loadDefaults(); tabsConfigure->value(tabModems); tabsModems->value(modem_config_tab); dlgConfig->show(); } else { if (!quick_change) return; const Fl_Menu_Item *m; m = quick_change->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); if (m && m->callback_) m->do_callback(0); } } void afconoff_cb(Fl_Widget *w, void *vi) { FL_LOCK_D(); Fl_Button *b = (Fl_Button *)w; int v = b->value(); FL_UNLOCK_D(); progStatus.afconoff = v; } void sqlonoff_cb(Fl_Widget *w, void *vi) { FL_LOCK_D(); Fl_Button *b = (Fl_Button *)w; int v = b->value(); FL_UNLOCK_D(); progStatus.sqlonoff = v ? true : false; } void stopMacroTimer() { if (progdefaults.useTimer == false) return; progdefaults.useTimer = false; Fl::remove_timeout(macro_timer); FL_LOCK_D(); btnMacroTimer->hide(); btnMacroDummy->show(); FL_UNLOCK_D(); restoreFocus(); } void cbMacroTimerButton(Fl_Widget *w, void *d) { stopMacroTimer(); } void cb_RcvMixer(Fl_Widget *w, void *d) { progStatus.RcvMixer = valRcvMixer->value() / 100.0; mixer->setRcvGain(progStatus.RcvMixer); } void cb_XmtMixer(Fl_Widget *w, void *d) { progStatus.XmtMixer = valXmtMixer->value() / 100.0; mixer->setXmtLevel(progStatus.XmtMixer); } int default_handler(int event) { if (event != FL_SHORTCUT) return 0; if (Fl::event_key() == FL_Escape && Fl::event_inside(RigViewerFrame) && RigViewerFrame->visible()) { CloseQsoView(); return 1; } Fl_Widget* w = Fl::focus(); if (w == fl_digi_main || w->window() == fl_digi_main) { int key = Fl::event_key(); if (key == FL_Escape || (key >= FL_F && key <= FL_F_Last)) { TransmitText->take_focus(); TransmitText->handle(FL_KEYBOARD); w->take_focus(); // remove this to leave tx text focused return 1; } } return 0; } bool clean_exit(void) { arq_close(); if (progdefaults.changed) { switch (fl_choice(_("Save changed configuration before exiting?"), _("Cancel"), _("Save"), _("Don't save"))) { case 0: return false; case 1: progdefaults.saveDefaults(); // fall through case 2: break; } } if (!oktoclear && progdefaults.NagMe) { switch (fl_choice(_("Save log before exiting?"), _("Cancel"), _("Save"), _("Don't save"))) { case 0: return false; case 1: qsoSave_cb(0, 0); // fall through case 2: break; } } if (macros.changed) { switch (fl_choice(_("Save changed macros before exiting?"), _("Cancel"), _("Save"), _("Don't save"))) { case 0: return false; case 1: macros.saveMacroFile(); // fall through case 2: break; } } if (Maillogfile) Maillogfile->log_to_file_stop(); if (logfile) logfile->log_to_file_stop(); // if (bSaveFreqList) saveFreqList(); progStatus.saveLastState(); #if USE_HAMLIB hamlib_close(); #endif rigCAT_close(); rigMEM_close(); if (mixer) mixer->closeMixer(); if (trx_state == STATE_RX || trx_state == STATE_TX || trx_state == STATE_TUNE) trx_state = STATE_ABORT; else { LOG_ERROR("trx in unexpected state %d", trx_state); exit(1); } while (trx_state != STATE_ENDED) { REQ_FLUSH(GET_THREAD_ID()); MilliSleep(10); } if (dlgConfig) { dlgConfig->hide(); delete cboHamlibRig; delete dlgConfig; } #if USE_HAMLIB if (xcvr) delete xcvr; #endif #if USE_XMLRPC XML_RPC_Server::stop(); #endif return true; } Fl_Menu_Item menu_[] = { {_("&Files"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { make_icon_label(_("Open macros..."), file_open_icon), 0, (Fl_Callback*)cb_mnuOpenMacro, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Save macros..."), save_as_icon), 0, (Fl_Callback*)cb_mnuSaveMacro, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Show config"), folder_open_icon), 0, cb_ShowConfig, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, //{"Log File", 0, (Fl_Callback*)cb_mnuLogFile, 0, FL_MENU_DIVIDER | FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, {_("Log File"), 0, 0, 0, FL_MENU_DIVIDER | FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, #if USE_SNDFILE { make_icon_label(_("Audio")), 0, 0, 0, FL_MENU_DIVIDER | FL_SUBMENU, _FL_MULTI_LABEL, 0, 14, 0}, {_("Rx capture"), 0, (Fl_Callback*)cb_mnuCapture, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, {_("Tx generate"), 0, (Fl_Callback*)cb_mnuGenerate, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, {_("Playback"), 0, (Fl_Callback*)cb_mnuPlayback, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, #endif { make_icon_label(_("E&xit"), log_out_icon), 0, (Fl_Callback*)cb_E, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {_("Op &Mode"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_CW].name, 0, cb_init_mode, (void *)MODE_CW, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"DominoEX", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX4].name, 0, cb_init_mode, (void *)MODE_DOMINOEX4, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX5].name, 0, cb_init_mode, (void *)MODE_DOMINOEX5, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX8].name, 0, cb_init_mode, (void *)MODE_DOMINOEX8, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX11].name, 0, cb_init_mode, (void *)MODE_DOMINOEX11, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX16].name, 0, cb_init_mode, (void *)MODE_DOMINOEX16, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX22].name, 0, cb_init_mode, (void *)MODE_DOMINOEX22, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"Hell", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_FELDHELL].name, 0, cb_init_mode, (void *)MODE_FELDHELL, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_SLOWHELL].name, 0, cb_init_mode, (void *)MODE_SLOWHELL, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_HELLX5].name, 0, cb_init_mode, (void *)MODE_HELLX5, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_HELLX9].name, 0, cb_init_mode, (void *)MODE_HELLX9, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_FSKHELL].name, 0, cb_init_mode, (void *)MODE_FSKHELL, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_FSKH105].name, 0, cb_init_mode, (void *)MODE_FSKH105, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_HELL80].name, 0, cb_init_mode, (void *)MODE_HELL80, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"MFSK", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK4].name, 0, cb_init_mode, (void *)MODE_MFSK4, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK8].name, 0, cb_init_mode, (void *)MODE_MFSK8, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK11].name, 0, cb_init_mode, (void *)MODE_MFSK11, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK16].name, 0, cb_init_mode, (void *)MODE_MFSK16, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK22].name, 0, cb_init_mode, (void *)MODE_MFSK22, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK31].name, 0, cb_init_mode, (void *)MODE_MFSK31, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK32].name, 0, cb_init_mode, (void *)MODE_MFSK32, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK64].name, 0, cb_init_mode, (void *)MODE_MFSK64, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"MT63", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MT63_500].name, 0, cb_init_mode, (void *)MODE_MT63_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MT63_1000].name, 0, cb_init_mode, (void *)MODE_MT63_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MT63_2000].name, 0, cb_init_mode, (void *)MODE_MT63_2000, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"Olivia", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { "8/500", 0, cb_oliviaA, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, { "16/500", 0, cb_oliviaB, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, { "32/1000", 0, cb_oliviaC, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { "Custom", 0, cb_oliviaCustom, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"PSK", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_BPSK31].name, 0, cb_init_mode, (void *)MODE_BPSK31, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_QPSK31].name, 0, cb_init_mode, (void *)MODE_QPSK31, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK63].name, 0, cb_init_mode, (void *)MODE_PSK63, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_QPSK63].name, 0, cb_init_mode, (void *)MODE_QPSK63, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK125].name, 0, cb_init_mode, (void *)MODE_PSK125, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_QPSK125].name, 0, cb_init_mode, (void *)MODE_QPSK125, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK250].name, 0, cb_init_mode, (void *)MODE_PSK250, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_QPSK250].name, 0, cb_init_mode, (void *)MODE_QPSK250, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"RTTY", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { "RTTY-45", 0, cb_rtty45, (void *)MODE_RTTY, 0, FL_NORMAL_LABEL, 0, 14, 0}, { "RTTY-50", 0, cb_rtty50, (void *)MODE_RTTY, 0, FL_NORMAL_LABEL, 0, 14, 0}, { "RTTY-75", 0, cb_rtty75, (void *)MODE_RTTY, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { "Custom", 0, cb_rttyCustom, (void *)MODE_RTTY, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"THOR", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR4].name, 0, cb_init_mode, (void *)MODE_THOR4, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR5].name, 0, cb_init_mode, (void *)MODE_THOR5, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR8].name, 0, cb_init_mode, (void *)MODE_THOR8, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR11].name, 0, cb_init_mode, (void *)MODE_THOR11, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"Throb", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THROB1].name, 0, cb_init_mode, (void *)MODE_THROB1, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THROB2].name, 0, cb_init_mode, (void *)MODE_THROB2, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THROB4].name, 0, cb_init_mode, (void *)MODE_THROB4, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THROBX1].name, 0, cb_init_mode, (void *)MODE_THROBX1, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THROBX2].name, 0, cb_init_mode, (void *)MODE_THROBX2, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THROBX4].name, 0, cb_init_mode, (void *)MODE_THROBX4, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"NBEMS modes", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX11].name, 0, cb_init_mode, (void *)MODE_DOMINOEX11, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX22].name, 0, cb_init_mode, (void *)MODE_DOMINOEX22, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK16].name, 0, cb_init_mode, (void *)MODE_MFSK16, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK32].name, 0, cb_init_mode, (void *)MODE_MFSK32, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK125].name, 0, cb_init_mode, (void *)MODE_PSK125, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK250].name, 0, cb_init_mode, (void *)MODE_PSK250, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, { mode_info[MODE_WWV].name, 0, cb_init_mode, (void *)MODE_WWV, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_ANALYSIS].name, 0, cb_init_mode, (void *)MODE_ANALYSIS, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {_("Configure"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { make_icon_label(_("Operator"), system_users_icon), 0, (Fl_Callback*)cb_mnuConfigOperator, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Colors && Fonts"), preferences_desktop_font_icon), 0, (Fl_Callback*)cb_mnuConfigFonts, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("User Interface")), 0, (Fl_Callback*)cb_mnuUI, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Waterfall"), waterfall_icon), 0, (Fl_Callback*)cb_mnuConfigWaterfall, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Modems"), emblems_system_icon), 0, (Fl_Callback*)cb_mnuConfigModems, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Rig Control"), multimedia_player_icon), 0, (Fl_Callback*)cb_mnuConfigRigCtrl, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Sound Card"), audio_card_icon), 0, (Fl_Callback*)cb_mnuConfigSoundCard, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("IDs")), 0, (Fl_Callback*)cb_mnuConfigID, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Misc")), 0, (Fl_Callback*)cb_mnuConfigMisc, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("QRZ"), net_icon), 0, (Fl_Callback*)cb_mnuConfigQRZ, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Save Config"), save_icon), 0, (Fl_Callback*)cb_mnuSaveConfig, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {_("View"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { make_icon_label(_("Digiscope"), utilities_system_monitor_icon), 0, (Fl_Callback*)cb_mnuDigiscope, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("MFSK Image"), image_icon), 0, (Fl_Callback*)cb_mnuPicViewer, 0, FL_MENU_INACTIVE, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("PSK Browser")), 0, (Fl_Callback*)cb_mnuViewer, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Rig Control"), multimedia_player_icon), 0, (Fl_Callback*)cb_mnuRig, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, {_("Help"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, #ifndef NDEBUG // settle the gmfsk vs fldigi argument once and for all { make_icon_label(_("Create sunspots"), weather_clear_icon), 0, cb_mnuFun, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, #endif { make_icon_label(_("Beginners' Guide"), start_here_icon), 0, cb_mnuBeginnersURL, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Online documentation..."), help_browser_icon), 0, cb_mnuVisitURL, (void *)PACKAGE_DOCS, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Fldigi web site..."), net_icon), 0, cb_mnuVisitURL, (void *)PACKAGE_HOME, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Reception reports..."), pskr_icon), 0, cb_mnuVisitPSKRep, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Command line options"), utilities_terminal_icon), 0, cb_mnuCmdLineHelp, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Audio device info"), audio_card_icon), 0, cb_mnuAudioInfo, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Build info"), executable_icon), 0, cb_mnuBuildInfo, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Event log"), dialog_information_icon), 0, cb_mnuDebug, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Check for updates..."), system_software_update_icon), 0, cb_mnuCheckUpdate, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("About"), help_about_icon), 0, cb_mnuAboutURL, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, }; Fl_Menu_Item *getMenuItem(const char *caption, Fl_Menu_Item* submenu) { if (submenu == 0 || !(submenu->flags & FL_SUBMENU)) submenu = menu_; int size = submenu->size() - 1; Fl_Menu_Item *item = 0; const char* label; for (int i = 0; i < size; i++) { label = (submenu[i].labeltype() == _FL_MULTI_LABEL) ? get_icon_label_text(&submenu[i]) : submenu[i].text; if (label && !strcmp(label, caption)) { item = submenu + i; break; } } if (!item) LOG_ERROR("FIXME: could not find menu \"%s\"", caption); return item; } void activate_rig_menu_item(bool b) { Fl_Menu_Item *rig = getMenuItem(_("Rig Control"), getMenuItem(_("View"))); if (!rig) return; if (b) { bSaveFreqList = true; rig->show(); } else { rig->hide(); if (rigcontrol) rigcontrol->hide(); } mnu->redraw(); } void activate_mfsk_image_item(bool b) { Fl_Menu_Item *mfsk_item = getMenuItem(_("MFSK Image")); if (mfsk_item) set_active(mfsk_item, b); } #if !defined(__APPLE__) && !defined(__CYGWIN__) void make_pixmap(Pixmap *xpm, const char **data) { // We need a displayed window to provide a GC for X_CreatePixmap Fl_Window w(0, 0, PACKAGE_NAME); w.xclass(PACKAGE_NAME); w.show(); w.make_current(); Fl_Pixmap icon(data); int maxd = MAX(icon.w(), icon.h()); *xpm = fl_create_offscreen(maxd, maxd); fl_begin_offscreen(*xpm); fl_color(FL_BACKGROUND_COLOR); fl_rectf(0, 0, maxd, maxd); icon.draw(maxd - icon.w(), maxd - icon.h()); fl_end_offscreen(); } #endif int rightof(Fl_Widget* w) { int a = w->align(); if (a == FL_ALIGN_CENTER || a & FL_ALIGN_INSIDE) return w->x() + w->w(); fl_font(FL_HELVETICA, FL_NORMAL_SIZE); int lw = static_cast(ceil(fl_width(w->label()))); if (a & (FL_ALIGN_TOP | FL_ALIGN_BOTTOM)) { if (a & FL_ALIGN_LEFT) return w->x() + MAX(w->w(), lw); else if (a & FL_ALIGN_RIGHT) return w->x() + w->w(); else return w->x() + ((lw > w->w()) ? (lw - w->w())/2 : w->w()); } else return w->x() + w->w() + lw; } int leftof(Fl_Widget* w) { int a = w->align(); if (a == FL_ALIGN_CENTER || a & FL_ALIGN_INSIDE) return w->x(); fl_font(FL_HELVETICA, FL_NORMAL_SIZE); int lw = static_cast(ceil(fl_width(w->label()))); if (a & (FL_ALIGN_TOP | FL_ALIGN_BOTTOM)) { if (a & FL_ALIGN_LEFT) return w->x(); else if (a & FL_ALIGN_RIGHT) return w->x() - (lw > w->w() ? lw - w->w() : 0); else return w->x() - (lw > w->w() ? (lw - w->w())/2 : 0); } else { if (a & FL_ALIGN_LEFT) return w->x() - lw; else return w->x(); } } int above(Fl_Widget* w) { int a = w->align(); if (a == FL_ALIGN_CENTER || a & FL_ALIGN_INSIDE) return w->y(); return (a & FL_ALIGN_TOP) ? w->y() + FL_NORMAL_SIZE : w->y(); } int below(Fl_Widget* w) { int a = w->align(); if (a == FL_ALIGN_CENTER || a & FL_ALIGN_INSIDE) return w->y() + w->h(); return (a & FL_ALIGN_BOTTOM) ? w->y() + w->h() + FL_NORMAL_SIZE : w->y() + w->h(); } string main_window_title; void update_main_title() { main_window_title = PACKAGE_TARNAME " - "; main_window_title += (progdefaults.myCall.empty() ? _("NO CALLSIGN SET") : progdefaults.myCall.c_str()); if (fl_digi_main != NULL) fl_digi_main->label(main_window_title.c_str()); } void showOpBrowserView(Fl_Widget *, void *) { if (RigViewerFrame->visible()) return CloseQsoView(); QsoInfoFrame1->hide(); QsoInfoFrame2->hide(); QsoButtonFrame->hide(); RigViewerFrame->show(); qso_opPICK->image(closepixmap); qso_opPICK->redraw_label(); qso_opPICK->tooltip(_("Close List")); } void CloseQsoView() { RigViewerFrame->hide(); QsoInfoFrame1->show(); QsoInfoFrame2->show(); QsoButtonFrame->show(); qso_opPICK->image(addrbookpixmap); qso_opPICK->redraw_label(); qso_opPICK->tooltip(_("Open List")); } void cb_qso_btnSelFreq(Fl_Widget *, void *) { qso_selectFreq(); } void cb_qso_btnDelFreq(Fl_Widget *, void *) { qso_delFreq(); } void cb_qso_btnAddFreq(Fl_Widget *, void *) { qso_addFreq(); } void cb_qso_btnClearList(Fl_Widget *, void *) { qso_clearList(); } void cb_qso_opBrowser(Fl_Browser*, void*) { if (!qso_opBrowser->value()) return; switch (Fl::event_button()) { case FL_LEFT_MOUSE: if (Fl::event_clicks()) { // double click qso_selectFreq(); CloseQsoView(); } break; case FL_RIGHT_MOUSE: qso_setFreq(); break; case FL_MIDDLE_MOUSE: qso_delFreq(); qso_addFreq(); break; default: break; } } void show_frequency(long long freq) { if (progdefaults.docked_rig_control) qsoFreqDisp->value(freq); else FreqDisp->value(freq); // REQ is built in to the widget } void show_mode(const string& sMode) { if (progdefaults.docked_rig_control) REQ_SYNC(&Fl_ComboBox::put_value, qso_opMODE, sMode.c_str()); else REQ_SYNC(&Fl_ComboBox::put_value, opMODE, sMode.c_str()); } void show_bw(const string& sWidth) { if (progdefaults.docked_rig_control) REQ_SYNC(&Fl_ComboBox::put_value, qso_opBW, sWidth.c_str()); else REQ_SYNC(&Fl_ComboBox::put_value, opBW, sWidth.c_str()); } void show_spot(bool v) { if (v) { mnu->size(btnAutoSpot->x(), mnu->h()); btnAutoSpot->value(progStatus.spot_recv); btnAutoSpot->show(); } else { btnAutoSpot->hide(); btnAutoSpot->value(v); btnAutoSpot->do_callback(); mnu->size(btnRSID->x(), mnu->h()); } mnu->redraw(); } void create_fl_digi_main() { int Y = 0; if (progdefaults.docked_rig_control) x_qsoframe += rig_control_width; IMAGE_WIDTH = progdefaults.wfwidth; Hwfall = progdefaults.wfheight; HNOM = DEFAULT_HNOM; WNOM = progStatus.mainW;//DEFAULT_HNOM; if (progdefaults.docked_scope) Wwfall = WNOM - 2 * BEZEL - Hwfall + 24; else Wwfall = WNOM - 2 * BEZEL - 2 * DEFAULT_SW; update_main_title(); fl_digi_main = new Fl_Double_Window(WNOM, HNOM, main_window_title.c_str()); mnuFrame = new Fl_Group(0,0,WNOM, Hmenu); mnu = new Fl_Menu_Bar(0, 0, WNOM - 150, Hmenu); // do some more work on the menu for (size_t i = 0; i < sizeof(menu_)/sizeof(menu_[0]); i++) { // FL_NORMAL_SIZE may have changed; update the menu items if (menu_[i].text) { menu_[i].labelsize_ = FL_NORMAL_SIZE; } // set the icon label for items with the multi label type if (menu_[i].labeltype() == _FL_MULTI_LABEL) set_icon_label(&menu_[i]); } mnu->menu(menu_); // reset the message dialog font fl_message_font(FL_HELVETICA, FL_NORMAL_SIZE); // reset the tooltip font Fl_Tooltip::font(FL_HELVETICA); Fl_Tooltip::size(FL_NORMAL_SIZE); Fl_Tooltip::enable(progdefaults.tooltips); btnAutoSpot = new Fl_Light_Button(WNOM - 200 - pad, 0, 50, Hmenu, "Spot"); btnAutoSpot->selection_color(FL_GREEN); btnAutoSpot->callback(cbAutoSpot, 0); btnAutoSpot->hide(); btnRSID = new Fl_Light_Button(WNOM - 150 - pad, 0, 50, Hmenu, "RSID"); btnRSID->selection_color(FL_GREEN); btnRSID->callback(cbRSID, 0); btnTune = new Fl_Light_Button(WNOM - 100 - pad, 0, 50, Hmenu, "TUNE"); btnTune->selection_color(FL_RED); btnTune->callback(cbTune, 0); btnMacroTimer = new Fl_Button(WNOM - 50 - pad, 0, 50, Hmenu); btnMacroTimer->color(fl_rgb_color(255, 255, 100)); btnMacroTimer->labelcolor(FL_RED); btnMacroTimer->callback(cbMacroTimerButton, 0); btnMacroTimer->hide(); btnMacroDummy = new Fl_Button(WNOM - 50 - pad, 0, 50, Hmenu, ""); mnuFrame->resizable(mnu); mnuFrame->end(); Fl_Group *TopFrame = new Fl_Group(0, Hmenu, WNOM, Hqsoframe + Hnotes); if (progdefaults.docked_rig_control) { RigControlFrame = new Fl_Group(0, Hmenu, rig_control_width, Hqsoframe + Hnotes); txtRigName = new Fl_Box(2, Hmenu, FREQWIDTH, Hqsoframe - FREQHEIGHT); txtRigName->align(FL_ALIGN_CENTER); txtRigName->color(FL_BACKGROUND_COLOR); txtRigName->label(_("No rig specified")); qsoFreqDisp = new cFreqControl(2, Hmenu + Hqsoframe - FREQHEIGHT, FREQWIDTH, FREQHEIGHT, ""); qsoFreqDisp->box(FL_DOWN_BOX); qsoFreqDisp->color(FL_BACKGROUND_COLOR); qsoFreqDisp->selection_color(FL_BACKGROUND_COLOR); qsoFreqDisp->labeltype(FL_NORMAL_LABEL); qsoFreqDisp->labelfont(0); qsoFreqDisp->labelsize(12); qsoFreqDisp->labelcolor(FL_FOREGROUND_COLOR); qsoFreqDisp->align(FL_ALIGN_CENTER); qsoFreqDisp->when(FL_WHEN_RELEASE); qsoFreqDisp->setCallBack(qso_movFreq); qsoFreqDisp->SetONOFFCOLOR( fl_rgb_color( progdefaults.FDforeground.R, progdefaults.FDforeground.G, progdefaults.FDforeground.B), fl_rgb_color( progdefaults.FDbackground.R, progdefaults.FDbackground.G, progdefaults.FDbackground.B)); qsoFreqDisp->value(145580000); Y = Hmenu + Hqsoframe + 1; int w_mng = BTNWIDTH; int w_pmb = (FREQWIDTH - w_mng) / 2; qso_opMODE = new Fl_ComboBox(2, Hmenu + Hqsoframe + 1, w_pmb, Hnotes - 2); qso_opMODE->box(FL_DOWN_BOX); qso_opMODE->color(FL_BACKGROUND2_COLOR); qso_opMODE->selection_color(FL_BACKGROUND_COLOR); qso_opMODE->labeltype(FL_NORMAL_LABEL); qso_opMODE->labelfont(0); qso_opMODE->labelsize(14); qso_opMODE->labelcolor(FL_FOREGROUND_COLOR); qso_opMODE->callback((Fl_Callback*)cb_qso_opMODE); qso_opMODE->align(FL_ALIGN_TOP); qso_opMODE->when(FL_WHEN_RELEASE); qso_opMODE->end(); qso_opBW = new Fl_ComboBox(rightof(qso_opMODE), Hmenu + Hqsoframe + 1, w_pmb, Hnotes - 2); qso_opBW->box(FL_DOWN_BOX); qso_opBW->color(FL_BACKGROUND2_COLOR); qso_opBW->selection_color(FL_BACKGROUND_COLOR); qso_opBW->labeltype(FL_NORMAL_LABEL); qso_opBW->labelfont(0); qso_opBW->labelsize(14); qso_opBW->labelcolor(FL_FOREGROUND_COLOR); qso_opBW->callback((Fl_Callback*)cb_qso_opBW); qso_opBW->align(FL_ALIGN_TOP); qso_opBW->when(FL_WHEN_RELEASE); qso_opBW->end(); qso_opPICK = new Fl_Button(rightof(qso_opBW), Hmenu + Hqsoframe + 1, w_mng, Hnotes - 2); addrbookpixmap = new Fl_Pixmap(address_book_icon); closepixmap = new Fl_Pixmap(close_icon); qso_opPICK->image(addrbookpixmap); qso_opPICK->callback(showOpBrowserView, 0); qso_opPICK->tooltip(_("Open List")); RigControlFrame->resizable(NULL); RigControlFrame->end(); int BV_h = Hqsoframe + Hnotes; int opB_w = 280; int qFV_w = opB_w + 2 * BTNWIDTH + 6; RigViewerFrame = new Fl_Group(rightof(RigControlFrame), Hmenu, qFV_w, BV_h); qso_btnSelFreq = new Fl_Button( rightof(RigControlFrame), Hmenu + 1, 20, Hnotes - 2); qso_btnSelFreq->image(new Fl_Pixmap(left_arrow_icon)); qso_btnSelFreq->tooltip(_("Select")); qso_btnSelFreq->callback((Fl_Callback*)cb_qso_btnSelFreq); qso_btnAddFreq = new Fl_Button( rightof(qso_btnSelFreq) + pad, Hmenu + 1, 20, Hnotes - 2); qso_btnAddFreq->image(new Fl_Pixmap(plus_icon)); qso_btnAddFreq->tooltip(_("Add current frequency")); qso_btnAddFreq->callback((Fl_Callback*)cb_qso_btnAddFreq); qso_btnClearList = new Fl_Button( rightof(RigControlFrame), Hmenu + qh + 1, 20, Hnotes - 2); qso_btnClearList->image(new Fl_Pixmap(trash_icon)); qso_btnClearList->tooltip(_("Clear list")); qso_btnClearList->callback((Fl_Callback*)cb_qso_btnClearList); qso_btnDelFreq = new Fl_Button( rightof(qso_btnClearList) + pad, Hmenu + qh + 1, 20, Hnotes - 2); qso_btnDelFreq->image(new Fl_Pixmap(minus_icon)); qso_btnDelFreq->tooltip(_("Delete from list")); qso_btnDelFreq->callback((Fl_Callback*)cb_qso_btnDelFreq); qso_opBrowser = new Fl_Browser(rightof(qso_btnDelFreq) + pad, Hmenu + 1, opB_w, BV_h - 1 ); qso_opBrowser->tooltip(_("Select operating parameters")); qso_opBrowser->callback((Fl_Callback*)cb_qso_opBrowser); qso_opBrowser->type(2); qso_opBrowser->box(FL_DOWN_BOX); qso_opBrowser->labelfont(4); qso_opBrowser->labelsize(12); qso_opBrowser->textfont(4); RigViewerFrame->resizable(NULL); RigViewerFrame->end(); RigViewerFrame->hide(); QsoButtonFrame = new Fl_Group(rightof(RigControlFrame), Hmenu, BTNWIDTH, Hqsoframe + Hnotes); btnQRZ = new Fl_Button(rightof(RigControlFrame) + pad, Hmenu + 1, BTNWIDTH - 2*pad, qh - pad); btnQRZ = new Fl_Button(rightof(RigControlFrame) + pad, Hmenu + 1, BTNWIDTH - 2*pad, qh - pad); btnQRZ->image(new Fl_Pixmap(net_icon)); btnQRZ->callback(cb_QRZ, 0); btnQRZ->tooltip(_("QRZ")); qsoClear = new Fl_Button(rightof(RigControlFrame) + pad, Hmenu + qh + 1, BTNWIDTH - 2*pad, qh - pad); qsoClear->image(new Fl_Pixmap(edit_clear_icon)); qsoClear->callback(qsoClear_cb, 0); qsoClear->tooltip(_("Clear")); qsoSave = new Fl_Button(rightof(RigControlFrame) + pad, Hmenu + Hqsoframe + 1, BTNWIDTH - 2*pad, qh - pad); qsoSave->image(new Fl_Pixmap(save_icon)); qsoSave->callback(qsoSave_cb, 0); qsoSave->tooltip(_("Save")); QsoButtonFrame->end(); } else { QsoButtonFrame = new Fl_Group(0, Hmenu, BTNWIDTH, Hqsoframe + Hnotes); btnQRZ = new Fl_Button(pad, Hmenu + 1, BTNWIDTH - 2*pad, qh - pad); btnQRZ->image(new Fl_Pixmap(net_icon)); btnQRZ->callback(cb_QRZ, 0); btnQRZ->tooltip(_("QRZ")); qsoClear = new Fl_Button(pad, Hmenu + qh + 1, BTNWIDTH - 2*pad, qh - pad); qsoClear->image(new Fl_Pixmap(edit_clear_icon)); qsoClear->callback(qsoClear_cb, 0); qsoClear->tooltip(_("Clear")); qsoSave = new Fl_Button(pad, Hmenu + Hqsoframe + 1, BTNWIDTH - 2*pad, qh - pad); qsoSave->image(new Fl_Pixmap(save_icon)); qsoSave->callback(qsoSave_cb, 0); qsoSave->tooltip(_("Save")); QsoButtonFrame->end(); } int y2 = Hmenu + qh + 1; int y3 = Hmenu + Hqsoframe + 1; QsoInfoFrame = new Fl_Group(x_qsoframe, Hmenu, WNOM - rightof(QsoButtonFrame) - pad, Hqsoframe + Hnotes); QsoInfoFrame1 = new Fl_Group(x_qsoframe, Hmenu, wf1, Hqsoframe + Hnotes); // QsoInfoFrame1->box(FL_BORDER_BOX); inpFreq = new Fl_Input(x_qsoframe + pad, y2, w_inpFreq, qh - pad, _("QSO Freq")); inpFreq->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); inpTime = new Fl_Input(rightof(inpFreq) + pad, y2, w_inpTime, qh - pad, _("Time")); inpTime->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); qsoTime = new Fl_Button(rightof(inpTime), y2, w_qsoTime, qh - pad); qsoTime->image(new Fl_Pixmap(time_icon)); qsoTime->callback(qsoTime_cb, 0); inpCall = new Fl_Input(rightof(qsoTime) + pad, y2, w_inpCall, qh - pad, _("Call")); inpCall->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); inpName = new Fl_Input(rightof(inpCall) + pad, y2, w_inpName, qh - pad, _("Name")); inpName->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); inpRstIn = new Fl_Input(rightof(inpName) + pad, y2, w_inpRstIn, qh - pad, "In"); inpRstIn->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); inpRstOut = new Fl_Input(rightof(inpRstIn) + pad, y2, w_inpRstOut, qh - pad, "Out"); inpRstOut->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); inpSerNo = new Fl_Input(rightof(inpRstOut) + pad, y2, w_inpSerNo, qh - pad, "##"); inpSerNo->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); Fl_Box *fm1box = new Fl_Box(x_qsoframe, y3, w_fm1, qh - pad, "Qth"); fm1box->align(FL_ALIGN_INSIDE); inpQth = new Fl_Input( rightof(fm1box), y3, w_inpQth, qh - pad, ""); inpQth->align(FL_ALIGN_INSIDE); Fl_Box *fm2box = new Fl_Box(rightof(inpQth), y3, w_fm2, qh - pad, "St"); fm2box->align(FL_ALIGN_INSIDE); inpCnty = new Fl_Input(rightof(fm2box), y3, w_inpCnty, qh - pad, ""); inpCnty->tooltip("US State or Country"); inpCnty->align(FL_ALIGN_INSIDE); Fl_Box *fm3box = new Fl_Box(rightof(inpCnty), y3, w_fm3, qh - pad, "Pr"); fm3box->align(FL_ALIGN_INSIDE); inpVEprov = new Fl_Input(rightof(fm3box), y3, w_inpProv, qh - pad, ""); inpVEprov->tooltip("Can. Province"); inpVEprov->align(FL_ALIGN_INSIDE); Fl_Box *fm4box = new Fl_Box(rightof(inpVEprov), y3, w_fm4, qh - pad, "Loc"); fm4box->align(FL_ALIGN_INSIDE); inpLoc = new Fl_Input(rightof(fm4box), y3, w_inpLOC, qh - pad, ""); inpLoc->align(FL_ALIGN_INSIDE); Fl_Box *fm5box = new Fl_Box(rightof(inpLoc), y3, w_fm5, qh - pad, "Az"); fm5box->align(FL_ALIGN_INSIDE); inpAZ = new Fl_Input(rightof(fm5box), y3, w_inpAZ, qh - pad, ""); inpAZ->align(FL_ALIGN_INSIDE); QsoInfoFrame1->resizable(NULL); QsoInfoFrame1->end(); QsoInfoFrame2 = new Fl_Group(x_qsoframe + wf1 + pad, Hmenu, WNOM - rightof(QsoInfoFrame1) - 2*pad, Hqsoframe + Hnotes); // QsoInfoFrame2->box(FL_BORDER_BOX); inpNotes = new Fl_Multiline_Input(x_qsoframe + wf1 + pad, y2, WNOM - rightof(QsoInfoFrame1) - 2*pad, qh + Hnotes - pad, _("Notes")); inpNotes->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); Fl_Group::current()->resizable(inpNotes); QsoInfoFrame2->end(); Fl_Group::current()->resizable(QsoInfoFrame2); QsoInfoFrame->end(); Fl_Group::current()->resizable(QsoInfoFrame); TopFrame->end(); Y = Hmenu + Hqsoframe + Hnotes + pad; // Fl_Widget* logfields[] = { inpFreq, inpTime, inpCall, inpName, inpRstIn, Fl_Widget* logfields[] = { inpCall, inpName, inpRstIn, inpRstOut, inpQth, inpAZ, inpLoc, inpNotes }; for (size_t i = 0; i < sizeof(logfields)/sizeof(*logfields); i++) logfields[i]->callback(cb_log); int sw = DEFAULT_SW; MixerFrame = new Fl_Group(0,Y,sw, Hrcvtxt + Hxmttxt); valRcvMixer = new Fl_Value_Slider(0, Y, sw, (Htext)/2, ""); valRcvMixer->type(FL_VERT_NICE_SLIDER); valRcvMixer->color(fl_rgb_color(0,110,30)); valRcvMixer->labeltype(FL_ENGRAVED_LABEL); valRcvMixer->selection_color(fl_rgb_color(255,255,0)); valRcvMixer->textcolor(FL_WHITE); valRcvMixer->range(100.0,0.0); valRcvMixer->value(100.0); valRcvMixer->step(1.0); valRcvMixer->callback( (Fl_Callback *)cb_RcvMixer); valXmtMixer = new Fl_Value_Slider(0, Y + (Htext)/2, sw, (Htext)/2, ""); valXmtMixer->type(FL_VERT_NICE_SLIDER); valXmtMixer->color(fl_rgb_color(110,0,30)); valXmtMixer->labeltype(FL_ENGRAVED_LABEL); valXmtMixer->selection_color(fl_rgb_color(255,255,0)); valXmtMixer->textcolor(FL_WHITE); valXmtMixer->range(100.0,0.0); valXmtMixer->value(100.0); valXmtMixer->step(1.0); valXmtMixer->callback( (Fl_Callback *)cb_XmtMixer); MixerFrame->end(); TiledGroup = new Fl_Tile_check(sw, Y, WNOM-sw, Htext); int minRxHeight = Hrcvtxt; int minTxHeight; if (minRxHeight < 66) minRxHeight = 66; minTxHeight = Htext - minRxHeight; ReceiveText = new FTextView(sw, Y, WNOM-sw, minRxHeight, ""); ReceiveText->color( fl_rgb_color( progdefaults.RxColor.R, progdefaults.RxColor.G, progdefaults.RxColor.B)); ReceiveText->setFont(progdefaults.RxFontnbr); ReceiveText->setFontSize(progdefaults.RxFontsize); ReceiveText->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV); ReceiveText->setFontColor(progdefaults.XMITcolor, FTextBase::XMIT); ReceiveText->setFontColor(progdefaults.CTRLcolor, FTextBase::CTRL); ReceiveText->setFontColor(progdefaults.SKIPcolor, FTextBase::SKIP); ReceiveText->setFontColor(progdefaults.ALTRcolor, FTextBase::ALTR); if (progdefaults.DisplayMacroFilename) { string Macroset = "<<<===== Macro File "; Macroset.append(progStatus.LastMacroFile); Macroset.append(" Loaded =====>>>\n\n"); ReceiveText->add(Macroset.c_str()); } TiledGroup->add_resize_check(FTextView::wheight_mult_tsize, ReceiveText); FHdisp = new Raster(sw, Y, WNOM-sw, minRxHeight); FHdisp->hide(); TransmitText = new FTextEdit(sw, Y + minRxHeight, WNOM-sw, minTxHeight); TransmitText->color( fl_rgb_color( progdefaults.TxColor.R, progdefaults.TxColor.G, progdefaults.TxColor.B)); TransmitText->setFont(progdefaults.TxFontnbr); TransmitText->setFontSize(progdefaults.TxFontsize); TransmitText->setFontColor(progdefaults.TxFontcolor, FTextBase::RECV); TransmitText->setFontColor(progdefaults.XMITcolor, FTextBase::XMIT); TransmitText->setFontColor(progdefaults.CTRLcolor, FTextBase::CTRL); TransmitText->setFontColor(progdefaults.SKIPcolor, FTextBase::SKIP); TransmitText->setFontColor(progdefaults.ALTRcolor, FTextBase::ALTR); Fl_Box *minbox = new Fl_Box(sw,Y + 66, WNOM-sw, Htext - 66 - 32); minbox->hide(); TiledGroup->resizable(minbox); Y += Htext; TiledGroup->end(); Fl_Group::current()->resizable(TiledGroup); Fl::add_handler(default_handler); Fl_Box *bx; Fl_Box *macroFrame = new Fl_Box(0, Y, WNOM, Hmacros); macroFrame->box(FL_ENGRAVED_FRAME); int Wbtn = (WNOM - 30 - 8 - 4)/NUMMACKEYS; int xpos = 2; for (int i = 0; i < NUMMACKEYS; i++) { if (i == 4 || i == 8) { bx = new Fl_Box(xpos, Y+2, 5, Hmacros - 4); bx->box(FL_FLAT_BOX); bx->color(FL_BLACK); xpos += 4; } btnMacro[i] = new Fl_Button(xpos, Y+2, Wbtn, Hmacros - 4, macros.name[i].c_str()); btnMacro[i]->callback(macro_cb, (void *)i); btnMacro[i]->tooltip(_("Left Click - execute\nRight Click - edit")); colorize_macro(i); xpos += Wbtn; } bx = new Fl_Box(xpos, Y+2, WNOM - 32 - xpos, Hmacros - 4); bx->box(FL_FLAT_BOX); bx->color(FL_BLACK); btnAltMacros = new Fl_Button(WNOM-32, Y+2, 30, Hmacros - 4, "1"); btnAltMacros->callback(altmacro_cb, 0); btnAltMacros->tooltip(_("Change macro set")); Y += Hmacros; if (progdefaults.docked_scope) { Fl_Pack *wfpack = new Fl_Pack(0, Y, WNOM, Hwfall); wfpack->type(1); wf = new waterfall(0, Y, Wwfall, Hwfall); wf->end(); Fl_Pack *ypack = new Fl_Pack( rightof(wf), Y, Hwfall - 24, Hwfall); ypack->type(0); wfscope = new Digiscope ( rightof(wf), Y, Hwfall - 24, Hwfall - 24); pgrsSquelch = new Progress( rightof(wf), Y + Hwfall - 24, Hwfall - 24, 12, ""); pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN); sldrSquelch = new Fl_Slider( FL_HOR_NICE_SLIDER, rightof(wf), Y + Hwfall - 12, Hwfall - 24, 12, ""); sldrSquelch->minimum(0); sldrSquelch->maximum(100); sldrSquelch->step(1); sldrSquelch->value(progStatus.sldrSquelchValue); sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch); sldrSquelch->color(FL_INACTIVE_COLOR); ypack->end(); Fl_Group::current()->resizable(wf); wfpack->end(); } else { Fl_Pack *wfpack = new Fl_Pack(0, Y, WNOM, Hwfall); wfpack->type(1); wf = new waterfall(0, Y, Wwfall, Hwfall); wf->end(); pgrsSquelch = new Progress( rightof(wf), Y + 4, DEFAULT_SW, Hwfall - 8, ""); pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN); pgrsSquelch->type(Progress::VERTICAL); pgrsSquelch->tooltip(_("Detected signal level")); sldrSquelch = new Fl_Slider( rightof(pgrsSquelch), Y + 4, DEFAULT_SW, Hwfall - 8, ""); sldrSquelch->minimum(100); sldrSquelch->maximum(0); sldrSquelch->step(1); sldrSquelch->value(progStatus.sldrSquelchValue); sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch); sldrSquelch->color(FL_INACTIVE_COLOR); sldrSquelch->tooltip(_("Squelch level")); Fl_Group::current()->resizable(wf); wfpack->end(); } Y += (Hwfall + 2); Fl_Pack *hpack = new Fl_Pack(0, Y, WNOM, Hstatus); hpack->type(1); MODEstatus = new Fl_Button(0,Hmenu+Hrcvtxt+Hxmttxt+Hwfall, Wmode, Hstatus, ""); MODEstatus->box(FL_DOWN_BOX); MODEstatus->color(FL_BACKGROUND2_COLOR); MODEstatus->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); MODEstatus->callback(status_cb, (void *)0); MODEstatus->when(FL_WHEN_CHANGED); MODEstatus->tooltip(_("Left clk - change mode\nRight clk - Modem Tab")); Status1 = new Fl_Box(rightof(MODEstatus), Hmenu+Hrcvtxt+Hxmttxt+Hwfall, Ws2n, Hstatus, ""); Status1->box(FL_DOWN_BOX); Status1->color(FL_BACKGROUND2_COLOR); Status1->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); Status2 = new Fl_Box(rightof(Status1), Hmenu+Hrcvtxt+Hxmttxt+Hwfall, Wimd, Hstatus, ""); Status2->box(FL_DOWN_BOX); Status2->color(FL_BACKGROUND2_COLOR); Status2->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); StatusBar = new Fl_Box( rightof(Status2), Hmenu+Hrcvtxt+Hxmttxt+Hwfall, WNOM - bwSqlOnOff - bwAfcOnOff - Wwarn - rightof(Status2) - 60, Hstatus, ""); StatusBar->box(FL_DOWN_BOX); StatusBar->color(FL_BACKGROUND2_COLOR); StatusBar->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); WARNstatus = new Fl_Box( rightof(StatusBar), Hmenu+Hrcvtxt+Hxmttxt+Hwfall, Wwarn, Hstatus, ""); WARNstatus->box(FL_DIAMOND_DOWN_BOX); WARNstatus->color(FL_BACKGROUND_COLOR); WARNstatus->labelcolor(FL_RED); WARNstatus->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); AFCindicator = new AFCind( rightof(WARNstatus), Hmenu+Hrcvtxt+Hxmttxt+Hwfall, 60, Hstatus, ""); int sql_width = bwSqlOnOff; #ifdef __APPLE__ sql_width -= 15; // leave room for resize handle #endif if (progdefaults.useCheckButtons) { btn_afconoff = new Fl_Check_Button( WNOM - bwSqlOnOff - bwAfcOnOff, Hmenu+Hrcvtxt+Hxmttxt+Hwfall, bwAfcOnOff, Hstatus, "AFC"); btn_sqlonoff = new Fl_Check_Button( WNOM - bwSqlOnOff, Hmenu+Hrcvtxt+Hxmttxt+Hwfall, sql_width, Hstatus, "SQL"); } else { btn_afconoff = new Fl_Light_Button( WNOM - bwSqlOnOff - bwAfcOnOff, Hmenu+Hrcvtxt+Hxmttxt+Hwfall, bwAfcOnOff, Hstatus, "AFC"); btn_sqlonoff = new Fl_Light_Button( WNOM - bwSqlOnOff, Hmenu+Hrcvtxt+Hxmttxt+Hwfall, sql_width, Hstatus, "SQL"); } btn_afconoff->callback(afconoff_cb, 0); btn_afconoff->value(1); btn_afconoff->tooltip(_("AFC on/off")); btn_sqlonoff->callback(sqlonoff_cb, 0); btn_sqlonoff->value(1); btn_sqlonoff->tooltip(_("SQL on/off")); Fl_Group::current()->resizable(StatusBar); hpack->end(); fl_digi_main->end(); fl_digi_main->callback(cb_wMain); #if defined (__CYGWIN__) fl_digi_main->icon((char*)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON))); #elif defined (__linux__) make_pixmap(&fldigi_icon_pixmap, fldigi_icon); fl_digi_main->icon((char *)fldigi_icon_pixmap); #endif fl_digi_main->xclass(PACKAGE_NAME); fl_digi_main->size_range(WMIN, HMIN);//WNOM, (HNOM < 400 ? HNOM : 400)); scopeview = new Fl_Double_Window(0,0,140,140, _("Scope")); scopeview->xclass(PACKAGE_NAME); digiscope = new Digiscope (0, 0, 140, 140); scopeview->resizable(digiscope); scopeview->size_range(SCOPEWIN_MIN_WIDTH, SCOPEWIN_MIN_HEIGHT); scopeview->end(); scopeview->hide(); if (progdefaults.docked_rig_control) activate_rig_menu_item(false); if (!progdefaults.menuicons) toggle_icon_labels(); } void put_freq(double frequency) { wf->carrier((int)floor(frequency + 0.5)); } void put_Bandwidth(int bandwidth) { wf->Bandwidth ((int)bandwidth); } static void set_metric(double metric) { pgrsSquelch->value(metric); static Fl_Color sqlcol = btn_sqlonoff->selection_color(); if (!progStatus.sqlonoff) return; if (metric < progStatus.sldrSquelchValue) btn_sqlonoff->selection_color(sqlcol); else btn_sqlonoff->selection_color(FL_GREEN); btn_sqlonoff->redraw_label(); } void display_metric(double metric) { FL_LOCK_D(); REQ_DROP(set_metric, metric); FL_UNLOCK_D(); FL_AWAKE_D(); } void put_cwRcvWPM(double wpm) { int U = progdefaults.CWupperlimit; int L = progdefaults.CWlowerlimit; double dWPM = 100.0*(wpm - L)/(U - L); FL_LOCK_D(); REQ_DROP(static_cast(&Fl_Progress::value), prgsCWrcvWPM, dWPM); REQ_DROP(static_cast(&Fl_Value_Output::value), valCWrcvWPM, (int)wpm); FL_UNLOCK_D(); FL_AWAKE_D(); } void set_scope_mode(Digiscope::scope_mode md) { if (digiscope) { digiscope->mode(md); REQ(&Fl_Window::size_range, scopeview, SCOPEWIN_MIN_WIDTH, SCOPEWIN_MIN_HEIGHT, 0, 0, 0, 0, (md == Digiscope::PHASE || md == Digiscope::XHAIRS)); } if (wfscope) wfscope->mode(md); } void set_scope(double *data, int len, bool autoscale) { if (digiscope) digiscope->data(data, len, autoscale); if (wfscope) wfscope->data(data, len, autoscale); } void set_phase(double phase, double quality, bool highlight) { if (digiscope) digiscope->phase(phase, quality, highlight); if (wfscope) wfscope->phase(phase, quality, highlight); } void set_rtty(double flo, double fhi, double amp) { if (digiscope) digiscope->rtty(flo, fhi, amp); if (wfscope) wfscope->rtty(flo, fhi, amp); } void set_video(double *data, int len, bool dir) { if (digiscope) digiscope->video(data, len, dir); if (wfscope) wfscope->video(data, len, dir); } void set_zdata(complex *zarray, int len) { if (digiscope) digiscope->zdata(zarray, len); if (wfscope) wfscope->zdata(zarray, len); } Fl_Menu_Item *mnuLogging = (Fl_Menu_Item *)0; void put_rx_char(unsigned int data) { static unsigned int last = 0; const char **asc = ascii; trx_mode mode = active_modem->get_mode(); if (mailclient || mailserver || arqmode) asc = ascii2; if (mode == MODE_RTTY || mode == MODE_CW) asc = ascii; int style = FTextBase::RECV; if (asc == ascii2 && iscntrl(data)) style = FTextBase::CTRL; if (wf->tmp_carrier()) style = FTextBase::ALTR; switch (data) { case '\n': if (last == '\r') break; case '\r': REQ(&FTextBase::addchr, ReceiveText, '\n', style); break; default: REQ(&FTextBase::addchr, ReceiveText, data, style); } last = data; WriteARQ(data); string s; if (iscntrl(data)) s = ascii2[data & 0x7F]; else { s += data; bool viewer = (mode >= MODE_PSK_FIRST && mode <= MODE_PSK_LAST && dlgViewer && dlgViewer->visible()); if (progStatus.spot_recv && !viewer) spot_recv(data); } if (Maillogfile) Maillogfile->log_to_file(cLogfile::LOG_RX, s); if (!mnuLogging) mnuLogging = getMenuItem(_("Log File")); if (mnuLogging) if (mnuLogging->value()) logfile->log_to_file(cLogfile::LOG_RX, s); } string strSecText = ""; void put_sec_char( char chr ) { fl_font(FL_HELVETICA, FL_NORMAL_SIZE); char s[2] = "W"; int lc = (int)ceil(fl_width(s)); int w = StatusBar->w(); int lw = (int)ceil(fl_width(StatusBar->label())); int over = 2 * lc + lw - w; if (chr >= ' ' && chr <= 'z') { if ( over > 0 ) strSecText.erase(0, (int)(1.0 * over / lc + 0.5)); strSecText.append(1, chr); FL_LOCK_D(); REQ(static_cast(&Fl_Box::label), StatusBar, strSecText.c_str()); WARNstatus->damage(); FL_UNLOCK_D(); FL_AWAKE_D(); } } static void clear_status_cb(void* arg) { reinterpret_cast(arg)->label(""); } static void dim_status_cb(void* arg) { reinterpret_cast(arg)->deactivate(); } static void (*const timeout_action[STATUS_NUM])(void*) = { clear_status_cb, dim_status_cb }; static void put_status_msg(Fl_Box* status, const char* msg, double timeout, status_timeout action) { status->activate(); status->label(msg); if (timeout > 0.0) { Fl::remove_timeout(timeout_action[action], status); Fl::add_timeout(timeout, timeout_action[action], status); } } void put_status(const char *msg, double timeout, status_timeout action) { static char m[50]; strncpy(m, msg, sizeof(m)); m[sizeof(m) - 1] = '\0'; REQ(put_status_msg, StatusBar, m, timeout, action); } void put_Status2(const char *msg, double timeout, status_timeout action) { static char m[60]; strncpy(m, msg, sizeof(m)); m[sizeof(m) - 1] = '\0'; info2msg = msg; REQ(put_status_msg, Status2, m, timeout, action); } void put_Status1(const char *msg, double timeout, status_timeout action) { static char m[60]; strncpy(m, msg, sizeof(m)); m[sizeof(m) - 1] = '\0'; info1msg = msg; REQ(put_status_msg, Status1, m, timeout, action); } void put_WARNstatus(double val) { FL_LOCK_D(); if (val < 0.05) WARNstatus->color(FL_BLACK); if (val > 0.05) WARNstatus->color(FL_DARK_GREEN); if (val > 0.9) WARNstatus->color(FL_YELLOW); if (val > 0.98) WARNstatus->color(FL_DARK_RED); WARNstatus->redraw(); FL_UNLOCK_D(); } void set_CWwpm() { FL_LOCK(); sldrCWxmtWPM->value(progdefaults.CWspeed); FL_UNLOCK(); } void clear_StatusMessages() { FL_LOCK_E(); StatusBar->label(""); Status1->label(""); Status2->label(""); FL_UNLOCK_E(); FL_AWAKE_E(); } void put_MODEstatus(trx_mode mode) { FL_LOCK_D(); REQ(static_cast(&Fl_Button::label), MODEstatus, mode_info[mode].sname); FL_UNLOCK_D(); FL_AWAKE_D(); } void put_rx_data(int *data, int len) { FHdisp->data(data, len); } int get_tx_char(void) { if (arq_text_available) return arq_get_char(); int c; static int pending = -1; if (pending >= 0) { c = pending; pending = -1; return c; } enum { STATE_CHAR, STATE_CTRL }; static int state = STATE_CHAR; switch (c = TransmitText->nextChar()) { case '\n': pending = '\n'; return '\r'; case '^': if (state == STATE_CTRL) break; state = STATE_CTRL; return -1; case 'r': case 'R': if (state != STATE_CTRL) break; REQ_SYNC(&FTextEdit::clear_sent, TransmitText); state = STATE_CHAR; c = 3; // ETX break; case -1: break; default: if (state == STATE_CTRL) { state = STATE_CHAR; pending = c; return '^'; } } pending = -1; return c; } void put_echo_char(unsigned int data) { static unsigned int last = 0; const char **asc = ascii; if (mailclient || mailserver || arqmode) asc = ascii2; if (active_modem->get_mode() == MODE_RTTY || active_modem->get_mode() == MODE_CW) asc = ascii; if (data == '\r' && last == '\r') // reject multiple CRs return; last = data; int style = FTextBase::XMIT; if (asc == ascii2 && iscntrl(data)) style = FTextBase::CTRL; REQ(&FTextBase::addchr, ReceiveText, data, style); string s = iscntrl(data) ? ascii2[data & 0x7F] : string(1, data); if (Maillogfile) Maillogfile->log_to_file(cLogfile::LOG_TX, s); if (!mnuLogging) mnuLogging = getMenuItem(_("Log File")); // should only be called once if (mnuLogging) if (mnuLogging->value()) logfile->log_to_file(cLogfile::LOG_TX, s); } void resetRTTY() { if (active_modem->get_mode() == MODE_RTTY) trx_start_modem(active_modem); } void resetOLIVIA() { if (active_modem->get_mode() == MODE_OLIVIA) trx_start_modem(active_modem); } void resetTHOR() { trx_mode md = active_modem->get_mode(); if (md == MODE_THOR4 || md == MODE_THOR5 || md == MODE_THOR8 || md == MODE_THOR11 || md == MODE_THOR16 || md == MODE_THOR22 ) trx_start_modem(active_modem); } void resetDOMEX() { trx_mode md = active_modem->get_mode(); if (md == MODE_DOMINOEX4 || md == MODE_DOMINOEX5 || md == MODE_DOMINOEX8 || md == MODE_DOMINOEX11 || md == MODE_DOMINOEX16 || md == MODE_DOMINOEX22 ) trx_start_modem(active_modem); } void enableMixer(bool on) { #if !USE_OSS on = false; #endif FL_LOCK_D(); if (on) { progdefaults.EnableMixer = true; #if USE_OSS mixer = new MixerOSS; #else mixer = new MixerBase; #endif try { mixer->openMixer(progdefaults.MXdevice.c_str()); } catch (const MixerException& e) { put_status(e.what(), 5); goto ret; } mixer->PCMVolume(progdefaults.PCMvolume); mixer->setXmtLevel(progStatus.XmtMixer); //valXmtMixer->value()); mixer->setRcvGain(progStatus.RcvMixer); //valRcvMixer->value()); if (progdefaults.LineIn == true) setMixerInput(1); else if (progdefaults.MicIn == true) setMixerInput(2); else setMixerInput(0); }else{ progdefaults.EnableMixer = false; if (mixer) mixer->closeMixer(); delete mixer; mixer = 0; } ret: resetMixerControls(); FL_UNLOCK_D(); } void enable_vol_sliders(bool val) { if (MixerFrame->visible()) { if (val) return; MixerFrame->hide(); TiledGroup->resize(TiledGroup->x() - MixerFrame->w(), TiledGroup->y(), TiledGroup->w() + MixerFrame->w(), TiledGroup->h()); } else { if (!val) return; TiledGroup->resize(TiledGroup->x() + MixerFrame->w(), TiledGroup->y(), TiledGroup->w() - MixerFrame->w(), TiledGroup->h()); MixerFrame->show(); } } void resetMixerControls() { if (progdefaults.EnableMixer) { menuMix->activate(); btnLineIn->activate(); btnMicIn->activate(); btnMixer->value(1); valPCMvolume->activate(); } else { menuMix->deactivate(); btnLineIn->deactivate(); btnMicIn->deactivate(); btnMixer->value(0); valPCMvolume->deactivate(); } enable_vol_sliders(progdefaults.EnableMixer); } void setPCMvolume(double vol) { mixer->PCMVolume(vol); progdefaults.PCMvolume = vol; } void setMixerInput(int dev) { int n= -1; switch (dev) { case 0: n = mixer->InputSourceNbr("Vol"); break; case 1: n = mixer->InputSourceNbr("Line"); break; case 2: n = mixer->InputSourceNbr("Mic"); break; default: n = mixer->InputSourceNbr("Vol"); } if (n != -1) mixer->SetCurrentInputSource(n); } void resetSoundCard() { bool mixer_enabled = progdefaults.EnableMixer; enableMixer(false); trx_reset(); if (mixer_enabled) enableMixer(true); } void setReverse(int rev) { active_modem->set_reverse(rev); } void start_tx() { if (progdefaults.rsid == true) return; trx_transmit(); REQ(&waterfall::set_XmtRcvBtn, wf, true); } void abort_tx() { if (trx_state == STATE_TUNE) { btnTune->value(0); btnTune->do_callback(); } else if (trx_state == STATE_TX) trx_start_modem(active_modem); } void set_AFCind(double val) { REQ (&AFCind::value, AFCindicator, val ); } void set_AFCrange(double val) { REQ (&AFCind::range, AFCindicator, val); } // Adjust and return fg color to ensure good contrast with bg Fl_Color adjust_color(Fl_Color fg, Fl_Color bg) { Fl_Color adj; unsigned max = 24; while ((adj = fl_contrast(fg, bg)) != fg && max--) fg = (adj == FL_WHITE) ? fl_color_average(fg, FL_WHITE, .9) : fl_color_average(fg, FL_BLACK, .9); return fg; } void qsy(long long rfc, long long fmid) { if (fmid < 0LL) fmid = (long long)active_modem->get_freq(); if (rfc == 0LL || rfc == wf->rfcarrier()) { active_modem->set_freq(fmid); return; } if (progdefaults.chkUSERIGCATis) REQ(rigCAT_set_qsy, rfc, fmid); else if (progdefaults.chkUSEMEMMAPis) REQ(rigMEM_set_qsy, rfc, fmid); #if USE_HAMLIB else if (progdefaults.chkUSEHAMLIBis) REQ(hamlib_set_qsy, rfc, fmid); #endif #if USE_XMLRPC else if (progdefaults.chkUSEXMLRPCis) REQ(xmlrpc_set_qsy, rfc, fmid); #endif else active_modem->set_freq(fmid); } bool quick_choice(const char* title, bool sel) { Fl_Menu_Item m[] = { { "Confirm" }, { "Cancel" }, { 0 } }; return m->popup(Fl::event_x(), Fl::event_y(), title, m + !sel) == m; }