kopia lustrzana https://github.com/jamescoxon/dl-fldigi
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 characterspull/1/head
rodzic
d2d254e5d3
commit
0d287c667d
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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] = ""; }
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue