summaryrefslogtreecommitdiffstats
path: root/call/call.c
diff options
context:
space:
mode:
authorThomas Osterried <ax25@x-berg.in-berlin.de>2016-02-11 19:00:10 +0100
committerThomas Osterried <ax25@x-berg.in-berlin.de>2016-02-11 19:00:10 +0100
commit11c04b0da3684b8922a094dd293773de3214f876 (patch)
treed9d8e2c11b87cbf774a4e221dbcd63ee83652832 /call/call.c
parent1214e075cc0a93fe2c11997202d653fd2422b4e5 (diff)
UTF-8 support for call.
Patch by Cathryn Mataga. 1. Now supports UTF8 or IBM850 as the encoding style over AX25. 1a. Attention was paid to make sure that wide characters worked with East Asian fonts. 2. Now the screen can be resized. correctly. The program no longer crashes when it is resized. 3. Added a scrollback buffer. Use the up and down arrow keys or the page up/page down keys to scroll through history. After the screen begins scrolling, press 'up arrow' to view history. 4. Many visual quirks have been fixed. This version is now dependent on iconv and wide character versions of ncurses, which I think should be everywhere these days. Signed-off-by: Thomas Osterried <ax25@x-berg.in-berlin.de>
Diffstat (limited to 'call/call.c')
-rw-r--r--call/call.c1010
1 files changed, 745 insertions, 265 deletions
diff --git a/call/call.c b/call/call.c
index 89d3264..f9fe6eb 100644
--- a/call/call.c
+++ b/call/call.c
@@ -36,7 +36,14 @@
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
-#include <curses.h>
+#define __USE_XOPEN
+#include <wchar.h>
+#include <wctype.h>
+#define _XOPEN_SOURCE_EXTENDED 1
+#include <ncursesw/ncurses.h>
+#include <locale.h>
+#include <iconv.h>
+#include <sys/ioctl.h>
#include <netax25/ax25.h>
#include <netrom/netrom.h>
@@ -79,10 +86,13 @@ static char *port;
static char *mycall;
static int stdin_is_tty = 1;
+static iconv_t ibm850toutf8 = 0, wcharttoibm850 = 0, wcharttoutf8 = 0, utf8towchart = 0;
volatile int interrupted = FALSE;
+static int sigwinchsignal = FALSE;
int paclen;
int fd;
+int curson = 1;
int wait_for_remote_disconnect = FALSE;
static struct timespec inactivity_timeout;
@@ -104,7 +114,7 @@ typedef struct {
WINDOW *ptr;
int max_y;
int max_x;
- char string[MAX_BUFLEN];
+ wchar_t string[MAX_BUFLEN];
unsigned long bytes;
int curs_pos;
} t_win;
@@ -113,10 +123,233 @@ typedef struct {
#define SLAVEMODE 002 /* Menu mode */
#define RAWMODE 004 /* mode used by earlier versions */
+#define ORIGINALENCODING 0
+#define UTF8ENCODING 1
+
+#define SCROLLBACKSIZE 5000
+
+typedef struct {
+ char *str;int len;
+}scrollbackstruct;
+
+
+static scrollbackstruct scrollback[SCROLLBACKSIZE];
+static int topscroll=0, lastscroll = 0, scrolledup=0, eatchar = 0;
+static char inbuf[MAX_BUFLEN];static int inbuflen = 0, inbufwid = 0;
+static char incharbuf[6];static int incharbuflen = 0;
+void statline(int mode, char *s);
+
+void addscrollline(char *s, int len)
+{
+ scrollback[lastscroll].str = malloc(len);
+ memcpy(scrollback[lastscroll].str, s, len);
+ scrollback[lastscroll].len = len;
+ if (++lastscroll >= SCROLLBACKSIZE)lastscroll = 0;
+ if (lastscroll == topscroll){
+ free(scrollback[topscroll].str);
+ if (++topscroll >= SCROLLBACKSIZE)topscroll = 0;
+ }
+}
+
+// Notes: Japanese, Chinese and Korean characters mostly take up two
+// characters in width. These characters return 2 via
+// wcwidth to let the code know that they require two
+// spaces. Mono-space fonts/ncurses seems to work correctly with
+// East Asian characters.
+//
+// There are also some characters that return a wcwidth of 0. I'm
+// not sure about all of them, but some of the 0 width characters
+// add a mark above or below a character. In order for these marks
+// to appear correctly, the previous character and the overstrike
+// must be drawn together. using wmove and drawing the accent doesn't
+// work.
+//
+// There are some other characters that have functions, and these
+// are not supported using a print to the screen. South Asian
+// fonts are complicated. I don't believe south asian fonts work
+// correctly from the Linux command line (as of late 2009). They
+// print but don't combine. The result is distorted.
+//
+// Many characters, as of 12/09, are too wide for a single space
+// in the font, although they return a wcwidth of 1. I suspect
+// this is due to these characters not being part of the mono-spaced
+// font and are instead pulled from an alternate font. These
+// characters also glitch in xterm, vim and other ncurses
+// software. I suspect this is actually a font bug, and any character
+// that returns wcwidth=1 in a monospaced font should be
+// monospaced.
+//
+
+
+int widthchar(char *s, size_t bytes, int xpos)
+{
+ wchar_t c;int width;
+ char *outbuf=(char *) &c;
+ size_t outsize = sizeof(wchar_t);
+ // Note: Actually need to check if bad UTF8 characters show as ?
+ if (iconv(utf8towchart, &s, &bytes, &outbuf, &outsize)< 0)return 0;
+ if (c == 9){
+ return 8 - (xpos & 7);
+ }
+ width = wcwidth(c);
+ if (width < 0)return 0;
+ return width;
+}
+
+
+int completecharlen(char *s)
+{
+ unsigned ut = (unsigned char)s[0];int clen;
+ if (ut <= 0x80)clen = 1;
+ else if ((ut >= 192) && (ut < 192+32))clen = 2;
+ else if ((ut >= 224) && (ut < 224+16))clen = 3;
+ else if ((ut >= 240) && (ut < 240+8))clen = 4;
+ else if ((ut >= 248) && (ut < 248+4))clen = 5;
+ else if ((ut >= 252) && (ut < 252+2))clen = 6;
+ else clen = 1; // bad
+ return clen;
+}
+
+
+// Must check for COLS while redrawing from history. Or otherwise the text
+// wraps around and does strange things.
+int waddnstrcolcheck(WINDOW *win, char *s, int len, int twidth)
+{
+ int n;
+ for (twidth = 0,n=0;n<len;){
+ int cwidth = completecharlen(&s[n]), width;
+ if (n + cwidth > len)return twidth; // Error condition
+ width = widthchar(&s[n], cwidth, twidth);
+ if (twidth+width > COLS)return twidth; //
+ waddnstr(win, &s[n], cwidth);
+ n += cwidth;
+ twidth += width;
+ }
+ return twidth;
+}
+
+// Update a line on the screen from the backscroll buffer.
+void updateline(int screeny, int yfrom, t_win *win_in, int mode, t_win *win_out)
+{
+ wmove(win_in->ptr, screeny, 0);
+ if (yfrom == lastscroll){
+ int twidth = 0;
+ if (inbuflen > 0)
+ twidth = waddnstrcolcheck(win_in->ptr, inbuf, inbuflen, 0);
+ if (mode == SLAVEMODE){
+ char obuf[MAX_BUFLEN];
+ char *inbuf = (char *)win_out->string, *outbuf = obuf;
+ size_t insize = win_out->bytes * sizeof(wchar_t), outsize = MAX_BUFLEN;
+ iconv(wcharttoutf8, &inbuf, &insize, &outbuf, &outsize);
+ waddnstrcolcheck(win_in->ptr, obuf, MAX_BUFLEN - outsize, twidth);
+ win_out->curs_pos = win_out->bytes;
+ }
+ }
+ else {
+ waddnstrcolcheck(win_in->ptr, scrollback[yfrom].str, scrollback[yfrom].len, 0);
+ }
+}
+
+// Cursor in SLAVE mode while scrolling looks broken.
+// Cursor in TALK mode is always good, because it's on the bottom window
+void checkcursor(int mode)
+{
+ int newcursor;
+ if ((mode == SLAVEMODE) && scrolledup)newcursor = 0;
+ else newcursor = 1;
+ if (curson != newcursor){
+ curs_set(newcursor);
+ curson = newcursor;
+ }
+}
+
+/* For CJK, it's important to keep the cursor always on the input
+ * window. Otherwise the display is confused */
+static void restorecursor(int mode, t_win *win_out)
+{
+ checkcursor(mode);
+ if (mode != RAWMODE){
+ int x,y;
+ getyx(win_out->ptr, y, x);// Must restore input cursor location.
+ wmove(win_out->ptr,y, x);
+ wrefresh(win_out->ptr);
+ }
+}
+
+void redrawscreen(t_win *win_in, int mode, t_win *win_out)
+{
+ int y, storedlines;
+ if (lastscroll >= topscroll) storedlines = lastscroll - topscroll;
+ else storedlines = lastscroll + SCROLLBACKSIZE - topscroll;
+ // Note it's stored lines + 1 extra line for text input.
+ for (y=0;(y<=win_in->max_y) && (y <= storedlines);y++){
+ int linefrom;
+ if (storedlines <= win_in->max_y){// This is a little confusing.
+ linefrom = topscroll + y;// The screen scrolls top down at start
+ }
+ else linefrom = lastscroll -scrolledup - (win_in->max_y) + y;
+ while (linefrom < 0)linefrom += SCROLLBACKSIZE;
+ while (linefrom >= SCROLLBACKSIZE)linefrom -= SCROLLBACKSIZE;
+ updateline(y,linefrom , win_in, mode, win_out);
+ }
+ checkcursor(mode);
+}
+
+void scrolltext(t_win *win_in, int lines, int mode, t_win *win_out)
+{
+ int topline, storedlines;
+ int y;
+ int wasscrolledup;
+ if (scrolledup + lines < 0){
+ lines = -scrolledup;
+ }
+ // storedlines = Lines stored in buffer.
+ if (lastscroll >= topscroll) storedlines = lastscroll - topscroll;
+ else storedlines = lastscroll + SCROLLBACKSIZE - topscroll;
+ // The max scrolling we can do is the # of lines stored - the
+ // screen size.
+ topline = storedlines - win_in->max_y;
+ if (topline < 0)topline = 0;
+ if (scrolledup + lines > topline){
+ lines = topline - scrolledup;
+ }
+ if (!lines)return;
+ wasscrolledup = scrolledup;
+ scrolledup += lines;
+ wscrl(win_in->ptr, -lines);
+ scrollok(win_in->ptr, FALSE);
+ if (lines > 0){
+ for (y=0;y<lines;y++){
+ int linefrom = lastscroll -scrolledup - (win_in->max_y) + y;
+ while (linefrom < 0)linefrom += SCROLLBACKSIZE;
+ while (linefrom >= SCROLLBACKSIZE)linefrom -= SCROLLBACKSIZE;
+ updateline(y,linefrom , win_in, mode, win_out);
+ }
+ }
+ else {
+ for (y=-lines-1;y>=0;y--){
+ int linefrom = lastscroll -scrolledup - y;
+ while (linefrom < 0)linefrom += SCROLLBACKSIZE;
+ while (linefrom >= SCROLLBACKSIZE)linefrom -= SCROLLBACKSIZE;
+ updateline(win_in->max_y - y,linefrom , win_in, mode, win_out);
+ }
+
+ }
+ scrollok(win_in->ptr, TRUE);
+ checkcursor(mode);
+ wrefresh(win_in->ptr);
+ if (wasscrolledup && !scrolledup){
+ statline(mode, "");
+ }
+ else if (!wasscrolledup && scrolledup){
+ statline(mode, "Viewing Scrollback");
+ }
+}
+
void usage(void)
{
- fprintf(stderr, "usage: call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-r] [-R]\n");
- fprintf(stderr, " [-s mycall] [-t] [-T timeout] [-v] [-w window] [-W]\n");
+ fprintf(stderr, "usage: call [-8] [-b l|e] [-d] [-h] [-i] [-m s|e] [-p paclen] [-r] [-R]\n");
+ fprintf(stderr, " [-s mycall] [-S] [-t] [-T timeout] [-v] [-w window] [-W]\n");
fprintf(stderr, " port callsign [[via] digipeaters...]\n");
exit(1);
}
@@ -161,6 +394,73 @@ void convert_upper_lower(char *buf, int len)
}
+
+/* Return the with of this character in character blocks. (Normal = 1, CJK=2)
+ * Also for control chracters, return the width of the replacement string.
+ * */
+static int wcwidthcontrol(wchar_t c)
+{
+ int width;
+ cchar_t cc = {0};
+ wchar_t *str;
+ cc.chars[0] = c;
+ str = wunctrl(&cc);
+ if (!str)return 0;
+ width = wcswidth(str, wcslen(str));
+ return width;
+}
+
+/* Return a string to print for a wchar_t. Expand control characters.
+ * Strings returned by wunctrl don't like to be freed. It seems. */
+static wchar_t *wunctrlwchar(wchar_t c)
+{
+ cchar_t cc = {0};
+ wchar_t *str;
+ cc.chars[0] = c;
+ str = wunctrl(&cc);
+ return str;
+}
+
+// For some reason wins_nwstr fails on fedora 12 on some characters
+// but waddnstr works.
+// Draw the entire input buffer when adding text.
+// The fonts that do overstrike fail when written one char at a time.
+void drawinbuf(WINDOW *w, wchar_t *string, int bytes, int cur_pos)
+{
+ int n, x, cursorx, xpos, ypos, width;
+ getyx(w, ypos, xpos);// Assume cursor to be at position of current char to draw.
+ x = xpos;cursorx = xpos;
+ // cur_pos-1 = the chracter that was just added.
+ for (n=cur_pos-2;n>=0;n--){// Move x position to start of string or 0
+ width = wcwidthcontrol(string[n]);
+ if (x >= width)x -= width;
+ else x = 0;
+ }
+ wmove(w, ypos, x);
+ for (n=0;n<bytes;n++){
+ char obuf[MAX_BUFLEN];
+ char *inbuf, *outbuf = obuf;
+ size_t insize, outsize = MAX_BUFLEN;
+ wchar_t *str;int len, width;
+ if (n == cur_pos){
+ cursorx = x;
+ }
+ str = wunctrlwchar(string[n]);
+ if (!str)continue;
+ inbuf = (char *) str;
+ len = wcslen(str);
+ insize = len * sizeof(wchar_t);
+ width = wcswidth(str, len);
+ iconv(wcharttoutf8, &inbuf, &insize, &outbuf, &outsize);
+ waddnstr(w, obuf, MAX_BUFLEN-outsize);
+ x += width;
+ }
+ if (cur_pos < bytes){
+ wmove(w,ypos, cursorx);
+ }
+}
+
+
/* Convert linear UNIX date to a MS-DOS time/date pair. */
static char * unix_to_sfbin_date_string(time_t gmt)
@@ -412,6 +712,13 @@ static int connect_to(char *address[])
return fd;
}
+
+static void cmd_sigwinch(int sig)
+{
+ signal(SIGWINCH, cmd_sigwinch);
+ sigwinchsignal = TRUE;
+}
+
void cmd_intr(int sig)
{
interrupted = TRUE;
@@ -428,7 +735,7 @@ void statline(int mode, char *s)
if (oldlen > 0) {
move(0, STATW_STAT);
attron(A_REVERSE);
- for (cnt = 0; cnt < oldlen; cnt++)
+ for (cnt = STATW_STAT; cnt < COLS; cnt++)
addch(' ');
oldlen = 0;
attroff(A_REVERSE);
@@ -441,21 +748,18 @@ void statline(int mode, char *s)
fflush(stdout);
return;
}
- if (strlen(s) > 80 - STATW_STAT)
- s[80 - STATW_STAT] = '\0';
+ if (COLS <= STATW_STAT)return;
+ l = strlen(s);
+ if (l > COLS - STATW_STAT)
+ l = COLS-STATW_STAT;
move(0, STATW_STAT);
attron(A_REVERSE);
- addstr(s);
-
- if (oldlen > strlen(s)) {
- l = oldlen - strlen(s);
- for (cnt = 0; cnt < l; cnt++)
- addch(' ');
- }
+ addnstr(s, l);
+ for (cnt = STATW_STAT+l;cnt < COLS;cnt++)addch(' ');
attroff(A_REVERSE);
- oldlen = strlen(s);
+ oldlen = l;
refresh();
}
@@ -800,6 +1104,10 @@ int start_screen(char *call[])
{
int cnt;
char idString[12];
+ struct winsize winsz = {0};
+
+ if ((ioctl(0, TIOCGWINSZ, &winsz) >= 0) && winsz.ws_row && winsz.ws_col)
+ resizeterm(winsz.ws_row, winsz.ws_col);
sprintf(idString, " %9.9s ", call[0]);
if ((win = initscr()) == NULL)
@@ -811,7 +1119,8 @@ int start_screen(char *call[])
addch(ACS_VLINE);
addstr("--------");
addch(ACS_VLINE);
- for (cnt = STATW_STAT; cnt <= 80; cnt++)
+ move(0, STATW_STAT);
+ for (cnt = STATW_STAT; cnt < COLS; cnt++)
addch(' ');
attroff(A_REVERSE);
@@ -819,8 +1128,8 @@ int start_screen(char *call[])
raw();
nodelay(win, TRUE);
keypad(win, TRUE);
+ curson = 1;
refresh();
-
return 0;
}
@@ -841,7 +1150,8 @@ int start_slave_mode(wint * wintab, t_win * win_in, t_win * win_out)
win_out->curs_pos = 0;
win_in->bytes = 0;
win_in->curs_pos = 0;
-
+ redrawscreen(win_in, SLAVEMODE, win_out);
+ wrefresh(win_in->ptr);
return 0;
}
@@ -872,15 +1182,16 @@ int start_talk_mode(wint * wintab, t_win * win_in, t_win * win_out)
scrollok(win_out->ptr, TRUE);
wclear(win_out->ptr);
- wrefresh(win_out->ptr);
wclear(win_in->ptr);
- wrefresh(win_in->ptr);
win_out->bytes = 0;
win_out->curs_pos = 0;
win_in->bytes = 0;
win_out->curs_pos = 0;
-
+ redrawscreen(win_in, TALKMODE, win_out);
+ restorecursor(TALKMODE, win_out);
+ wrefresh(win_in->ptr);
+ wrefresh(win_out->ptr);
return 0;
}
@@ -931,168 +1242,208 @@ int change_mode(int oldmode, int newmode, wint * wintab, t_win * win_in,
break;
}
+ scrolledup = 0;
return newmode;
}
-void writeincom(int mode, t_win * win_in, unsigned char buf[], int bytes)
+static void reinit_mode(int mode, wint * wintab, t_win * win_in, t_win * win_out, char *call[])
{
- int cnt;
-
- if (mode & RAWMODE) {
- while (write(STDOUT_FILENO, buf, bytes) == -1) {
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- usleep(100000);
- continue;
- }
- exit(1);
- }
- return;
- }
- for (cnt = 0; cnt < bytes; cnt++) {
- switch (buf[cnt]) {
- case 201:
- case 218:
- waddch(win_in->ptr, ACS_ULCORNER);
- break;
- case 187:
- case 191:
- waddch(win_in->ptr, ACS_URCORNER);
- break;
- case 200:
- case 192:
- waddch(win_in->ptr, ACS_LLCORNER);
- break;
- case 188:
- case 217:
- waddch(win_in->ptr, ACS_LRCORNER);
- break;
- case 204:
- case 195:
- waddch(win_in->ptr, ACS_LTEE);
- break;
- case 185:
- case 180:
- waddch(win_in->ptr, ACS_RTEE);
- break;
- case 203:
- case 194:
- waddch(win_in->ptr, ACS_TTEE);
- break;
- case 202:
- case 193:
- waddch(win_in->ptr, ACS_BTEE);
- break;
- case 205:
- case 196:
- waddch(win_in->ptr, ACS_HLINE);
- break;
- case 186:
- case 179:
- waddch(win_in->ptr, ACS_VLINE);
- break;
- case 129:
- waddch(win_in->ptr, 252); /*u umlaut */
- break;
- case 132:
- waddch(win_in->ptr, 228); /*a umlaut */
- break;
- case 142:
- waddch(win_in->ptr, 196); /*A umlaut */
- break;
- case 148:
- waddch(win_in->ptr, 246); /*o umlaut */
- break;
- case 153:
- waddch(win_in->ptr, 214); /*O umlaut */
- break;
- case 154:
- waddch(win_in->ptr, 220); /*U umlaut */
- break;
- case 225:
- waddch(win_in->ptr, 223); /*sz */
- break;
- default:
- {
- if (buf[cnt] > 127)
- waddch(win_in->ptr, '.');
- else
- waddch(win_in->ptr, buf[cnt]);
- }
- }
+ switch (mode) {
+ case RAWMODE:
+ break;
+ case TALKMODE:// Clear the screen and re-init. Which looks awful.
+ wclear(win_out->ptr);
+ wrefresh(win_out->ptr);
+ wclear(win_in->ptr);
+ //wrefresh(win_in->ptr);
+ wintab->next = 0;
+ endwin();
+ start_screen(call);
+ start_talk_mode(wintab, win_in, win_out);
+ restorecursor(mode, win_out);
+ break;
+ case SLAVEMODE:// Also fix me.
+ wclear(win_out->ptr);
+ //wrefresh(win_out->ptr);
+ wintab->next = 0;
+ endwin();
+ start_screen(call);
+ start_slave_mode(wintab, win_in, win_out);
+ restorecursor(mode, win_out);
+ break;
}
-
-/* waddnstr(win_in->ptr, buf, bytes); */
- wrefresh(win_in->ptr);
}
-int getstring(wint * wintab, char text[], char buf[])
+void waddnstrcrcheck(t_win *win_in, char *buf, int bytes, int draw, int mode, t_win *win_out)
{
- int c;
- int ypos = 0, xpos = 0;
- int bytes = 0;
+ int n;
+ for (n=0;n<bytes;n++){
+ int width;
+ incharbuf[incharbuflen++] = buf[n];
+ if (completecharlen(incharbuf) > incharbuflen)continue;
+ if (eatchar && (incharbuf[0] == '\n')){
+ eatchar = 0;
+ incharbuflen = 0;
+ continue;
+ }
+ width = widthchar(incharbuf, incharbuflen, inbufwid);
+ eatchar = 0;
+ if (draw) {
+ if (win_in) waddnstr(win_in->ptr, incharbuf, incharbuflen);
+ else write(STDOUT_FILENO, incharbuf, incharbuflen);
+ }
+ if (incharbuf[0] == '\n')incharbuflen = 0;
+ else if (width + inbufwid <= COLS){
+ if (inbuflen + incharbuflen <= MAX_BUFLEN){
+ memcpy(&inbuf[inbuflen], incharbuf, incharbuflen);
+ inbuflen += incharbuflen;
+ }
+ incharbuflen = 0;
+ inbufwid += width;
+ if (inbufwid >= COLS)eatchar = 1;
+ continue;// Skip to next line when width goes over.
+ }
+ addscrollline(inbuf, inbuflen);
+ if (incharbuflen){
+ memcpy(&inbuf[0], incharbuf, incharbuflen);
+ inbuflen = incharbuflen;
+ incharbuflen = 0;
+ inbufwid = width;
+ }
+ else {
+ inbuflen = 0;
+ inbufwid = 0;
+ }
+ if (scrolledup && win_in && win_out){
+ scrolledup++; // scrolledup is relative to bottom line
+ scrolltext(win_in, 0, mode, win_out);
+ }
+ }
+ if (draw && win_in) wrefresh(win_in->ptr);
+
+}
- WINDOW *win = winopen(wintab, 3, COLS, 10, 0, TRUE);
- wmove(win, 1, 2);
- waddstr(win, text);
- wrefresh(win);
+void writeincom(int mode, int encoding, t_win * win_in, unsigned char buf[], int bytes, t_win *win_out)
+{
+ if (mode & RAWMODE) {
+ while (write(STDOUT_FILENO, buf, bytes) == -1) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ usleep(100000);
+ continue;
+ }
+ exit(1);
+ }
+ return;
+ } else if (encoding == UTF8ENCODING)
+ waddnstrcrcheck(win_in, (char *)buf, bytes,scrolledup == 0, mode, win_out);
+ else {
+ char *inbuf = (char *) buf, out[MAX_BUFLEN], *outbuf=out;
+ size_t insize = bytes, outsize = MAX_BUFLEN;
+ iconv(ibm850toutf8, &inbuf, &insize, &outbuf, &outsize);
+ waddnstrcrcheck(win_in, out, MAX_BUFLEN-outsize,scrolledup == 0, mode, win_out);
+ }
+ return;
+}
+static void writeincomstr(int mode, int encoding, t_win * win_in, char buf[], t_win *win_out)
+{
+ int len;
+ len = strlen(buf);
+ writeincom(mode, encoding, win_in, (unsigned char *)buf, len, win_out);
+}
- do {
- c = getch();
- if (c != ERR) {
- switch (c) {
- case KEY_BACKSPACE:
- case 127:
- {
- getyx(win, ypos, xpos);
- if (xpos > 0 && bytes > 0) {
- wmove(win, ypos, --xpos);
- waddch(win, ' ');
- wmove(win, ypos, xpos);
- bytes--;
- }
- }
- break;
- case (int) '\n':
- case (int) '\r':
- case KEY_ENTER:
- {
- waddch(win, '\n');
- buf[bytes++] = (char) '\n';
- wrefresh(win);
- buf[bytes] = 0;
- }
- break;
- default:
- {
- waddch(win, (char) c);
- buf[bytes++] = (char) c;
- }
- }
- wrefresh(win);
- }
- }
- while (c != '\n' && c != '\r' && c != KEY_ENTER);
- delwin(win);
- winclose(wintab);
- return 0;
+int outstring(char *buf, wchar_t *string, int bytes, int encoding)
+{
+ char *inbuf = (char *) string, *outbuf = buf;
+ size_t insize = bytes * sizeof(wchar_t), outsize = MAX_BUFLEN-1;
+ if (encoding == UTF8ENCODING){
+ iconv(wcharttoutf8, &inbuf, &insize, &outbuf, &outsize);
+ }
+ else {
+ iconv(wcharttoibm850, &inbuf, &insize, &outbuf, &outsize);
+
+ }
+ buf[(MAX_BUFLEN-1)-outsize] = '\0';
+ return (MAX_BUFLEN-1)-outsize;
+}
+
+int getstring(wint * wintab, char text[], char buf[])
+{
+ wchar_t c;
+ int ypos = 0, xpos = 0;
+ int bytes = 0;
+ wchar_t wbuf[MAX_BUFLEN];
+ WINDOW *win = winopen(wintab, 3, COLS, 10, 0, TRUE);
+ int done = 0;
+
+ wmove(win, 1, 2);
+ waddstr(win, text);
+ wrefresh(win);
+
+ do {
+ int r;
+ wint_t ci;
+ r = get_wch(&ci);
+ if (r != ERR) {
+ c = (wchar_t) ci;
+ if (((r == KEY_CODE_YES) && (c == KEY_BACKSPACE))||
+ ((r == OK) && ((c==127)|| (c==8)))){
+ getyx(win, ypos, xpos);
+ if (bytes > 0) {
+ int width, j;
+ width = wcwidthcontrol(wbuf[bytes-1]);
+ for (j=0;j<width;j++) mvwdelch(win, ypos, xpos-width);
+ xpos -= width;
+ wmove(win, ypos, xpos);
+ bytes--;
+ }
+ }
+ else if (( (r==KEY_CODE_YES) && (c == KEY_ENTER))||
+ ( (r == OK) && ((c=='\n') || (c=='\r')))){
+ wbuf[bytes++] = (wchar_t) '\n';
+ outstring(buf, wbuf, bytes, UTF8ENCODING);
+ done = 1;
+ }
+ else if (r == KEY_CODE_YES); // Put in code for other KEYCODES here
+ else if (bytes+2 < MAX_BUFLEN){
+ //int width;
+ //width = wins_nwchrmy(win, c);
+ //getyx(win, ypos, xpos);
+ //wmove(win, ypos, xpos+width);
+ wbuf[bytes++] = c;
+ drawinbuf(win, wbuf, bytes, bytes);
+ }
+ wrefresh(win);
+ }
+ }
+ while (!done);
+ delwin(win);
+ winclose(wintab);
+ return 0;
}
+
int readoutg(t_win * win_out, wint * wintab, menuitem * top, char buf[],
- int keyesc)
+ int keyesc, int mode, int encoding, t_win *win_in)
{
int out_cnt;
- int c;
+ int r;
+ wint_t ci;
+ wchar_t c;
int ypos = 0, xpos = 0;
int value;
- c = getch();
- if (c == ERR)
+ r = get_wch(&ci);
+ if (r == ERR)
return 0;
+ c = (wchar_t) ci;
if (c == keyesc) {
- if ((value = top_menu(wintab, top, 1)) == 0)
+ if ((value = top_menu(wintab, top, 1)) == 0) {
+ restorecursor(mode, win_out);
return 0;
+ }
+ restorecursor(mode, win_out);
buf[0] = '~';
switch (value) {
case 0x01:
@@ -1111,6 +1462,7 @@ int readoutg(t_win * win_out, wint * wintab, menuitem * top, char buf[],
getstring(wintab,
"Please enter filename: ",
&buf[2]);
+ restorecursor(mode, win_out);
return strlen(buf);
}
case 0x12:
@@ -1135,6 +1487,7 @@ int readoutg(t_win * win_out, wint * wintab, menuitem * top, char buf[],
getstring(wintab,
"Please enter filename: ",
buf + 2);
+ restorecursor(mode, win_out);
return strlen(buf);
}
case 0x21:
@@ -1158,97 +1511,164 @@ int readoutg(t_win * win_out, wint * wintab, menuitem * top, char buf[],
wrefresh(win_out->ptr);
return 2;
}
- switch (c) {
- case KEY_BACKSPACE:
- case 127:
- {
+ if (((r == KEY_CODE_YES) && (c == KEY_BACKSPACE))||
+ ((r == OK) && ((c==127)|| (c==8)))){
+ if ((mode == SLAVEMODE) && scrolledup) return 0;
+ while(win_out->curs_pos > 0){
+ int width;int j;
getyx(win_out->ptr, ypos, xpos);
- if (win_out->bytes > 0) {
- if (win_out->curs_pos < win_out->bytes) {
- mvwaddnstr(win_out->ptr, ypos,
- --xpos,
- &win_out->
- string[win_out->
- curs_pos],
- win_out->bytes -
- win_out->curs_pos);
- waddch(win_out->ptr, ' ');
- memmove(&win_out->
- string[win_out->curs_pos -
- 1],
- &win_out->string[win_out->
- curs_pos],
- win_out->bytes -
- win_out->curs_pos);
- } else
- mvwaddch(win_out->ptr, ypos,
- --xpos, ' ');
-
- wmove(win_out->ptr, ypos, xpos);
- win_out->bytes--;
- win_out->curs_pos--;
- }
- }
- break;
- case KEY_LEFT:
- if (win_out->curs_pos > 0) {
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos-1]);
+ for (j=0;j<width;j++) mvwdelch(win_out->ptr, ypos, xpos-width);
+ xpos -= width;
+ wmove(win_out->ptr, ypos, xpos);
+ if (win_out->curs_pos < win_out->bytes) {
+ memmove(&win_out->
+ string[win_out->curs_pos - 1],
+ &win_out->string[win_out-> curs_pos],
+ (win_out->bytes -
+ win_out->curs_pos) * sizeof(wchar_t));
+ }
+ win_out->bytes--;
win_out->curs_pos--;
- getyx(win_out->ptr, ypos, xpos);
- wmove(win_out->ptr, ypos, xpos - 1);
+ if (width)break;
}
- break;
- case KEY_RIGHT:
- if (win_out->curs_pos < win_out->bytes) {
+ }
+ else if (( (r==KEY_CODE_YES) && (c == KEY_ENTER))||
+ ( (r == OK) && ((c=='\n') || (c=='\r')))){
+ if ((mode == SLAVEMODE) && scrolledup) return 0;
+ while (win_out->curs_pos < win_out->bytes) { // Move to end of the line
+ int width;
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos]);
win_out->curs_pos++;
getyx(win_out->ptr, ypos, xpos);
- wmove(win_out->ptr, ypos, xpos + 1);
+ wmove(win_out->ptr, ypos, xpos + width);
+ }
+ waddch(win_out->ptr, '\n');
+ win_out->string[win_out->bytes++] = (wchar_t) '\n';
+ wrefresh(win_out->ptr);
+ out_cnt = outstring(buf, win_out->string, win_out->bytes, encoding);
+ if (mode == SLAVEMODE){
+ char obuf[MAX_BUFLEN];
+ char *inbuf = (char *)win_out->string, *outbuf = obuf;
+ size_t insize = win_out->bytes * sizeof(wchar_t), outsize = MAX_BUFLEN;
+ iconv(wcharttoutf8, &inbuf, &insize, &outbuf, &outsize);
+ waddnstrcrcheck(win_in, obuf, MAX_BUFLEN-outsize, 0, mode, win_out);
}
- break;
- case KEY_ENTER:
- case (int) '\n':
- case (int) '\r':
- {
- if (win_out->curs_pos < win_out->bytes) {
- getyx(win_out->ptr, ypos, xpos);
- wmove(win_out->ptr, ypos,
- xpos + win_out->bytes -
- win_out->curs_pos);
+ win_out->bytes = 0;
+ win_out->curs_pos = 0;
+ return out_cnt;
+ }
+ else if (r == KEY_CODE_YES){
+ switch(c){
+ case KEY_LEFT:// Character of 0 width
+ while (win_out->curs_pos > 0) {
+ int width;
+ win_out->curs_pos--;
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos]);
+ getyx(win_out->ptr, ypos, xpos);
+ wmove(win_out->ptr, ypos, xpos - width);
+ if (width)break; // Skip to non-width
+ }
+ break;
+ case KEY_RIGHT:
+ {
+ int skipped = 0;// Skip over 0 length characters
+ while (win_out->curs_pos < win_out->bytes) {
+ int width;
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos]);
+ if (width){
+ if (skipped)break;
+ skipped = 1;
+ }
+ win_out->curs_pos++;
+ getyx(win_out->ptr, ypos, xpos);
+ wmove(win_out->ptr, ypos, xpos + width);
+ }
+ break;
}
- waddch(win_out->ptr, '\n');
- win_out->string[win_out->bytes++] = (char) '\n';
- wrefresh(win_out->ptr);
- strncpy(buf, win_out->string, win_out->bytes);
- wrefresh(win_out->ptr);
- out_cnt = win_out->bytes;
- win_out->bytes = 0;
- win_out->curs_pos = 0;
- return out_cnt;
+ case KEY_UP:
+ scrolltext(win_in, 1, mode, win_out);
+ break;
+ case KEY_DOWN:
+ scrolltext(win_in, -1, mode, win_out);
+ break;
+ case KEY_NPAGE:
+ scrolltext(win_in, -win_in->max_y, mode, win_out);
+ break;
+ case KEY_PPAGE:
+ scrolltext(win_in, win_in->max_y, mode, win_out);
+ break;
+ case KEY_HOME:
+ while (win_out->curs_pos > 0) {
+ int width;
+ win_out->curs_pos--;
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos]);
+ getyx(win_out->ptr, ypos, xpos);
+ wmove(win_out->ptr, ypos, xpos - width);
+ }
+ break;
+ case KEY_END:
+ while (win_out->curs_pos < win_out->bytes) { // Move to end of the line
+ int width;
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos]);
+ win_out->curs_pos++;
+ getyx(win_out->ptr, ypos, xpos);
+ wmove(win_out->ptr, ypos, xpos + width);
+ }
+ break;
+ case KEY_DC:{
+ int skipped = 0;
+ if ((mode == SLAVEMODE) && scrolledup) return 0;
+ while (win_out->curs_pos < win_out->bytes){
+ int width;int j;
+ getyx(win_out->ptr, ypos, xpos);
+ width = wcwidthcontrol(win_out->string[win_out->curs_pos]);
+ if (width){
+ if (skipped)break;
+ skipped = 1;
+ }
+ for (j=0;j<width;j++) mvwdelch(win_out->ptr, ypos, xpos);
+ if (win_out->curs_pos + 1 < win_out->bytes) {
+ memmove(&win_out-> string[win_out->curs_pos],
+ &win_out->string[win_out-> curs_pos+1],
+ (win_out->bytes - (win_out->curs_pos+1)) * sizeof(wchar_t));
+ }
+ win_out->bytes--;
+ }
+ break;
+ }
+ case KEY_RESIZE:
+ break;
+ case KEY_BACKSPACE:
+ break;
+ case KEY_ENTER:
+ break;
+ default:
+ break;
}
+ }
+ else switch (c) {
+ case 8:
+ case 127:
+ case '\r':
+ case '\n':
break;
default:
- {
- waddch(win_out->ptr, (char) c);
+ if ((mode == SLAVEMODE) && scrolledup) return 0; // Don't try to edit while scrolled up in SLAVEmode.
+ // It's just not possible because the cursor is off screen
+ if (win_out->bytes < MAX_BUFLEN ) {
if (win_out->curs_pos < win_out->bytes) {
- getyx(win_out->ptr, ypos, xpos);
- waddnstr(win_out->ptr,
- &win_out->string[win_out->
- curs_pos],
- win_out->bytes -
- win_out->curs_pos);
memmove(&win_out->
string[win_out->curs_pos + 1],
- &win_out->string[win_out->
- curs_pos],
- win_out->bytes -
- win_out->curs_pos);
- win_out->string[win_out->curs_pos] =
- (char) c;
- wmove(win_out->ptr, ypos, xpos);
- } else
- win_out->string[win_out->bytes] = (char) c;
-
+ &win_out->string[win_out-> curs_pos],
+ (win_out->bytes -
+ win_out->curs_pos) * sizeof(wchar_t));
+ }
+ win_out->string[win_out->curs_pos] = c;
win_out->bytes++;
win_out->curs_pos++;
+ drawinbuf(win_out->ptr, win_out->string, win_out->bytes, win_out->curs_pos);
+ break;
}
}
wrefresh(win_out->ptr);
@@ -1521,8 +1941,8 @@ void statbits(int mode, char stat, int m)
refresh();
}
-
-int cmd_call(char *call[], int mode)
+
+int cmd_call(char *call[], int mode, int encoding)
{
menuitem con[] = {
{"~Reconnect", 'R', M_ITEM, (void *) 0x01},
@@ -1585,8 +2005,8 @@ int cmd_call(char *call[], int mode)
int upllen = 0;
char *c, *t;
t_gp gp;
- t_win win_in;
- t_win win_out;
+ t_win win_in = {0};
+ t_win win_out = {0};
WINDOW *swin = 0;
int cnt;
int crc = 0;
@@ -1607,9 +2027,11 @@ int cmd_call(char *call[], int mode)
return FALSE;
interrupted = FALSE;
+ sigwinchsignal = FALSE;
signal(SIGQUIT, cmd_intr);
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
+ signal(SIGWINCH, cmd_sigwinch);
sigemptyset(&oursigs);
sigaddset(&oursigs, SIGQUIT);
@@ -1668,6 +2090,12 @@ int cmd_call(char *call[], int mode)
usleep(100000);
continue;
}
+ if ((errno == EINTR) && sigwinchsignal) {
+ // Just process screen resize here.
+ reinit_mode(mode, &wintab, &win_in, &win_out, call);
+ sigwinchsignal = 0;
+ continue;
+ }
perror("select");
}
break;
@@ -1715,8 +2143,9 @@ int cmd_call(char *call[], int mode)
convert_cr_lf(buf, bytes);
if (!sevenplus) {
- writeincom(mode, &win_in,
- (unsigned char * ) buf, bytes);
+ writeincom(mode, encoding, &win_in,
+ (unsigned char * ) buf, bytes, &win_out);
+ restorecursor(mode, &win_out);
} else {
for (cnt = 0; cnt < bytes;
cnt++)
@@ -1843,7 +2272,7 @@ int cmd_call(char *call[], int mode)
} else {
bytes =
readoutg(&win_out, &wintab, top, buf,
- 0x1d);
+ 0x1d, mode, encoding, &win_in);
if (bytes == -1) {
wclear(win_in.ptr);
wrefresh(win_in.ptr);
@@ -1908,24 +2337,26 @@ int cmd_call(char *call[], int mode)
case '?':
case 'h':
case 'H':
- printf("\nTilde escapes:\n");
- printf(". close\n");
- printf("~ send ~\n");
- printf("r reconnect\n");
- printf("! shell\n");
- printf("Z suspend program. Resume with \"fg\"\n");
- printf("s Stop upload\n");
- printf("o Open log\n");
- printf("c Close log\n");
- printf("0 Switch GUI to \"RAW\" (line) mode - already here ;)\n");
- printf("1 Switch GUI to \"Slave\" mode\n");
- printf("2 Switch GUI to \"Talk\" (split) mode\n");
- printf("u Upload\n");
- printf("a Upload (autobin protocol)\n");
- printf("b Upload binary data (crlf conversion)\n");
- printf("yd YAPP Download\n");
- printf("yu YAPP Upload\n");
- fflush(stdout);
+ writeincomstr(mode, encoding, &win_in,"\nTilde escapes:\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,". close\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"~ send ~\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"r reconnect\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"! shell\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"Z suspend program. Resume with \"fg\"\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"s Stop upload\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"o Open log\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"c Close log\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"0 Switch GUI to \"RAW\" (line) mode - already here ;)\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"1 Switch GUI to \"Slave\" mode\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"2 Switch GUI to \"Talk\" (split) mode\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"u Upload\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"a Upload (autobin protocol)\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"b Upload binary data (crlf conversion)\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"yd YAPP Download\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"yu YAPP Upload\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"i IBM850 encoding\n", &win_out);
+ writeincomstr(mode, encoding, &win_in,"8 UTF-8 encoding\n", &win_out);
+ restorecursor(mode, &win_out);
continue;
case 'S':
case 's':
@@ -1938,6 +2369,7 @@ int cmd_call(char *call[], int mode)
statline(mode,
"No upload in progress");
}
+ restorecursor(mode, &win_out);
continue;
case 'A':
case 'a':
@@ -1948,6 +2380,7 @@ int cmd_call(char *call[], int mode)
if (uploadfile != -1) {
statline(mode,
"Already uploading");
+ restorecursor(mode, &win_out);
continue;
}
if ((t =
@@ -1959,12 +2392,14 @@ int cmd_call(char *call[], int mode)
if (*t == '\0') {
statline(mode,
"Upload requires a filename");
+ restorecursor(mode, &win_out);
continue;
}
uploadfile = open(t, O_RDONLY);
if (uploadfile == -1) {
statline(mode,
"Unable to open upload file");
+ restorecursor(mode, &win_out);
continue;
}
if (lseek(uploadfile, 0L, SEEK_END)
@@ -2063,8 +2498,9 @@ int cmd_call(char *call[], int mode)
uplpos = 0;
upldp = -1;
upllen = 0;
- }
- break;
+ }
+ restorecursor(mode, &win_out);
+ break;
case 'b':
case 'B':
binup = TRUE;
@@ -2102,6 +2538,7 @@ int cmd_call(char *call[], int mode)
statline(mode, s);
} else
statbits(mode, 'L', 1);
+ restorecursor(mode, &win_out);
continue;
case 'C':
case 'c':
@@ -2113,10 +2550,12 @@ int cmd_call(char *call[], int mode)
statline(mode,
"Log file not open");
}
+ restorecursor(mode, &win_out);
continue;
case 'Y':
case 'y':
cmd_yapp(buf + 2, bytes - 2);
+ restorecursor(mode, &win_out);
continue;
case '~':
bytes--;
@@ -2146,9 +2585,21 @@ int cmd_call(char *call[], int mode)
&wintab, &win_in,
&win_out, call);
continue;
+ case '8':
+ encoding = UTF8ENCODING;
+ statline(mode, "UTF-8 encoding");
+ restorecursor(mode, &win_out);
+ continue;
+ case 'i':
+ case 'I':
+ encoding = ORIGINALENCODING;
+ statline(mode, "IBM850 encoding");
+ restorecursor(mode, &win_out);
+ continue;
default:
statline(mode,
"Unknown '~' escape. Type ~h for a list");
+ restorecursor(mode, &win_out);
continue;
}
}
@@ -2164,8 +2615,10 @@ int cmd_call(char *call[], int mode)
if (uploadfile != -1) {
statline(mode,
"Ignored. Type ~s to stop upload");
+ restorecursor(mode, &win_out);
continue;
}
+
convert_lf_cr(buf, bytes);
while (offset != bytes) {
@@ -2199,6 +2652,7 @@ int cmd_call(char *call[], int mode)
winclose(&wintab);
statline(mode,
"Upload complete: 0 bytes");
+ restorecursor(mode, &win_out);
continue;
}
if (upldp == -1) {
@@ -2214,6 +2668,7 @@ int cmd_call(char *call[], int mode)
"Upload complete: %ld bytes",
uplpos);
statline(mode, s);
+ restorecursor(mode, &win_out);
continue;
}
if (upllen == -1) {
@@ -2225,6 +2680,7 @@ int cmd_call(char *call[], int mode)
"Error reading upload file: upload aborted at %ld bytes",
uplpos);
statline(mode, s);
+ restorecursor(mode, &win_out);
continue;
}
if (!binup)
@@ -2244,6 +2700,7 @@ int cmd_call(char *call[], int mode)
if (errno != EWOULDBLOCK && errno != EAGAIN) {
sprintf(s, "Write error during upload. Connection lost");
statline(mode, s);
+ restorecursor(mode, &win_out);
perror("write");
break;
}
@@ -2302,18 +2759,27 @@ int cmd_call(char *call[], int mode)
}
}
+void iconvclose(void)
+{
+ iconv_close(ibm850toutf8);
+ iconv_close(wcharttoibm850);
+ iconv_close(wcharttoutf8);
+ iconv_close(utf8towchart);
+}
int main(int argc, char **argv)
{
int p;
int mode = TALKMODE;
+ int encoding = UTF8ENCODING;// Maybe controversial?
+ setlocale(LC_ALL, "");
if (!isatty(STDIN_FILENO))
stdin_is_tty = 0;
setlinebuf(stdin);
- while ((p = getopt(argc, argv, "b:dhm:p:rs:RStT:vw:W")) != -1) {
+ while ((p = getopt(argc, argv, "b:dhm:p:rs:RStT:vw:Wi8")) != -1) {
switch (p) {
case 'b':
if (*optarg != 'e' && *optarg != 'l') {
@@ -2350,6 +2816,7 @@ int main(int argc, char **argv)
}
break;
case 'r':
+ COLS = 80; // This is used to format the scrollback buffer, which is stored in raw
mode = RAWMODE;
break;
case 's':
@@ -2402,6 +2869,12 @@ int main(int argc, char **argv)
case 'W':
wait_for_remote_disconnect = TRUE;
break;
+ case 'i':
+ encoding = ORIGINALENCODING;
+ break;
+ case '8':
+ encoding = UTF8ENCODING;
+ break;
case '?':
case ':':
usage();
@@ -2411,6 +2884,13 @@ int main(int argc, char **argv)
if (optind == argc || optind == argc - 1) {
usage();
}
+
+ ibm850toutf8 = iconv_open("UTF8", "IBM850");
+ wcharttoibm850 = iconv_open("IBM850", "WCHAR_T");
+ wcharttoutf8 = iconv_open("UTF8", "WCHAR_T");
+ utf8towchart = iconv_open("WCHAR_T", "UTF8");
+ atexit(iconvclose);
+
port = argv[optind];
if (ax25_config_load_ports() == 0) {
@@ -2459,7 +2939,7 @@ int main(int argc, char **argv)
printf("GW4PTS AX.25 Connect v1.11\n");
fflush(stdout);
}
- while (cmd_call(argv + optind + 1, mode)) {
+ while (cmd_call(argv + optind + 1, mode, encoding)) {
if (!be_silent) {
printf("Wait 60 sec before reconnect\n");
fflush(stdout);