8000 minicom/src/minicom.c at master · TKHSTKY/minicom · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
1705 lines (1542 loc) · 45.2 KB

minicom.c

File metadata and controls

1705 lines (1542 loc) · 45.2 KB
/*
* minicom.c Main program. The main loop of the terminal emulator
* itself is in main.c. (Yeah yeah it's confusing).
*
* This file is part of the minicom communications package,
* Copyright 1991-1996 Miquel van Smoorenburg.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* fmg 1/11/94 colors
* jl 30.06.97 log it if you quit without reset while online
* fmg 8/20/97 History buffer searching added
* jseymour@jimsun.LinxNet.com (Jim Seymour) 03/26/98 - Added support for
* multiple tty devices via new "get_port()" function.
* kubota@debian.or.jp 07/98 - Added option -C to start capturing from the
* command line
* jl 09.07.98 added option -S to start a script at startup
* mark.einon@gmail.com 16/02/11 - Added option to timestamp terminal output
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <getopt.h>
#include <wchar.h>
#include <wctype.h>
#include <iconv.h>
#include <limits.h>
#define EXTERN
#include "port.h"
#include "minicom.h"
#include "intl.h"
static const char option_string[] =
#ifdef ENABLE_NLS
"I18n "
#endif
"";
#define RESET 1
#define NORESET 2
#ifdef DEBUG
/* Show signals when debug is on. */
static void signore(int sig)
{
if (stdwin)
werror(_("Got signal %d"), sig);
else
printf("%s\r\n", _("Got signal %d"), sig);
}
#endif /*DEBUG*/
static int line_timestamp;
/*
* Sub - menu's.
*/
static const char *c1[] = { N_(" Yes "), N_(" No "), NULL };
static const char *c2[] = { N_(" Close "), N_(" Pause "), N_(" Exit "), NULL };
static const char *c3[] = { N_(" Close "), N_(" Unpause"), N_(" Exit "), NULL };
static const char *c7[] = { N_(" Yes "), N_(" No "), NULL };
/* Initialize modem port. */
void port_init(void)
{
m_setparms(portfd, P_BAUDRATE, P_PARITY, P_BITS, P_STOPB,
P_HASRTS[0] == 'Y', P_HASXON[0] == 'Y');
}
static void do_hang(int askit)
{
int c = 0;
if (askit)
c = ask(_("Hang-up line?"), c7);
if (c == 0)
hangup();
}
/*
* We've got the hangup or term signal.
*/
static void hangsig(int sig)
{
if (stdwin)
werror(_("Killed by signal %d !\n"), sig);
if (capfp)
fclose(capfp);
keyboard(KUNINSTALL, 0);
hangup();
modemreset();
leave("\n");
}
/*
* Jump to a shell
*/
#ifdef SIGTSTP
static void shjump(int sig)
{
sigset_t ss, oldss;
(void)sig;
mc_wleave();
signal(SIGTSTP, SIG_DFL);
sigemptyset(&ss);
sigaddset(&ss, SIGTSTP);
sigprocmask(SIG_UNBLOCK, &ss, &oldss);
fputs(_("Suspended. Type \"fg\" to resume.\n"),stdout);
kill(getpid(), SIGTSTP);
sigprocmask(SIG_SETMASK, &oldss, NULL);
signal(SIGTSTP, shjump);
mc_wreturn();
if (use_status)
show_status();
}
#else
static void shjump(int sig)
{
char *sh;
int pid;
int status;
int f;
(void)sig;
sh = getenv("SHELL");
if (sh == NULL) {
werror(_("SHELL variable not set"));
return;
}
if ((pid = fork()) == -1) {
werror(_("Out of memory: could not fork()"));
return;
}
if (pid != 0)
mc_wleave();
if (pid == 0) {
for (f = 1; f < _NSIG; f++)
signal(f, SIG_DFL);
for (f = 3; f < 20; f++)
close(f);
fputs(_("Shelled out. Type \"exit\" to return.\n"), stdout);
execl(sh, sh, NULL);
exit(1);
}
m_wait(&status);
mc_wreturn();
if (use_status)
show_status();
}
#endif /*SIGTSTP*/
/* Get a line from either window or scroll back buffer. */
static ELM *mc_getline(WIN *w, int no)
{
int i;
static ELM outofrange[MAXCOLS] = {{0,0,0}};
if (no < us->histlines) {
/* Get a line from the history buffer. */
i = no + us->histline /*- 1*/;
if (i >= us->histlines)
i -= us->histlines;
if (i < 0)
i = us->histlines - 1;
return us->histbuf + (i * us->xs);
}
/* Get a line from the "us" window. */
no -= us->histlines;
if (no >= w->ys) {
if (outofrange[0].value == 0) {
for (i = 0; i < MAXCOLS; i++) {
outofrange[i].value = ' ';
outofrange[i].color = us->color;
outofrange[i].attr = us->attr;
}
outofrange[0].value = '~';
}
return outofrange;
}
return w->map + (no * us->xs);
}
/* Redraw the window. */
static void drawhist(WIN *w, int y, int r)
{
int f;
w->direct = 0;
for (f = 0; f < w->ys; f++)
mc_wdrawelm(w, f, mc_getline(w, y++));
if (r)
mc_wredraw(w, 1);
w->direct = 1;
}
/*
* fmg 8/20/97
* drawhist_look()
* Redraw the window, highlight line that was found to contain
* pattern 'look'
* Needed by re-draw screen function after EACH find_next()
*/
void drawhist_look(WIN *w, int y, int r, wchar_t *look, int case_matters)
{
int f;
ELM *tmp_e;
wchar_t tmp_line[MAXCOLS];
tmp_line[0]='\0';
w->direct = 0;
for (f = 0; f < w->ys; f++) {
tmp_e = mc_getline(w, y++);
/* First we "accumulate" the line into a variable */
mc_wdrawelm_var(w, tmp_e, tmp_line);
/* Does it have what we want? */
if (wcslen(look) > 1 && wcslen(tmp_line) > 1) {
if (StrStr(tmp_line,look, case_matters))
mc_wdrawelm_inverse(w, f, tmp_e); /* 'inverse' it */
else
mc_wdrawelm(w, f, tmp_e); /* 'normal' output */
}
}
if (r)
mc_wredraw(w, 1);
w->direct = 1;
}
/*
* fmg 8/20/97
* Search history - main function that started the C-code blasphemy :-)
* This function doesn't care about case/case-less status...
*/
void searchhist(WIN *w_hist, wchar_t *str)
{
int y;
WIN *w_new;
const char *hline;
size_t i;
/* Find out how big a window we must open. */
y = w_hist->y2;
if (st == (WIN *)0 || (st && tempst))
y--;
/* Open a Search line window. */
w_new = mc_wopen(0, y+1, w_hist->x2, y+1, 0, st_attr, sfcolor, sbcolor, 0, 0, 1);
w_new->doscroll = 0;
w_new->wrap = 0;
hline = _("SEARCH FOR (ESC=Exit)");
mc_wprintf(w_new, "%s(%d):",hline,MAX_SEARCH);
mc_wredraw(w_new, 1);
mc_wflush();
mc_wlocate(w_new, mbslen(hline)+6, 0);
for (i = 0; str[i] != 0; i++)
mc_wputc(w_new, str[i]);
mc_wlocate(w_new, mbslen(hline)+6, 0);
mc_wgetwcs(w_new, str, MAX_SEARCH, MAX_SEARCH);
#if 0
if (!str[0]) { /* then unchanged... must have pressed ESC... get out */
mc_wflush();
mc_wclose(w_new, 0);
return;
}
#endif
mc_wredraw(w_hist, 1);
mc_wclose(w_new, 1);
mc_wflush();
return;
}
/*
* fmg 8/20/97
* Move scope to next hit of pattern in the buffer.
* Returns line-number of next "hit_line" or -1 if none found
* (we beep elsewhere ;-)
*/
int find_next(WIN *w, WIN *w_hist,
int hit_line, /* 'current' Match line */
wchar_t *look, /* pattern */
int case_matters) /* guess... */
{
int next_line;
ELM *tmp_e;
wchar_t tmp_line[MAXCOLS];
int all_lines;
if (!look)
return(++hit_line); /* next line */
tmp_line[0] = '\0'; /* Personal phobia, I need to do this.. */
hit_line++; /* we NEED this so we don't search only same line! */
all_lines = w->histlines + w_hist->ys;
if (hit_line >= all_lines) { /* Make sure we've got a valid line! */
werror(_("Search Wrapping Around to Start!"));
hit_line = 0;
}
for (next_line = hit_line; next_line <= all_lines; next_line++) {
/* we do 'something' here... :-) */
tmp_e = mc_getline(w_hist, next_line);
/*
* First we "accumulate" the line into a variable.
* To see 'why', see what an 'ELM' structure looks like!
*/
mc_wdrawelm_var(w, tmp_e, tmp_line);
/* Does it have what we want? */
if (wcslen(tmp_line) > 1 && wcslen(look) > 1)
if (StrStr(tmp_line, look, case_matters))
return next_line;
}
if (hit_line >= all_lines) { /* Make sure we've got a valid line! */
werror(_("Search Wrapping Around to Start!"));
hit_line = 0;
}
return -1; /* nothing found! */
}
/*
* fmg 8/22/97
* Needed this for the case-less conparison... and Linux libc
* doesn't seem to have a strnstr function... so we fudge.. ;-)
*/
const wchar_t *upcase(wchar_t *dest, wchar_t *src)
{
wchar_t *d = dest;
while (*src)
*d++ = towupper(*src++);
*d = '\0';
return dest;
}
/*
* fmg 8/22/97
* Needed this for the case-less conparison... and Linux libc
* doesn't seem to have a strnstr function... so we fudge.. ;-)
*/
wchar_t *StrStr(wchar_t *str1, wchar_t *str2, int case_matters)
{
wchar_t tmpstr1[MAXCOLS], tmpstr2[MAXCOLS];
if (case_matters)
return wcsstr(str1, str2);
else
return wcsstr(upcase(tmpstr1, str1), upcase(tmpstr2, str2));
}
static void drawcite(WIN *w, int y, int citey, int start, int end)
{
if (y+citey >= start && y+citey <= end)
mc_wdrawelm_inverse(w, y, mc_getline(w, y+citey));
else
mc_wdrawelm(w, y, mc_getline(w, y+citey));
}
static void drawcite_whole(WIN *w, int y, int start, int end)
{
int sy;
for (sy = 0; sy < w->ys; sy++)
drawcite(w, sy, y, start, end);
}
static void do_cite(WIN *w, int start, int end)
{
wchar_t tmp_line[MAXCOLS];
ELM *tmp_e;
int x, y;
for (y=start; y<=end; y++) {
vt_send('>');
vt_send(' ');
tmp_e = mc_getline(w, y);
mc_wdrawelm_var(w, tmp_e, tmp_line);
tmp_line[w->xs] = 0;
for (x = w->xs-1; x >= 0; x--) {
if (tmp_line[x] <= ' ')
tmp_line[x]=0;
else
break;
}
for (x = 0; tmp_line[x]; x++) {
char buf[MB_LEN_MAX];
size_t i, len;
len = one_wctomb(buf, tmp_line[x]);
for (i = 0; i < len; i++)
vt_send(buf[i]);
}
vt_send(13);
}
}
/* Scroll back */
static void scrollback(void)
{
int y,c;
WIN *b_us, *b_st;
ELM *tmp_e;
int case_matters=0; /* fmg: case-importance, needed for 'N' */
static wchar_t look_for[MAX_SEARCH]; /* fmg: last used search pattern */
wchar_t tmp_line[MAXCOLS];
int citemode = 0;
int cite_ystart = 1000000,
cite_yend = -1,
cite_y = 0;
int inverse;
int loop = 1;
char hline0[128], hline1[128], *hline;
static int hit=0;
/* Find out how big a window we must open. */
y = us->y2;
if (st == (WIN *)0 || (st && tempst))
y--;
/* Open a window. */
b_us = mc_wopen(0, 0, us->x2, y, 0, us->attr, COLFG(us->color),
COLBG(us->color), 0, 0, 0);
mc_wcursor(b_us, CNONE);
/* Open a help line window. */
b_st = mc_wopen(0, y+1, us->x2, y+1, 0, st_attr, sfcolor, sbcolor, 0, 0, 1);
b_st->doscroll = 0;
b_st->wrap = 0;
/* Make sure help line is as wide as window. */
/*
* fmg 8/20/97
* added /=Srch, \=CaseLess, and N=Next and changed rest of line...
* Hope you like it :-)
*/
strcpy(hline0,
_("HISTORY: U=Up D=Down F=PgDn B=PgUp s=Srch S=CaseLess N=Next C=Cite ESC=Exit "));
if (b_st->xs < 127)
hline0[b_st->xs] = 0;
hline = hline0;
mc_wprintf(b_st, "%s", hline);
mc_wredraw(b_st, 1);
mc_wflush();
/* And do the job. */
y = us->histlines;
/* fmg 8/20/97
* Needed for N)extSearch, keeps track of line on which current "hit"
* is... we advance it to 'N'ext hit in find_next(). We start at "top"
* of history stack
*/
hit = 0;
drawhist(b_us, y, 0);
while (loop) {
c = wxgetch();
switch (c) {
/*
* fmg 8/22/97
* Take care of the search key: Caseless
*/
case '\\':
case 'S':
case_matters = 0; /* case-importance, ie. none :-) */
/*
* fmg 8/22/97
* Take care of the search key: Exact Match
*/
case '/':
case 's':
if (!us->histlines) {
mc_wbell();
werror(_("History buffer Disabled!"));
break;
}
if (!us->histline) {
mc_wbell();
werror(_("History buffer empty!"));
break;
}
if (citemode)
break;
/* we need this for the case-importance-toggle to work.. */
if (c == '/' || c == 's')
case_matters=1; /* case-importance, ie. DOES */
/* open up new search window... */
searchhist(b_us, look_for);
/* must redraw status line... */
mc_wlocate(b_st, 0, 0); /* move back to column 0! */
mc_wprintf(b_st, "%s", hline); /* and show the above-defined hline */
mc_wredraw(b_st, 1); /* again... */
/* highlight any matches */
if (wcslen(look_for) > 1) {
hit = find_next(us, b_us, y, look_for, case_matters);
if (hit == -1) {
mc_wbell();
mc_wflush();
hit = 0;
break;
}
drawhist_look(b_us, hit, 1, look_for, case_matters);
y = hit;
} else {
mc_wbell();
break;
}
mc_wflush();
break;
/*
* fmg 8/22/97
* Take care of the Next Hit key...
* Popup an error window if no previous... why not start a new
* search? How do we know which case-importance they wanted?
*/
case 'n':
case 'N':
/* highlight NEXT match */
if (citemode)
break;
if (wcslen(look_for) > 1) {
hit = find_next(us, b_us, y, look_for, case_matters);
if (hit == -1) {
mc_wbell();
mc_wflush();
hit = 0;
break;
}
drawhist_look(b_us, hit, 1, look_for, case_matters);
y = hit;
} else { /* no search pattern... */
mc_wbell();
werror(_("No previous search!\n Please 's' or 'S' first!"));
}
mc_wflush();
break;
case 'u':
case 'U':
case K_UP:
if (citemode && cite_y) {
cite_y--;
if (cite_ystart != 1000000) {
cite_yend = y + cite_y;
drawcite(b_us, cite_y+1, y, cite_ystart, cite_yend);
drawcite(b_us, cite_y, y, cite_ystart, cite_yend);
}
mc_wlocate(b_us, 0, cite_y);
break;
}
if (y <= 0)
break;
y--;
if (cite_ystart != 1000000)
cite_yend = y + cite_y;
mc_wscroll(b_us, S_DOWN);
/*
* fmg 8/20/97
* This is needed so that the movement in window will HIGHLIGHT
* the lines that have the pattern we wanted... it's just nice.
* This almost beggs for a function :-)
*/
if (citemode) {
inverse = (y+cite_y >= cite_ystart && y+cite_y <= cite_yend);
} else {
tmp_e = mc_getline(b_us, y);
if (wcslen(look_for) > 1) {
/* quick scan for pattern match */
mc_wdrawelm_var(b_us, tmp_e, tmp_line);
inverse = (wcslen(tmp_line)>1 &&
StrStr(tmp_line, look_for, case_matters));
} else
inverse = 0;
}
if (inverse)
mc_wdrawelm_inverse(b_us, 0, mc_getline(b_us, y));
else
mc_wdrawelm(b_us, 0, mc_getline(b_us, y));
if (citemode)
mc_wlocate(b_us, 0, cite_y);
mc_wflush();
break;
case 'd':
case 'D':
case K_DN:
if (citemode && cite_y < b_us->ys-1) {
cite_y++;
if (cite_ystart != 1000000) {
cite_yend = y + cite_y;
drawcite(b_us, cite_y-1, y, cite_ystart, cite_yend);
drawcite(b_us, cite_y, y, cite_ystart, cite_yend);
}
mc_wlocate(b_us, 0, cite_y);
break;
}
if (y >= us->histlines)
break;
y++;
if (cite_ystart != 1000000)
cite_yend = y + cite_y;
mc_wscroll(b_us, S_UP);
/*
* fmg 8/20/97
* This is needed so that the movement in window will HIGHLIGHT
* the lines that have the pattern we wanted... it's just nice.
* This almost beggs for a function :-)
*/
if (citemode) {
inverse = (y+cite_y >= cite_ystart && y+cite_y <= cite_yend);
} else {
tmp_e = mc_getline(b_us, y + b_us->ys - 1);
if (wcslen(look_for) > 1) {
/* quick scan for pattern match */
mc_wdrawelm_var(b_us, tmp_e, tmp_line);
inverse = (wcslen(tmp_line)>1 &&
StrStr(tmp_line, look_for, case_matters));
} else
inverse = 0;
}
if (inverse)
mc_wdrawelm_inverse(b_us, b_us->ys - 1,
mc_getline(b_us, y + b_us->ys - 1));
else
mc_wdrawelm(b_us, b_us->ys - 1,
mc_getline(b_us, y + b_us->ys - 1));
if (citemode)
mc_wlocate(b_us, 0, cite_y);
mc_wflush();
break;
case 'b':
case 'B':
case K_PGUP:
if (y <= 0)
break;
y -= b_us->ys;
if (y < 0)
y = 0;
if (cite_ystart != 1000000)
cite_yend = y + cite_y;
/*
* fmg 8/20/97
* This is needed so that the movement in window will HIGHLIGHT
* the lines that have the pattern we wanted... it's just nice.
* Highlight any matches
*/
if (wcslen(look_for) > 1 && us->histline)
drawhist_look(b_us, y, 1, look_for, case_matters);
else
drawhist(b_us, y, 1);
if (citemode)
mc_wlocate(b_us, 0, cite_y);
break;
case 'f':
case 'F':
case ' ': /* filipg: space bar will go page-down... pager-like */
case K_PGDN:
if (y >= us->histlines)
break;
y += b_us->ys;
if (y > us->histlines)
y=us->histlines;
if (cite_ystart != 1000000)
cite_yend = y + cite_y;
/*
* fmg 8/20/97
* This is needed so that the movement in window will HIGHLIGHT
* the lines that have the pattern we wanted... it's just nice.
* Highlight any matches
*/
if (wcslen(look_for) > 1 && us->histline)
drawhist_look(b_us, y, 1, look_for, case_matters);
else
drawhist(b_us, y, 1);
if (citemode)
mc_wlocate(b_us, 0, cite_y);
break;
case 'C': case 'c': /* start citation mode */
if (citemode ^= 1) {
cite_y = 0;
cite_ystart = 1000000;
cite_yend = -1;
strcpy(hline1, _(" CITATION: ENTER=select start line ESC=exit "));
if (b_st->xs < 127)
hline1[b_st->xs]=0;
hline = hline1;
} else {
hline = hline0;
}
mc_wlocate(b_st, 0, 0);
mc_wprintf(b_st, "%s", hline);
mc_wredraw(b_st, 1);
if (citemode)
mc_wlocate(b_us, 0, cite_y);
break;
case 10: case 13:
if (!citemode) break;
if (cite_ystart == 1000000) {
cite_yend = cite_ystart = y + cite_y;
strcpy(hline1, _(" CITATION: ENTER=select end line ESC=exit "));
if (b_st->xs < 127)
hline1[b_st->xs]=0;
} else {
if (cite_ystart > cite_yend)
break;
drawcite_whole(b_us, y, 1000000, -1);
loop = 0;
break;
}
mc_wlocate(b_st, 0, 0);
mc_wprintf(b_st, "%s", hline);
mc_wredraw(b_st, 1);
mc_wdrawelm_inverse(b_us, cite_y, mc_getline(b_us, cite_ystart));
mc_wlocate(b_us, 0, cite_y);
break;
case K_ESC:
if (!citemode) {
loop = 0;
break;
}
if (cite_ystart == 1000000) {
citemode = 0;
hline = hline0;
} else {
cite_ystart = 1000000;
strcpy(hline1, _(" CITATION: ENTER=select start line ESC=exit "));
}
drawcite_whole(b_us, y, cite_ystart, cite_yend);
mc_wlocate(b_st, 0, 0);
mc_wprintf(b_st, "%s", hline);
mc_wredraw(b_st, 1);
if (citemode)
mc_wlocate(b_us, 0, cite_y);
break;
}
}
/* Cleanup. */
if (citemode)
do_cite(b_us, cite_ystart, cite_yend);
mc_wclose(b_us, y == us->histlines ? 0 : 1);
mc_wclose(b_st, 1);
mc_wlocate(us, us->curx, us->cury);
mc_wflush();
mc_wredraw(us, 1);
}
#ifdef SIGWINCH
/* The window size has changed. Re-initialize. */
static void change_size(int sig)
{
(void)sig;
size_changed = 1;
signal(SIGWINCH, change_size);
}
#endif /*SIGWINCH*/
static void usage(int env_args, int optind, char *mc)
{
if (env_args >= optind && mc)
fprintf(stderr, _("Wrong option in environment MINICOM=\"%s\"\n"), mc);
fprintf(stderr, _("Type \"minicom %s\" for help.\n"), "--help");
exit(1);
}
/* Give some help information */
static void helpthem(void)
{
char *mc = getenv("MINICOM");
printf(_(
"Usage: %s [OPTION]... [configuration]\n"
"A terminal program for Linux and other unix-like systems.\n\n"
" -b, --baudrate : set baudrate (ignore the value from config)\n"
" -D, --device : set device name (ignore the value from config)\n"
" -s, --setup : enter setup mode\n"
" -o, --noinit : do not initialize modem & lockfiles at startup\n"
" -m, --metakey : use meta or alt key for commands\n"
" -M, --metakey8 : use 8bit meta key for commands\n"
" -l, --ansi : literal; assume screen uses non IBM-PC character set\n"
" -L, --iso : don't assume screen uses ISO8859\n"
" -w, --wrap : Linewrap on\n"
" -H, --displayhex : display output in hex\n"
" -z, --statline : try to use terminal's status line\n"
" -7, --7bit : force 7bit mode\n"
" -8, --8bit : force 8bit mode\n"
" -c, --color=on/off : ANSI style color usage on or off\n"
" -a, --attrib=on/off : use reverse or highlight attributes on or off\n"
" -t, --term=TERM : override TERM environment variable\n"
" -S, --script=SCRIPT : run SCRIPT at startup\n"
" -d, --dial=ENTRY : dial ENTRY from the dialing directory\n"
" -p, --ptty=TTYP : connect to pseudo terminal\n"
" -C, --capturefile=FILE : start capturing to FILE\n"
" -T, --disabletime : disable display of online time\n"
" -R, --remotecharset : character set of communication partner\n"
" -v, --version : output version information and exit\n"
" configuration : configuration file to use\n\n"
"These options can also be specified in the MINICOM environment variable.\n"),
PACKAGE);
if (mc) {
printf(_("This variable is currently set to \"%s\".\n"), mc);
} else {
printf(_("This variable is currently unset.\n"));
}
printf(_(
"The configuration directory for the access file and the configurations\n"
"is compiled to %s.\n\n"
"Report bugs to <minicom-devel@lists.alioth.debian.org>.\n"), CONFDIR);
}
static void set_addlf(int val)
{
vt_set(val, -1, -1, -1, -1, -1, -1, -1, -1);
}
/* Toggle linefeed addition. Can be called through the menu, or by a macro. */
void toggle_addlf(void)
{
addlf = !addlf;
set_addlf(addlf);
}
static void set_addcr(int val)
{
vt_set(-1, -1, -1, -1, -1, -1, -1, -1, val);
}
/* Toggle carriagereturn addition. Can be called through the menu, or by a macro. */
void toggle_addcr(void)
{
addcr = !addcr;
set_addcr(addcr);
}
static void set_local_echo(int val)
{
vt_set(-1, -1, -1, -1, val, -1 ,-1, -1, -1);
}
/* Toggle local echo. Can be called through the menu, or by a macro. */
void toggle_local_echo(void)
{
local_echo = !local_echo;
set_local_echo(local_echo);
}
static void set_line_timestamp(int val)
{
vt_set(-1, -1, -1, -1 ,-1, -1, -1, val, -1);
}
/* Toggle host timestamping on/off */
static void toggle_line_timestamp(void)
{
++line_timestamp;
line_timestamp %= TIMESTAMP_LINE_NR_OF_OPTIONS;
set_line_timestamp(line_timestamp);
}
/* -------------------------------------------- */
static void do_iconv_just_copy(char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*outbytesleft && *inbytesleft)
{
*(*outbuf) = *(*inbuf);
++(*outbuf);
++(*inbuf);
--(*outbytesleft);
--(*inbytesleft);
}
}
#ifdef HAVE_ICONV
static iconv_t iconv_rem2local;
static int iconv_enabled;
int using_iconv(void)
{
return iconv_enabled;
}
static void init_iconv(const char *remote_charset)
{
char local_charset[40];
char *tmp;
if (!remote_charset)
return;
// try to find some charset that minicom is using
tmp = getenv("LC_CTYPE");
if (!tmp)
tmp = getenv("LC_ALL");
if (!tmp)
tmp = getenv("LANG");
if (!tmp)
tmp = "ASCII";
// should be like 'en_US.UTF-8'
if (strchr(tmp, '.'))
tmp = strchr(tmp, '.') + 1;
snprintf(local_charset, sizeof(local_charset),
"%s//TRANSLIT", tmp);
local_charset[sizeof(local_charset) - 1] = 0;
if (0)
{
printf("Remote charset: %s\n", remote_charset);
printf("Local charset: %s\n", local_charset);
}
iconv_rem2local = iconv_open(local_charset, remote_charset);
if (iconv_rem2local != (iconv_t)-1)
iconv_enabled = 1;
else
printf("Activating iconv failed with: %s(%d)\n",
strerror(errno), errno);
}
void do_iconv(char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
if (!iconv_enabled
|| iconv(iconv_rem2local,
inbuf, inbytesleft,
outbuf, outbytesleft) == (size_t)-1)
{
do_iconv_just_copy(inbuf, inbytesleft, outbuf, outbytesleft);
// in case of error re-init conversion descriptor
// (will this work?)
if (iconv_enabled)
iconv(iconv_rem2local, NULL, NULL, NULL, NULL);
}
}
static void close_iconv(void)
{
if (iconv_enabled)
iconv_close(iconv_rem2local);
}
#else
int using_iconv(void)
{
return 0;
}
static void init_iconv(const char *remote_charset)
{
(void)remote_charset;
}
void do_iconv(char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
do_iconv_just_copy(inbuf, inbytesleft, outbuf, outbytesleft);
}
static void close_iconv(void)
0