Cyrillic-UTF8 chars

* Added support for displaying, transmitting & receiving
    UTF-8 characters
  * Modes which support UTF-8 characters:
    - PSK31, PSK63, PSK125, PSK250, PSK500
    - Olivia - must enable 8 bit extended characters
    - MT63 - must enable 8 bit extended characters
    - MFSK - all baudrates supported
  * Modified "clear_sent" method in FTextRXTX to correct
    behavior when TX buffer contains UTF-8 characters
pull/1/head
David Freese 2012-02-06 07:55:02 -06:00
rodzic d2d254e5d3
commit 0d287c667d
28 zmienionych plików z 647 dodań i 174 usunięć

Wyświetl plik

@ -410,6 +410,7 @@ fldigi_SOURCES += \
include/table.h \
include/textio.h \
include/psk_browser.h \
include/utf8file_io.h \
include/weather.h \
irrxml/CXMLReaderImpl.h \
irrxml/fast_atof.h \
@ -461,6 +462,7 @@ fldigi_SOURCES += \
misc/strutil.cxx \
misc/threads.cxx \
misc/timeops.cxx \
misc/utf8file_io.cxx \
misc/util.cxx \
misc/weather.cxx \
mt63/dsp.cxx \

Wyświetl plik

@ -255,7 +255,7 @@ int view_rtty::decode_char(int ch)
data = channel[ch].rxdata & ((1 << nbits) - 1);
if (nbits == 5)
return baudot_dec(ch, data);
return baudot_dec(ch & 0x7F, data);
return data;
}
@ -319,7 +319,6 @@ bool view_rtty::rx(int ch, bool bit)
// print this RTTY_CHANNEL
if ( c != 0 )
REQ(&viewaddchr, ch, (int)channel[ch].frequency, c, mode);
// put_rx_char(progdefaults.rx_lowercase ? tolower(c) : c);
}
flag = true;
}

Wyświetl plik

@ -5271,8 +5271,8 @@ an merging"));
btnmt63_interleave->callback((Fl_Callback*)cb_btnmt63_interleave);
o->value(0);if (progdefaults.mt63_interleave == 64) o->value(1);
} // Fl_Check_Button* btnmt63_interleave
{ Fl_Check_Button* o = btnMT63_8bit = new Fl_Check_Button(195, 106, 205, 20, _("8-bit extended characters"));
btnMT63_8bit->tooltip(_("Enable this for Latin-1 accented characters"));
{ Fl_Check_Button* o = btnMT63_8bit = new Fl_Check_Button(195, 106, 205, 20, _("8-bit extended characters (UTF-8)"));
btnMT63_8bit->tooltip(_("Enable this for UTF-8 characters"));
btnMT63_8bit->down_box(FL_DOWN_BOX);
btnMT63_8bit->callback((Fl_Callback*)cb_btnMT63_8bit);
o->value(progdefaults.mt63_8bit);
@ -5386,8 +5386,8 @@ an merging"));
} // Fl_Counter2* cntOlivia_sinteg
o->end();
} // Fl_Group* o
{ btnOlivia_8bit = new Fl_Check_Button(114, 229, 200, 20, _("8-bit extended characters"));
btnOlivia_8bit->tooltip(_("Enable this for Latin-1 accented characters"));
{ btnOlivia_8bit = new Fl_Check_Button(114, 229, 200, 20, _("8-bit extended characters (UTF-8)"));
btnOlivia_8bit->tooltip(_("Enable this for UTF-8 characters"));
btnOlivia_8bit->down_box(FL_DOWN_BOX);
btnOlivia_8bit->callback((Fl_Callback*)cb_btnOlivia_8bit);
} // Fl_Check_Button* btnOlivia_8bit

Wyświetl plik

@ -1924,10 +1924,10 @@ progdefaults.changed = true;}
code0 {o->value(0);if (progdefaults.mt63_interleave == 64) o->value(1);}
}
Fl_Check_Button btnMT63_8bit {
label {8-bit extended characters}
label {8-bit extended characters (UTF-8)}
callback {progdefaults.mt63_8bit = o->value();
progdefaults.changed = true;}
tooltip {Enable this for Latin-1 accented characters} xywh {195 106 205 20} down_box DOWN_BOX
tooltip {Enable this for UTF-8 characters} xywh {195 106 205 20} down_box DOWN_BOX
code0 {o->value(progdefaults.mt63_8bit);}
}
Fl_Check_Button btnMT63_rx_integration {
@ -2032,10 +2032,10 @@ progdefaults.changed = true;}
}
}
Fl_Check_Button btnOlivia_8bit {
label {8-bit extended characters}
label {8-bit extended characters (UTF-8)}
callback {progdefaults.olivia8bit = o->value();
progdefaults.changed = true;}
tooltip {Enable this for Latin-1 accented characters} xywh {114 229 200 20} down_box DOWN_BOX
tooltip {Enable this for UTF-8 characters} xywh {114 229 200 20} down_box DOWN_BOX
}
}
}

Wyświetl plik

@ -2389,7 +2389,7 @@ void startTimedExecute(std::string &title)
btnMacroTimer->color(fl_rgb_color(240, 240, 0));
btnMacroTimer->redraw_label();
ReceiveText->clear();
ReceiveText->add(txt.c_str(), FTextBase::CTRL);
ReceiveText->addstr(txt, FTextBase::CTRL);
}
void cbMacroTimerButton(Fl_Widget*, void*)
@ -3721,7 +3721,7 @@ void showMacroSet() {
void showDTMF(const string s) {
string dtmfstr = "\n<DTMF> ";
dtmfstr.append(s);
ReceiveText->add(dtmfstr.c_str());
ReceiveText->addstr(dtmfstr);
}
void setwfrange() {
@ -3785,7 +3785,7 @@ static void cb_mainViewer(Fl_Hold_Browser*, void*) {
bHistory = true;
} else {
ReceiveText->addchr('\n', FTextBase::ALTR);
ReceiveText->addstr(mainViewer->line(sel).c_str(), FTextBase::ALTR);
ReceiveText->addstr(mainViewer->line(sel), FTextBase::ALTR);
}
active_modem->set_freq(mainViewer->freq(sel));
active_modem->set_sigsearch(SIGSEARCH);
@ -5556,7 +5556,9 @@ void add_rxtx_char(int data)
memset(rxtx_raw_buff, 0, RAW_BUFF_LEN+1);
rxtx_raw_len = 0;
}
rxtx_raw_buff[rxtx_raw_len++] = (unsigned char)data;
if (data & 0xFF00) // UTF-8 character
rxtx_raw_buff[rxtx_raw_len++] = (data >> 8) & 0xFF;
rxtx_raw_buff[rxtx_raw_len++] = (unsigned char)(data & 0xFF);
}
//======================================================================
@ -5581,6 +5583,8 @@ void add_rx_char(int data)
memset(rx_raw_buff, 0, RAW_BUFF_LEN+1);
rx_raw_len = 0;
}
if (data & 0xFF00) // UTF-8 character
rx_raw_buff[rx_raw_len++] = (data >> 8) & 0xFF;
rx_raw_buff[rx_raw_len++] = (unsigned char)data;
}
@ -5610,6 +5614,8 @@ void add_tx_char(int data)
}
//======================================================================
static unsigned char firstUTF8 = 0;
static void put_rx_char_flmain(unsigned int data, int style)
{
ENSURE_THREAD(FLMAIN_TID);
@ -5623,25 +5629,35 @@ static void put_rx_char_flmain(unsigned int data, int style)
if (mode == MODE_RTTY || mode == MODE_CW)
asc = ascii;
if (asc == ascii2 && iscntrl(data))
if (asc == ascii2 && (data < ' ') && iscntrl(data))
style = FTextBase::CTRL;
if (wf->tmp_carrier())
style = FTextBase::ALTR;
if (progdefaults.autoextract == true) rx_extract_add(data);
speak(data);
add_rx_char(data);
switch (data) {
case '\n':
if (last == '\r')
break;
case '\r':
if ((data & 0x80) == 0x80) {
if (firstUTF8 == 0)
firstUTF8 = data;
else {
add_rx_char(firstUTF8);
add_rx_char(data);
ReceiveText->add(firstUTF8, style);
ReceiveText->add(data, style);
firstUTF8 = 0;
}
} else {
firstUTF8 = 0;
if (data == '\n' && last == '\r');
else if (data == '\r') {
add_rx_char('\n');
ReceiveText->add('\n', style);
break;
default:
ReceiveText->add(data & 0x7F, style);
} else {
add_rx_char(data);
ReceiveText->add(data, style);
}
}
last = data;
@ -5649,7 +5665,7 @@ static void put_rx_char_flmain(unsigned int data, int style)
WriteARQ(data);
string s;
if (iscntrl(data))
if (data < ' ' && iscntrl(data))
s = ascii2[data & 0x7F];
else {
s += data;
@ -5988,6 +6004,8 @@ int get_tx_char(void)
void put_echo_char(unsigned int data, int style)
{
if (!data) return;
if (progdefaults.QSKadjust && (active_modem->get_mode() == MODE_CW))
return;
@ -6009,9 +6027,21 @@ void put_echo_char(unsigned int data, int style)
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 FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
string sch;
sch.clear();
if (data & 0xFF00) {
sch += (data >> 8) & 0xFF;
sch += (data & 0xFF);
} else
sch = (data & 0xFF);
REQ(&FTextRX::addstr, ReceiveText, sch, style);
#else
REQ(&FTextBase::addchr, ReceiveText, data, style);
#endif
string s = iscntrl(data & 0x7F) ? ascii2[data & 0x7F] : string(1, data);
if (Maillogfile)
Maillogfile->log_to_file(cLogfile::LOG_TX, s);
@ -6243,11 +6273,11 @@ void note_qrg(bool no_dup, const char* prefix, const char* suffix, trx_mode mode
qrg_marks[buf] = m;
if (prefix && *prefix)
ReceiveText->add(prefix);
ReceiveText->add(buf, FTextBase::QSY);
ReceiveText->addstr(prefix);
ReceiveText->addstr(buf, FTextBase::QSY);
ReceiveText->mark();
if (suffix && *suffix)
ReceiveText->add(suffix);
ReceiveText->addstr(suffix);
}
void xmtrcv_selection_color()

Wyświetl plik

@ -23,6 +23,8 @@
#ifndef FTextRXTX_H_
#define FTextRXTX_H_
#include <string>
#include "FTextView.h"
///
@ -36,12 +38,21 @@ public:
virtual int handle(int event);
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
virtual void add(unsigned int c, int attr = RECV);
virtual void add(const char *s, int attr = RECV)
{
while (*s)
add(*s++, attr);
}
#else
virtual void add(unsigned char c, int attr = RECV);
virtual void add(const char *s, int attr = RECV)
{
while (*s)
add(*s++, attr);
}
#endif
void set_quick_entry(bool b);
bool get_quick_entry(void) { return menu[RX_MENU_QUICK_ENTRY].value(); }
@ -95,9 +106,9 @@ public:
void clear(void);
void clear_sent(void);
int nextChar(void);
unsigned int nextChar(void);
bool eot(void);
void add_text(const char *s);
void add_text(std::string s);
void setFont(Fl_Font f, int attr = NATTR);
@ -124,9 +135,10 @@ private:
protected:
static Fl_Menu_Item menu[];
bool PauseBreak;
bool PauseBreak;
int txpos;
static int *ptxpos;
int utf8_txpos;
static int *ptxpos;
int bkspaces;
};

Wyświetl plik

@ -24,6 +24,7 @@
#define FTextView_H_
#include <stddef.h>
#include <string>
#include <FL/Fl.H>
#include <FL/Enumerations.H>
@ -48,9 +49,9 @@ public:
FTextBase(int x, int y, int w, int h, const char *l = 0);
virtual ~FTextBase() { delete tbuf; delete sbuf; }
virtual void add(const char *text, int attr = RECV);
virtual void add(unsigned char c, int attr = RECV);
void addstr(const char *text, int attr = RECV) { add(text, attr); }
virtual void add(const char *text, int attr = RECV);
void addstr(std::string text, int attr = RECV) { add(text.c_str(), attr); }
void addchr(unsigned char c, int attr = RECV) { add(c, attr); }
virtual int handle(int event);

Wyświetl plik

@ -216,13 +216,22 @@ public:
char* text_range(int start, int end) const;
/**
Returns the character at the specified position pos in the buffer.
Returns the UCS-4 character at the specified position pos in the buffer.
Positions start at 0
\param pos byte offset into buffer, pos must be at acharacter boundary
\param pos byte offset into buffer, pos must be at a character boundary
\return Unicode UCS-4 encoded character
*/
unsigned int char_at(int pos) const;
/**
Returns the UTF-8 character at the specified position pos in the buffer.
Positions start at 0
param pos byte offset into buffer, pos must be at a character boundary
return Unicode UTF-8 encoded character
return length of Unicode encoded character in len
*/
unsigned int get_char_at(int pos, int &len) const;
/**
Returns the raw byte at the specified position pos in the buffer.
Positions start at 0

Wyświetl plik

@ -242,7 +242,7 @@ protected:
void eval_s2n();
void sendsymbol(int sym);
void sendbit(int bit);
void sendchar(unsigned char c);
void sendchar(unsigned int c);
void sendidle();
void flushtx();
void clearbits();

Wyświetl plik

@ -25,6 +25,7 @@ private:
static std::string bkgnd[];
std::string fline;
std::string nuline;
std::string bwsrline[MAXCHANNELS];
int bwsrfreq[MAXCHANNELS];
@ -36,6 +37,8 @@ private:
int cols[2];
char szLine[32];
size_t nchars;
size_t linechars[32];
unsigned char firstUTF8[32];
public:
static int cwidth;
@ -54,7 +57,7 @@ public:
void setfont(Fl_Font font, int sz) { fnt = font; siz = sz; evalcwidth();}
void columns(int a) { cols[0] = a; cols[1] = 0; column_widths(cols); }
void resize(int x, int y, int w, int h);
void addchr(int ch, int freq, char c, int md);
void addchr(int ch, int freq, unsigned char c, int md);
std::string freqformat (int i);
void set_freq(int i, int freq);
void clearline(int i) { bwsrline[i] = ""; }

Wyświetl plik

@ -0,0 +1,31 @@
// ----------------------------------------------------------------------------
// utf8file_io.h
//
// Copyright (C) 2012
// 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 3 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 this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef UTF8_FILE_IO
#define UTF8_FILE_IO
#include <string>
int UTF8_readfile ( const char *file, std::string &textread );
int UTF8_writefile( const char *file, std::string &textwrite );
#endif

Wyświetl plik

@ -176,7 +176,7 @@ void cAdifIO::fillfield (int fieldnum, char *buff)
static void write_rxtext(const char *s)
{
ReceiveText->add(s);
ReceiveText->addstr(s);
}
void cAdifIO::do_readfile(const char *fname, cQsoDb *db)

Wyświetl plik

@ -315,7 +315,7 @@ int comparerecs (const void *rp1, const void *rp2) { // rp1 needle, rp2 haystack
static void rxtext(const char *s)
{
ReceiveText->add(s);
ReceiveText->addstr(s);
}
void merge_recs( cQsoDb *db, cQsoDb *mrgdb ) // (haystack, needle)

Wyświetl plik

@ -810,11 +810,20 @@ void mfsk::sendbit(int bit)
}
}
void mfsk::sendchar(unsigned char c)
void mfsk::sendchar(unsigned int c)
{
const char *code = varienc(c);
while (*code)
sendbit(*code++ - '0');
const char *code;
if (c & 0xFF00) { // UTF-8 character send two bytes
unsigned char c1 = (c >> 8) & 0xFF;
unsigned char c2 = (c & 0xFF);
code = varienc(c1);
while (*code) sendbit(*code++ - '0');
code = varienc(c2);
while (*code) sendbit(*code++ - '0');
} else {
code = varienc(c);
while (*code) sendbit(*code++ - '0');
}
put_echo_char(c);
}

Wyświetl plik

@ -753,7 +753,7 @@ void pskmail_notify_rsid(trx_mode mode)
for (int ii=0; ii < n; ii++)
WriteARQSysV((unsigned char)buf[ii]);
#endif
ReceiveText->add(buf, FTextBase::CTRL);
ReceiveText->addstr(buf, FTextBase::CTRL);
}
}
@ -771,7 +771,7 @@ void pskmail_notify_s2n(double s2n_ncount, double s2n_avg, double s2n_stddev)
for (int ii=0; ii < n; ii++)
WriteARQSysV((unsigned char)buf[ii]);
#endif
ReceiveText->add(buf, FTextBase::CTRL);
ReceiveText->addstr(buf, FTextBase::CTRL);
}
}

Wyświetl plik

@ -48,6 +48,7 @@
#include "logsupport.h"
#include "icons.h"
#include "weather.h"
#include "utf8file_io.h"
#include <FL/Fl.H>
#include <FL/filename.H>
@ -1865,7 +1866,7 @@ void queue_reset()
static void postQueue(std::string s)
{
ReceiveText->add(s.c_str(), FTextBase::CTRL);
ReceiveText->addstr(s, FTextBase::CTRL);
}
void queue_execute()
@ -2080,7 +2081,7 @@ LOG_INFO("loading: %s", Filename.c_str());
if (progdefaults.DisplayMacroFilename) {
string Macroset;
Macroset.assign("\nMacros: ").append(progStatus.LastMacroFile).append("\n");
ReceiveText->add(Macroset.c_str());
ReceiveText->addstr(Macroset);
}
}
@ -2105,7 +2106,7 @@ void MACROTEXT::openMacroFile()
if (progdefaults.DisplayMacroFilename) {
string Macroset;
Macroset.assign("\nMacros: ").append(progStatus.LastMacroFile).append("\n");
ReceiveText->add(Macroset.c_str());
ReceiveText->addstr(Macroset);
}
}
@ -2273,7 +2274,8 @@ void MACROTEXT::timed_execute()
queue_reset();
TransmitText->clear();
text2send = expandMacro(exec_string);
TransmitText->add(text2send.c_str());
TransmitText->add_text(text2send);
// TransmitText->addstr(text2send);
exec_string.clear();
active_modem->set_stopflag(false);
start_tx();
@ -2293,7 +2295,8 @@ void MACROTEXT::execute(int n)
}
if (progStatus.repeatMacro == -1)
TransmitText->add( text2send.c_str() );
TransmitText->add_text( text2send );
// TransmitText->addstr( text2send );
else {
size_t p = std::string::npos;
text2send = text[n];
@ -2301,7 +2304,8 @@ void MACROTEXT::execute(int n)
text2send[p] = '[';
while ((p = text2send.find('>')) != std::string::npos)
text2send[p] = ']';
TransmitText->add( text2send.c_str() );
TransmitText->add_text( text2send );
// TransmitText->addstr( text2send );
}
text2send.clear();
@ -2367,7 +2371,32 @@ static std::string mtext =
";
void MACROTEXT::saveMacros(const std::string& fname) {
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
std::string work;
std::string output;
char temp[200];
output.assign(mtext);
for (int i = 0; i < MAXMACROS; i++) {
snprintf(temp, sizeof(temp), "\n//\n// Macro # %d\n/$ %d %s\n",
i+1, i, macros.name[i].c_str());
output.append(temp);
work = macros.text[i];
size_t pos;
pos = work.find('\n');
while (pos != std::string::npos) {
work.insert(pos, "\\n");
pos = work.find('\n', pos + 3);
}
output.append(work).append("\n");
}
UTF8_writefile(fname.c_str(), output);
#else
std::string work;
ofstream mfile(fname.c_str());
mfile << mtext;
for (int i = 0; i < MAXMACROS; i++) {
@ -2384,6 +2413,9 @@ void MACROTEXT::saveMacros(const std::string& fname) {
}
mfile << "\n";
mfile.close();
#endif
changed = false;
}

Wyświetl plik

@ -0,0 +1,165 @@
// ----------------------------------------------------------------------------
// utf8file_io.cxx
//
// Copyright (C) 2012
// 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 3 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 this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Text_Buffer.H>
#include <FL/fl_ask.H>
#include "utf8file_io.h"
#include "icons.h"
#define linelen 1024
//----------------------------------------------------------------------
// filter that produces, from an input stream fed by reading from fp,
// a UTF-8-encoded output stream written in buffer.
// Input can be UTF-8. If it is not, it is decoded with CP1252.
// Output is UTF-8.
// *input_was_changed is set to true if the input was not strict UTF-8
// so output differs from input.
//----------------------------------------------------------------------
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
#include <FL/fl_utf8.h>
static int utf8_read_(
char *buffer, int buflen,
char *line, int sline, char *endline,
FILE *fp,
bool *input_was_changed )
{
char *p, *q, multibyte[5];
int l, lp, lq, r;
unsigned u;
p = line;
q = buffer;
while (q < buffer + buflen) {
if (p >= endline) {
r = fread(line, 1, sline, fp);
endline = line + r;
if (r == 0) return q - buffer;
p = line;
}
l = fl_utf8len1(*p);
if (p + l > endline) {
memmove(line, p, endline - p);
endline -= (p - line);
r = fread(endline, 1, sline - (endline - line), fp);
endline += r;
p = line;
if (endline - line < l) break;
}
while ( l > 0) {
u = fl_utf8decode(p, p+l, &lp);
lq = fl_utf8encode(u, multibyte);
if (lp != l || lq != l) *input_was_changed = true;
if (q + lq > buffer + buflen) {
memmove(line, p, endline - p);
endline -= (p - line);
return q - buffer;
}
memcpy(q, multibyte, lq);
q += lq;
p += lp;
l -= lp;
}
}
memmove(line, p, endline - p);
endline -= (p - line);
return q - buffer;
}
static const char file_encoding_warning_message[] =
"Input file was not UTF-8 encoded.\n"
"Text has been converted to UTF-8.";
//----------------------------------------------------------------------
// Read text from a file.
// utf8_input_filter accepts UTF-8 or CP1252 as input encoding.
// Output is always UTF-8 encoded std::string
//----------------------------------------------------------------------
int UTF8_readfile(const char *file, std::string &output)
{
FILE *fp;
if (!(fp = fl_fopen(file, "r")))
return 1;
char buffer[2 * linelen + 1], line[linelen];
char *endline = line;
int l;
bool input_file_was_transcoded = false;
while (true) {
l = utf8_read_(
buffer, linelen * 2 + 1,
line, linelen, endline,
fp,
&input_file_was_transcoded);
if (l == 0) break;
buffer[l] = 0;
output.append(buffer);
}
int e = ferror(fp) ? 2 : 0;
fclose(fp);
if ( (!e) && input_file_was_transcoded)
fl_alert2("%s", file_encoding_warning_message);
return e;
}
//----------------------------------------------------------------------
// Write text std::string to file.
// Unicode safe.
//----------------------------------------------------------------------
int UTF8_writefile( const char *file, std::string &text )
{
FILE *fp;
if (!(fp = fl_fopen(file, "w")))
return 1;
int buflen = text.length();
int r = fwrite( text.c_str(), 1, buflen, fp );
int e = (r != buflen) ? 1 : ferror(fp) ? 2 : 0;
fclose(fp);
return e;
}
#else
int UTF8_readfile(const char *file, std::string &output)
{
return 0;
}
int UTF8_writefile( const char *file, std::string &text )
{
return 0;
}
#endif

Wyświetl plik

@ -2234,7 +2234,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
XMLRPC_LOCK;
REQ_SYNC(&FTextTX::add_text, TransmitText, params.getString(0).c_str());
REQ_SYNC(&FTextTX::add_text, TransmitText, params.getString(0));
*retval = xmlrpc_c::value_nil();
}
};
@ -2252,7 +2252,7 @@ public:
XMLRPC_LOCK;
vector<unsigned char> bytes = params.getBytestring(0);
bytes.push_back(0);
REQ_SYNC(&FTextTX::add_text, TransmitText, (const char*)&bytes[0]);
REQ_SYNC(&FTextTX::add_text, TransmitText, string((const char*)&bytes[0]));
*retval = xmlrpc_c::value_nil();
}

Wyświetl plik

@ -111,26 +111,65 @@ int mt63::tx_process()
put_echo_char(c);
if (c > 127) {
c &= 127;
Tx->SendChar(127);
if (c & 0xFF00) { // UTF-8 character send two bytes
unsigned char c1 = (c >> 8) & 0xFF;
unsigned char c2 = (c & 0xFF);
if (c1 > 127) {
c1 &= 127;
Tx->SendChar(127);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
Tx->Comb.Output.Data[i] /= maxval;
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
}
Tx->SendChar(c1);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
for (int i = 0; i < Tx->Comb.Output.Len; i++) {
Tx->Comb.Output.Data[i] /= maxval;
}
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
if (c2 > 127) {
c2 &= 127;
Tx->SendChar(127);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
Tx->Comb.Output.Data[i] /= maxval;
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
}
Tx->SendChar(c2);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++) {
Tx->Comb.Output.Data[i] /= maxval;
}
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
} else {
if (c > 127) {
c &= 127;
Tx->SendChar(127);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
Tx->Comb.Output.Data[i] /= maxval;
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
}
Tx->SendChar(c);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++) {
Tx->Comb.Output.Data[i] /= maxval;
}
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
}
Tx->SendChar(c);
for (int i = 0; i < Tx->Comb.Output.Len; i++)
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
maxval = fabs(Tx->Comb.Output.Data[i]);
for (int i = 0; i < Tx->Comb.Output.Len; i++) {
Tx->Comb.Output.Data[i] /= maxval;
}
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
return 0;
}

Wyświetl plik

@ -141,7 +141,6 @@ int olivia::unescape(int c)
int olivia::tx_process()
{
int c = 0, len = 0;
unsigned char ch;
if (tones != progdefaults.oliviatones ||
bw != progdefaults.oliviabw ||
@ -160,28 +159,46 @@ int olivia::tx_process()
// modem already has that many characters buffered, don't try
// to read any more. If stopflag is set, we will always read
// whatever there is.
if (stopflag || (Tx->GetReadReady() < Tx->BitsPerSymbol)) {
if (!stopflag && (c = get_tx_char()) == 0x03)
stopflag = true;
if (stopflag)
Tx->Stop();
else {
/* Replace un-representable characters with a dot */
if (c == -1)
c = 0;
if (c > (progdefaults.olivia8bit ? 255 : 127))
c = '.';
if (c > 127) {
c &= 127;
Tx->PutChar(127);
if (c & 0xFF00) { // UTF-8 character send two bytes
unsigned char c1 = (c >> 8) & 0xFF;
unsigned char c2 = (c & 0xFF);
if (c1 > (progdefaults.olivia8bit ? 255 : 127))
c1 = '.';
if (progdefaults.olivia8bit && (c1 > 127)) {
c1 &= 127;
Tx->PutChar(127);
}
Tx->PutChar(c1);
if (c2 > (progdefaults.olivia8bit ? 255 : 127))
c2 = '.';
if (progdefaults.olivia8bit && (c2 > 127)) {
c2 &= 127;
Tx->PutChar(127);
}
Tx->PutChar(c2);
} else {
if (c > (progdefaults.olivia8bit ? 255 : 127))
c = '.';
if (!progdefaults.olivia8bit && (c > 127)) {
c &= 127;
Tx->PutChar(127);
}
Tx->PutChar(c);
}
Tx->PutChar(c);
}
}
if (Tx->GetChar(ch) > 0)
if ((c = unescape(ch)) != -1)
put_echo_char(c);
if (c != 0 && c != 0x03) {
put_echo_char(c);
}
if ((len = Tx->Output(txfbuffer)) > 0)
ModulateXmtr(txfbuffer, len);

Wyświetl plik

@ -46,6 +46,8 @@
#include "pskeval.h"
#include "ascii.h"
#include "debug.h"
extern waterfall *wf;
// Change the following for DCD low pass filter adjustment
@ -1100,7 +1102,11 @@ int psk::tx_process()
tx_bit(0);
}
} else {
tx_char(c);
if (c & 0xFF00) {
tx_char((c >> 8) & 0xFF);
tx_char(c & 0xFF);
} else
tx_char(c);
put_echo_char(c);
}
return 0;

Wyświetl plik

@ -166,10 +166,10 @@ void viewpsk::rx_bit(int ch, int bit)
if ((channel[ch].shreg & 3) == 0) {
c = psk_varicode_decode(channel[ch].shreg >> 2);
channel[ch].shreg = 0;
if (c == -1) return;
if (c == '\n' || c == '\r') c = ' ';
if (isprint(c)) {
REQ(&viewaddchr, ch, (int)channel[ch].frequency, c, viewmode);
}
if (iscntrl(c & 0xFF)) return;
REQ(&viewaddchr, ch, (int)channel[ch].frequency, c, viewmode);
}
}

Wyświetl plik

@ -830,7 +830,7 @@ static void notify_notify(const notify_t& n)
note_qrg(false, text.c_str(), text.c_str() + p + strlen("$RX_MARKER"), n.mode, 0LL, n.afreq);
}
else
ReceiveText->add(text.c_str());
ReceiveText->addstr(text);
}
// expand macros and append to transmit text

Wyświetl plik

@ -1816,12 +1816,13 @@ void waterfall::insert_text(bool check)
if ((i = progdefaults.WaterfallClickText.find("<FREQ>")) != string::npos) {
string s = progdefaults.WaterfallClickText;
s[i] = '\0';
ReceiveText->add(s.c_str());
ReceiveText->addstr(s);
note_qrg(false);
ReceiveText->add(s.c_str() + i + strlen("<FREQ>"));
// ReceiveText->addstr(s);
// ReceiveText->addstr(s.c_str() + i + strlen("<FREQ>"));
}
else
ReceiveText->add(progdefaults.WaterfallClickText.c_str(), FTextView::SKIP);
ReceiveText->addstr(progdefaults.WaterfallClickText, FTextView::SKIP);
}
static void find_signal_text(void)

Wyświetl plik

@ -258,7 +258,7 @@ out:
///
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
void FTextRX::add(unsigned char c, int attr)
void FTextRX::add(unsigned int c, int attr)
{
if (c == '\r')
return;
@ -277,8 +277,17 @@ void FTextRX::add(unsigned char c, int attr)
tbuf->remove(tbuf->length() - 1, tbuf->length());
sbuf->remove(sbuf->length() - 1, sbuf->length());
if (s_text.length()) {
s_text.erase(s_text.end() - 1);
s_style.erase(s_style.end() - 1);
if (tbuf->byte_at(tbuf->length() - 1 ) & 0x80) { //UTF-8 character
s_text.erase(s_text.end() - 2);
s_style.erase(s_style.end() - 2);
tbuf->remove(tbuf->length() - 2, tbuf->length());
sbuf->remove(sbuf->length() - 2, sbuf->length());
} else {
s_text.erase(s_text.end() - 1);
s_style.erase(s_style.end() - 1);
tbuf->remove(tbuf->length() - 1, tbuf->length());
sbuf->remove(sbuf->length() - 1, sbuf->length());
}
}
break;
case '\n':
@ -835,6 +844,7 @@ FTextTX::FTextTX(int x, int y, int w, int h, const char *l)
memcpy(menu + TX_MENU_CUT, FTextEdit::menu, (FTextEdit::menu->size() - 1) * sizeof(*FTextEdit::menu));
context_menu = menu;
init_context_menu();
utf8_txpos = txpos = 0;
}
/// Handles fltk events for this widget.
@ -870,6 +880,7 @@ void FTextTX::clear(void)
{
FTextEdit::clear();
txpos = 0;
utf8_txpos = 0;
bkspaces = 0;
PauseBreak = false;
}
@ -879,8 +890,9 @@ void FTextTX::clear(void)
///
void FTextTX::clear_sent(void)
{
tbuf->remove(0, txpos);
clear();
txpos = 0;
utf8_txpos = 0;
bkspaces = 0;
PauseBreak = false;
set_word_wrap(restore_wrap);
@ -901,9 +913,9 @@ bool FTextTX::eot(void)
/// @return The next character, or ETX if the transmission has been paused, or
/// NUL if no text should be transmitted.
///
int FTextTX::nextChar(void)
unsigned int FTextTX::nextChar(void)
{
int c;
unsigned int c;
if (bkspaces) {
--bkspaces;
@ -913,40 +925,58 @@ int FTextTX::nextChar(void)
PauseBreak = false;
c = 0x03;
}
else if (insert_position() <= txpos) // empty buffer or cursor inside transmitted text
c = -1;
else {
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
if ((c = static_cast<unsigned char>(tbuf->char_at(txpos)))) {
#else
if ((c = static_cast<unsigned char>(tbuf->character(txpos)))) {
#endif
else if (insert_position() <= utf8_txpos) { // empty buffer or cursor inside transmitted text
c = -1;
} else {
int n;
if ((c = tbuf->get_char_at(utf8_txpos, n))) {
//LOG_DEBUG("%04X, %d, %d ", c & 0xFFFF, utf8_txpos, n);
if (n == 1) c &= 0xFF;
REQ(FTextTX::changed_cb, utf8_txpos, 0, 0, -1, static_cast<const char *>(0), this);
REQ(FTextTX::changed_cb, utf8_txpos+1, 0, 0, -1, static_cast<const char *>(0), this);
++txpos;
utf8_txpos += n;
} else
c = -1;
#else
else if (insert_position() <= txpos) { // empty buffer or cursor inside transmitted text
c = -1;
} else {
if ((c = static_cast<unsigned char>(tbuf->character(txpos)))) {
REQ(FTextTX::changed_cb, txpos, 0, 0, -1, static_cast<const char *>(0), this);
++txpos;
REQ(FTextTX::changed_cb, txpos, 0, 0, -1,
static_cast<const char *>(0), this);
}
#endif
}
return c;
}
void FTextTX::add_text(const char *s)
// called by xmlrpc thread
// called by macro execution
void FTextTX::add_text(string s)
{
while (*s) {
if (*s == '\b') {
for (size_t n = 0; n < s.length(); n++) {
if (s[n] == '\b') {
int ipos = insert_position();
if (tbuf->length()) {
if (ipos > 0 && txpos == ipos) {
bkspaces++;
txpos--;
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
int nn;
tbuf->get_char_at(utf8_txpos, nn);
utf8_txpos -= nn;
#endif
}
tbuf->remove(tbuf->length() - 1, tbuf->length());
sbuf->remove(sbuf->length() - 1, sbuf->length());
redraw();
}
s++;
} else
add(*s++, RECV);
} else {
LOG_DEBUG("%04x ", s[n] & 0x00FF);
add(s[n] & 0xFF, RECV);
}
}
}
@ -1032,22 +1062,36 @@ int FTextTX::handle_key(int key)
// In CW mode: Tab pauses, skips rest of buffer, applies the
// SKIP style, then resumes sending when new text is entered.
// Ctrl-tab does the same thing as for all other modes.
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
if (utf8_txpos != insert_position())
insert_position(utf8_txpos);
else
insert_position(tbuf->length());
if (!(Fl::event_state() & FL_CTRL) && active_modem == cw_modem) {
int n = tbuf->length() - utf8_txpos;
char s[n + 1];
memset(s, FTEXT_DEF + SKIP, n);
s[n] = 0;
sbuf->replace(utf8_txpos, sbuf->length(), s);
insert_position(tbuf->length());
redisplay_range(utf8_txpos, insert_position());
utf8_txpos = insert_position();
}
#else
insert_position(txpos != insert_position() ? txpos : tbuf->length());
if (!(Fl::event_state() & FL_CTRL) && active_modem == cw_modem) {
int n = tbuf->length() - txpos;
char s[n + 1];
memset(s, FTEXT_DEF + SKIP, n);
s[n] = 0;
sbuf->replace(txpos, sbuf->length(), s);
insert_position(tbuf->length());
redisplay_range(txpos, insert_position());
txpos = insert_position();
}
// show_insert_position();
#endif
return 1;
// Move cursor, or search up/down with the Meta/Alt modifiers
// Move cursor, or search up/down with the Meta/Alt modifiers
case FL_Left:
if (Fl::event_state() & (FL_META | FL_ALT)) {
active_modem->searchDown();
@ -1064,12 +1108,21 @@ int FTextTX::handle_key(int key)
case FL_BackSpace:
{
int ipos = insert_position();
#if FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR == 3
if (utf8_txpos == ipos) {
bkspaces++;
if (tbuf->byte_at(ipos - 1) & 0x80) utf8_txpos -= 2;
else utf8_txpos--;
txpos--;
}
#else
if (txpos > 0 && txpos >= ipos) {
if (tbuf->length() >= txpos && txpos > ipos)
return 1;
bkspaces++;
txpos--;
}
#endif
return 0;
}
// alt - 1 / 2 changes macro sets

Wyświetl plik

@ -123,7 +123,6 @@ void FTextBase::add(const char *s, int attr)
memset(a, FTEXT_DEF + attr, n);
a[n] = '\0';
sbuf->replace(insert_position(), insert_position() + n, a);
insert(s);
}

Wyświetl plik

@ -245,14 +245,43 @@ char *Fl_Text_Buffer_mod::text_range(int start, int end) const {
Pos must be at a character boundary.
*/
unsigned int Fl_Text_Buffer_mod::char_at(int pos) const {
if (pos < 0 || pos >= mLength)
return '\0';
if (pos < 0 || pos >= mLength)
return '\0';
IS_UTF8_ALIGNED2(this, (pos))
IS_UTF8_ALIGNED2(this, (pos))
const char *src = address(pos);
return fl_utf8decode(src, 0, 0);
}
const char *src = address(pos);
return *src;
}
/*
Return a UTF-8 character at the given index.
Pos must be at a character boundary.
*/
unsigned int Fl_Text_Buffer_mod::get_char_at(int pos, int &len) const {
if (pos < 0 || pos >= mLength) {
len = 1;
return 0;
}
IS_UTF8_ALIGNED2(this, (pos))
const char *src = address(pos);
unsigned int code;
int codelen;
if (*src & 0x80) { // what should be a multibyte encoding
fl_utf8decode(src, src+2, &codelen);
if (codelen == 2)
code = (*src << 8) | (*(src+1) & 0xFF);
else
code = *src & 0xFF;
} else { // handle the 1-byte utf8 encoding:
code = (*src & 0xFF);
codelen = 1;
}
len = codelen;
return code;
}
/*

Wyświetl plik

@ -73,9 +73,12 @@ pskBrowser::pskBrowser(int x, int y, int w, int h, const char *l)
bwsrfreq[i] = NULLFREQ;
bline = freqformat(i);
if ( i < progdefaults.VIEWERchannels) add(bline.c_str());
linechars[i] = 0;
firstUTF8[i] = 0;
}
nchars = (w - cols[0] - (sbarwidth + 2*BWSR_BORDER)) / cwidth;
nchars = nchars < 1 ? 1 : nchars;
}
void pskBrowser::evalcwidth()
@ -103,15 +106,20 @@ string pskBrowser::freqformat(int i) // 0 < i < channels
case VIEWER_LABEL_AF:
if (freq != NULLFREQ)
snprintf(szLine, sizeof(szLine), "%4d", freq);
else
sprintf(szLine, " ");
break;
case VIEWER_LABEL_RF:
if (freq != NULLFREQ)
snprintf(szLine, sizeof(szLine), "%8.2f", (rfc + (usb ? freq : -freq)) / 1000.0f);
else
sprintf(szLine, " ");
break;
case VIEWER_LABEL_CH:
snprintf(szLine, sizeof(szLine), "%2d", i + 1);
break;
default:
sprintf(szLine, " ");
break;
}
fline = bkselect;
@ -144,30 +152,32 @@ void pskBrowser::swap(int i, int j)
void pskBrowser::resize(int x, int y, int w, int h)
{
if (w) {
size_t nuchars = (w - cols[0] - (sbarwidth + 2 * BWSR_BORDER)) / cwidth;
nuchars = nuchars < 1 ? 1 : nuchars;
string bline;
Fl_Hold_Browser::clear();
for (int i = 0, j = 0; i < progdefaults.VIEWERchannels; i++) {
if (progdefaults.VIEWERascend) j = progdefaults.VIEWERchannels - 1 - i;
else j = i;
size_t len = bwsrline[j].length();
if (len > nuchars)
bwsrline[j] = bwsrline[j].substr(len - nuchars);
bline = freqformat(j);
if (seek_re) {
if (seek_re->match(bwsrline[j].c_str(), REG_NOTBOL | REG_NOTEOL))
bline.append(dkred);
} else if (!progdefaults.myCall.empty() &&
strcasestr(bwsrline[j].c_str(), progdefaults.myCall.c_str()))
bline.append(dkgreen);
bline.append(bwsrline[j]);
Fl_Hold_Browser::add(bline.c_str());
Fl_Hold_Browser::resize(x,y,w,h);
evalcwidth();
nchars = (w - cols[0] - (sbarwidth + 2 * BWSR_BORDER)) / cwidth;
nchars = nchars < 1 ? 1 : nchars;
string bline;
Fl_Hold_Browser::clear();
for (int i = 0, j = 0; i < progdefaults.VIEWERchannels; i++) {
if (progdefaults.VIEWERascend) j = progdefaults.VIEWERchannels - 1 - i;
else j = i;
bwsrline[j].clear();
firstUTF8[j] = 0;
linechars[j] = 0;
// size_t len = bwsrline[j].length();
// if (len > nchars)
// bwsrline[j] = bwsrline[j].substr(len - nchars);
bline = freqformat(j);
if (seek_re) {
if (seek_re->match(bwsrline[j].c_str(), REG_NOTBOL | REG_NOTEOL))
bline.append(dkred);
} else if (!progdefaults.myCall.empty() &&
strcasestr(bwsrline[j].c_str(), progdefaults.myCall.c_str()))
bline.append(dkgreen);
// bline.append(bwsrline[j]);
Fl_Hold_Browser::add(bline.c_str());
}
}
nchars = nuchars;
evalcwidth();
}
Fl_Hold_Browser::resize(x,y,w,h);
}
void pskBrowser::makecolors()
@ -212,45 +222,70 @@ void pskBrowser::makecolors()
bkgnd[1] = tempstr;
}
void pskBrowser::addchr(int ch, int freq, char c, int md) // 0 < ch < channels
void pskBrowser::addchr(int ch, int freq, unsigned char c, int md) // 0 < ch < channels
{
static string nuline;
size_t chars = (w() - cols[0] - (sbarwidth + 2 * BWSR_BORDER)) / cwidth;
chars = chars < 1 ? 1 : chars;
int index = ch;
if (index < 0 || index >= MAXCHANNELS)
if (ch < 0 || ch >= MAXCHANNELS)
return;
bwsrfreq[index] = freq;
if (c < ' ' || c > '~') c = ' ';
if (bwsrline[index].length() == 1 && bwsrline[index][0] == ' ')
bwsrline[index].clear();
if (progdefaults.VIEWERmarquee) {
if (bwsrline[index].length() >= chars )
bwsrline[index].erase(0,1);
} else {
if (bwsrline[index].length() >= chars)
bwsrline[index].clear();
}
bwsrline[index] += c;
if (c == '\n') c = ' ';
if (c < ' ') return;
nuline = freqformat(index);
nchars = (w() - cols[0] - (sbarwidth + 2 * BWSR_BORDER)) / cwidth;
nchars = nchars < 1 ? 1 : nchars;
bwsrfreq[ch] = freq;
if (bwsrline[ch].length() == 1 && bwsrline[ch][0] == ' ') {
bwsrline[ch].clear();
linechars[ch] = 0;
firstUTF8[ch] = 0;
}
if ((linechars[ch] > nchars) && (firstUTF8[ch] == 0)) {
if (progdefaults.VIEWERmarquee) {
while (linechars[ch] > nchars) {
if ((bwsrline[ch][0] & 0x80) == 0x80) // UTF-8 character
bwsrline[ch].erase(0,2);
else
bwsrline[ch].erase(0,1);
linechars[ch]--;
}
} else {
bwsrline[ch].clear();
linechars[ch] = 0;
firstUTF8[ch] = 0;
}
}
if (firstUTF8[ch] != 0) {
bwsrline[ch] += firstUTF8[ch];
bwsrline[ch] += c;
linechars[ch]++;
firstUTF8[ch] = 0;
} else if ((c & 0x80) == 0x80) {
firstUTF8[ch] = c;
return;
} else {
bwsrline[ch] += c;
linechars[ch]++;
}
nuline = freqformat(ch);
if (seek_re) {
if (seek_re->match(bwsrline[index].c_str(), REG_NOTBOL | REG_NOTEOL))
if (seek_re->match(bwsrline[ch].c_str(), REG_NOTBOL | REG_NOTEOL))
nuline.append(dkred);
} else if (!progdefaults.myCall.empty() &&
strcasestr(bwsrline[index].c_str(), progdefaults.myCall.c_str()))
strcasestr(bwsrline[ch].c_str(), progdefaults.myCall.c_str()))
nuline.append(dkgreen);
nuline.append("@.").append(bwsrline[index]);
nuline.append("@.").append(bwsrline[ch]);
if (progdefaults.VIEWERascend)
text(progdefaults.VIEWERchannels - index, nuline.c_str());
text(progdefaults.VIEWERchannels - ch, nuline.c_str());
else
text(index + 1, nuline.c_str());
text(ch + 1, nuline.c_str());
redraw();
}
@ -287,6 +322,7 @@ void pskBrowser::clearch(int n, int freq) // 0 < n < channels
{
bwsrline[n] = " ";
set_freq(n, freq);
redraw();
}
int pskBrowser::freq(int i) { // 1 < i < progdefaults.VIEWERchannels