static char rcsid[] = "@(#)$Id: terminal.c,v 1.51 2006/04/09 07:37:07 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.51 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "headers.h"
#include "s_me.h"
#include "cs_imp.h"
#include "cs_terminal.h"
DEBUG_VAR(Debug,__FILE__,"charset");
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
static char * sStr P_((unsigned char *p));
static char * sStr (p)
unsigned char *p;
{
return (char *)p;
}
int match_charset_name(cs1,cs2)
charset_t cs1;
charset_t cs2;
{
if (cs1 == cs2)
return 1;
if (!cs1 || !cs2)
return 0;
if (cs1->MIME_name && cs2->MIME_name &&
0 == istrcmp(cs1->MIME_name,cs2->MIME_name)) {
SIGDPRINT(Debug,9,(&Debug,
"** Matched charset by name %s (%p) == %s (%p)\n",
cs1->MIME_name,cs1,
cs2->MIME_name,cs2));
return 1;
}
return 0;
}
void debug_display_settings(p,sig,stream)
struct display_settings *p;
int sig;
int stream;
{
int i;
int corrupted = 0;
if (stream) {
SIGDPRINT(Debug,8,(&Debug,
"Stream sets: (%d sets)\n",
p->set_count));
} else {
SIGDPRINT(Debug,8,(&Debug,
"Terminal sets: (%d sets)\n",
p->set_count));
}
for (i = 0; i < p->set_count; i++) {
if (i >= sizeof (p->sets) /
sizeof (p->sets[0])) {
corrupted++;
break;
}
SIGDPRINT(Debug,8,(&Debug," set [%d]: bank=",i));
switch(p->sets[i].bank) {
case bank_unspecified: SIGDPRINT(Debug,8,(&Debug, "(none)")); break;
default: SIGDPRINT(Debug,8,(&Debug, "G%d ",
p->sets[i].bank)); break;
}
SIGDPRINT(Debug,8,(&Debug," type="));
switch(p->sets[i].type) {
case iso2022_other: SIGDPRINT(Debug,8,(&Debug,"other")); break;
case iso2022_94: SIGDPRINT(Debug,8,(&Debug,"94 ")); break;
case iso2022_96: SIGDPRINT(Debug,8,(&Debug,"96 ")); break;
case iso2022_94x94: SIGDPRINT(Debug,8,(&Debug,"94x94")); break;
case iso2022_96x96: SIGDPRINT(Debug,8,(&Debug,"96x96")); break;
default: SIGDPRINT(Debug,8,(&Debug,"?????"));
corrupted++; break;
}
{
int k;
SIGDPRINT(Debug,8,(&Debug," bytes="));
for (k = 0; k < sizeof p->sets[i].bytes && p->sets[i].bytes[k]; k++) {
int val = (unsigned char) p->sets[i].bytes[k];
if (k > 0) {
SIGDPRINT(Debug,8,(&Debug," "));
}
SIGDPRINT(Debug,8,(&Debug,"%d/%d",val/16,val%16));
}
}
SIGDPRINT(Debug,8,(&Debug," width=%d\n",p->width[i]));
}
for (i = 0; i < 4; i++) {
SIGDPRINT(Debug,8,(&Debug," bank G%d=",i));;
switch(p->bank[i]) {
case -1: SIGDPRINT(Debug,8,(&Debug,"(none)")); break;
default: SIGDPRINT(Debug,9,(&Debug,"set %d",p->bank[i]));
if (p->bank[i] < 0 || p->bank[i] >= p->set_count) {
corrupted++;
SIGDPRINT(Debug,8,(&Debug," ????"));
}
break;
}
SIGDPRINT(Debug,8,(&Debug,"\n"));
}
SIGDPRINT(Debug,8,(&Debug," left="));;
switch(p->current_L) {
case bank_unspecified: SIGDPRINT(Debug,8,(&Debug,"(none)")); break;
default: SIGDPRINT(Debug,8,(&Debug,"G%d ",
p->current_L)); break;
}
SIGDPRINT(Debug,8,(&Debug,"\n"));
SIGDPRINT(Debug,8,(&Debug," right="));;
switch(p->current_R) {
case bank_unspecified: SIGDPRINT(Debug,8,(&Debug,"(none)")); break;
default: SIGDPRINT(Debug,8,(&Debug,"G%d ",
p->current_R)); break;
}
SIGDPRINT(Debug,8,(&Debug,"\n"));
if (corrupted) {
if (stream)
panic("STRING PANIC",__FILE__,__LINE__,
"debug_display_settings",
#ifdef DEBUG
Debug.active >= 8 ?
"Corrupted stream sets information -- see debugfile" :
#endif
"Corrupted stream sets information",sig);
else
panic("STRING PANIC",__FILE__,__LINE__,
"debug_display_settings",
#ifdef DEBUG
Debug.active >= 8 ?
"Corrupted terminal sets information -- see debugfile" :
#endif
"Corrupted terminal sets information",sig);
}
}
static void debug_charset_sets P_((struct setlist *p));
static void debug_charset_sets(p)
struct setlist *p;
{
int i;
DPRINT(Debug,8,(&Debug,"(output) charset sets: \n"));
for (i = 0;
i < sizeof (p->sets) / sizeof (p->sets[0]) && p->sets[i];
i++) {
char *s;
DPRINT(Debug,8,(&Debug," set [%d]: bank=",i));
switch(p->sets[i]->bank) {
case bank_unspecified: DPRINT(Debug,8,(&Debug,"(none)")); break;
default: DPRINT(Debug,8,(&Debug,"G%d ",
p->sets[i]->bank)); break;
}
DPRINT(Debug,8,(&Debug," type="));
switch(p->sets[i]->type) {
case iso2022_other: DPRINT(Debug,8,(&Debug,"other")); break;
case iso2022_94: DPRINT(Debug,8,(&Debug,"94 ")); break;
case iso2022_96: DPRINT(Debug,8,(&Debug,"96 ")); break;
case iso2022_94x94: DPRINT(Debug,8,(&Debug,"94x94")); break;
case iso2022_96x96: DPRINT(Debug,8,(&Debug,"96x96")); break;
default: DPRINT(Debug,8,(&Debug,"?????")); break;
}
s = iso2022_codestr(p->sets[i]->bytes, sizeof p->sets[i]->bytes);
DPRINT(Debug,8,(&Debug," bytes=%s\n",s));
free(s);
}
DPRINT(Debug,8,(&Debug," left="));
switch(p->initial_L) {
case bank_unspecified: DPRINT(Debug,8,(&Debug,"(none)")); break;
default: DPRINT(Debug,8,(&Debug,"G%d ",
p->initial_L)); break;
}
DPRINT(Debug,8,(&Debug," rigth="));
switch(p->initial_R) {
case bank_unspecified: DPRINT(Debug,8,(&Debug,"(none)")); break;
default: DPRINT(Debug,8,(&Debug,"G%d ",
p->initial_R)); break;
}
DPRINT(Debug,8,(&Debug,"\n"));
for (i = 0;
i < sizeof (p->initial_bank) / sizeof (p->initial_bank[0]);
i++) {
DPRINT(Debug,8,(&Debug," initial bank G%d=",i));
if (-1 == p->initial_bank[i]) {
DPRINT(Debug,8,(&Debug,"(none)\n"));
} else {
DPRINT(Debug,8,(&Debug,"set %d",p->initial_bank[i]));
if (p->initial_bank[i] < 0 ||
p->initial_bank[i] >= sizeof (p->sets) / sizeof (p->sets[0]) ||
!p->sets[p->initial_bank[i]]) {
DPRINT(Debug,8,(&Debug," ?????"));
}
DPRINT(Debug,8,(&Debug,"\n"));
}
}
}
void reset_display_settings(p)
struct display_settings *p;
{
int i;
/* defined in hdrs/defs.h */
bzero((void *)p,sizeof (struct display_settings));
p->magic = DISPLAY_STATE_magic;
p->set_count = 0;
p->bank[0] = -1;
p->bank[1] = -1;
p->bank[2] = -1;
p->bank[3] = -1;
p->current_L = bank_unspecified;
p->current_R = bank_unspecified;
if (sizeof (p->width) / sizeof (p->width[0]) !=
sizeof (p->sets) / sizeof (p->sets[0]))
panic("STRING PANIC",__FILE__,__LINE__,
"reset_display_settings",
"width and sets array do not have save number of elemens",0);
for (i = 0; i < sizeof (p->width) / sizeof (p->width[0]); i++)
p->width[i] = -1;
#ifdef WCHAR
p->wcwidth = 0;
#endif
}
void free_terminal_info(p)
struct display_settings **p;
{
if (*p) {
if (DISPLAY_STATE_magic != (*p)->magic)
panic("STRING PANIC",__FILE__,__LINE__,
"free_terminal_info",
"Bad magic number",0);
(*p)->magic = 0; /* Not valid */
free(*p);
*p = NULL;
}
}
/* May be called from signal handler -- on that situation use
buffer specified as argument -- otherwise result is malloced
*/
char * iso2022_change_helper_1(terminal_info,ID,setnum,buffer,size)
screen_info_p terminal_info;
struct iso2022_setid ID;
int setnum;
char * buffer;
int size;
{
char * ret = NULL;
int maybe_signal = buffer != NULL;
if (maybe_signal) {
SIGDPRINT(Debug,9,(&Debug,
"iso2022_change_helper_1: buffer=%p size=%d\n",
buffer,size));
}
if (ID.bank != bank_unspecified) {
if (-1 == terminal_info->bank[ID.bank]) {
terminal_info->bank[ID.bank] = setnum;
if (maybe_signal) {
if (!ret)
ret = iso2022_setid_stream(ID,buffer,size);
else {
char buffer1[128];
char *c = iso2022_setid_stream(ID,buffer1,sizeof buffer1);
ret = strfcat(buffer,c,size);
}
} else {
char *c = iso2022_setid_stream(ID,NULL,0);
ret = strmcat(ret,c);
free(c);
}
} else if (terminal_info->bank[ID.bank] != setnum) {
SIGDPRINT(Debug,4,(&Debug,
"terminal_switch_to [iso2022_change_helper_1]: Several assignments for bank G%d\n",
ID.bank));
SIGDPRINT(Debug,8,(&Debug,
" Assigned to set %d -- another candinate set %d\n",
terminal_info->bank[ID.bank],setnum));
}
/* Initial bank settinsg do not set left and right so
set them here if them are not set ion iso2022_info */
if (terminal_info->bank[ID.bank] == setnum) {
if (terminal_info->current_L == bank_unspecified &&
ID.bank == bank_G0) {
terminal_info->current_L = bank_G0;
if (maybe_signal) {
if (!ret)
ret = lock_shift(0,terminal_info->current_L,buffer,
size);
else {
char buffer1[10];
char * c = lock_shift(0,terminal_info->current_L,
buffer1,sizeof buffer1);
ret = strfcat(buffer,c,size);
}
} else {
char *c = lock_shift(0,terminal_info->current_L,NULL,0);
ret = strmcat(ret,c);
free(c);
}
}
if (/* For ISO-8859-* charsets */
terminal_info->current_R == bank_unspecified &&
ID.type == iso2022_96 ||
/* For EUC-* charsets */
terminal_info->current_R == bank_unspecified &&
ID.type == iso2022_94x94 &&
ID.bank == bank_G1
) {
terminal_info->current_R = ID.bank;
if (maybe_signal) {
if (!ret)
ret = lock_shift(1,terminal_info->current_R,
buffer,size);
else {
char buffer1[10];
char *c = lock_shift(1,terminal_info->current_R,
buffer1,sizeof buffer1);
ret = strfcpy(buffer,c,size);
}
} else {
char *c = lock_shift(1,terminal_info->current_R,NULL,0);
ret = strmcat(ret,c);
free(c);
}
}
}
} else if (ID.type == iso2022_other) {
ret = iso2022_setid_stream(ID,buffer,size);
}
if (maybe_signal && ret && ret != buffer)
panic("STRING PANIC",__FILE__,__LINE__,
"iso2022_change_helper_1","buffer != ret when called from signal",1);
return ret;
}
/* Result is MALLOCed */
char * terminal_charset_post_init(terminal_info,iso2022_info)
screen_info_p terminal_info;
struct setlist * iso2022_info;
{
char * ret = NULL;
int max,k;
int i;
/* FIXME: Usage of this function on string.c unclear!!! */
static screen_info_p LAST_COMPLAIN = NULL;
static struct setlist * LAST_COMPLAIN_b = NULL;
if (DISPLAY_STATE_magic != terminal_info->magic)
panic("STRING PANIC",__FILE__,__LINE__,
"terminal_charset_post_init",
"Bad terminal_info (bad magic)",0);
/* Only check that terminal_info includes same sets
(on beginning of list) than iso2022_info */
for (max = 0; max < sizeof (iso2022_info->sets) /
sizeof (iso2022_info->sets[0]) &&
iso2022_info->sets[max];
max++) {
if (max >= terminal_info->set_count ||
terminal_info->sets[max].type != iso2022_info->sets[max]->type ||
0 != strncmp(sStr(terminal_info->sets[max].bytes),
sStr(iso2022_info->sets[max]->bytes),
sizeof (terminal_info->sets[max].bytes)) ||
(bank_unspecified != iso2022_info->sets[max]->bank &&
terminal_info->sets[max].bank != iso2022_info->sets[max]->bank)) {
if (LAST_COMPLAIN != terminal_info ||
LAST_COMPLAIN_b != iso2022_info) {
LAST_COMPLAIN = terminal_info;
LAST_COMPLAIN_b = iso2022_info;
DPRINT(Debug,8,(&Debug,
"terminal_charset_post_init: Output charset not current terminal charset\n"));
DPRINT(Debug,8,(&Debug,
" (perhaps subset) -- can't really post init terminal charset\n"));
if (max >= terminal_info->set_count) {
DPRINT(Debug,8,(&Debug,
" Only %d sets on terminal... \n",
terminal_info->set_count));
} else {
DPRINT(Debug,8,(&Debug,
" [%d] -- bank G%d on terminal set not match to output charset\n",
max, terminal_info->sets[max].bank));
}
debug_display_settings(terminal_info,0,0);
debug_charset_sets(iso2022_info);
}
return NULL;
}
}
LAST_COMPLAIN = NULL;
LAST_COMPLAIN_b = NULL;
if (terminal_info->set_count > 0 &&
terminal_info->sets[0].type == iso2022_other) {
if (same_setid(terminal_info->sets[0],
*(iso2022_info->sets[0]))) {
DPRINT(Debug,8,(&Debug,
"terminal_charset_post_init: Terminal was on no ISO2022 mode ... NO change\n"));
return NULL;
} else {
char *c;
DPRINT(Debug,8,(&Debug,
"terminal_charset_post_init: Terminal was on no ISO2022 mode ... returning to ISO2022\n"));
c = iso2022_setid_stream(return_to_iso2022,NULL,0);
ret = strmcat(ret,c);
free(c);
reset_display_settings(terminal_info);
}
}
/* Remove assignments which does not belong to iso2022_info */
for (k = 0; k < 4; k++) {
if (terminal_info->bank[k] >= max) {
if (k == terminal_info->current_L)
terminal_info->current_L = bank_unspecified;
if (k == terminal_info->current_R)
terminal_info->current_R = bank_unspecified;
terminal_info->bank[k] = -1;
}
}
if (bank_unspecified != iso2022_info->initial_L &&
terminal_info->current_L != iso2022_info->initial_L) {
char *c = lock_shift(0,terminal_info->current_L,NULL,0);
ret = strmcat(ret,c);
free(c);
}
if (bank_unspecified != iso2022_info->initial_R &&
terminal_info->current_R != iso2022_info->initial_R) {
char *c = lock_shift(1,terminal_info->current_R,NULL,0);
ret = strmcat(ret,c);
free(c);
}
for (i = 0;
i < sizeof (iso2022_info->initial_bank) /
sizeof (iso2022_info->initial_bank[0]);
i++) {
int x = iso2022_info->initial_bank[i];
if (-1 != x) {
struct iso2022_setid ID;
if (x < 0 ||
x >= sizeof (iso2022_info->sets) /
sizeof (iso2022_info->sets[0]) ||
! iso2022_info->sets[x])
panic("STRING PANIC",__FILE__,__LINE__,
"terminal_charset_post_init",
"Bad initial_bank (set)",
0);
ID = * (iso2022_info->sets[x]);
if (ID.bank != i)
panic("STRING PANIC",__FILE__,__LINE__,
"terminal_charset_post_init",
"Bad initial_bank (bank number)",
0);
set_initial_bank(&ret,ID,terminal_info,NULL,0,0);
}
}
for (k = 0; k < max; k++) {
char * c;
struct iso2022_setid ID = terminal_info->sets[k];
c=iso2022_change_helper_1(terminal_info,ID,k,NULL,0);
if (c) {
ret = strmcat(ret,c);
free(c);
}
}
if (ret)
debug_display_settings(terminal_info,0,0);
return ret;
}
screen_info_p create_terminal_info(void)
{
screen_info_p terminal_info;
terminal_info = safe_malloc(sizeof (struct display_settings));
reset_display_settings(terminal_info);
return terminal_info;
}
void iso2022_setid_select_bank (ID,terminal_info)
struct iso2022_setid *ID;
screen_info_p terminal_info;
{
if (ID->bank == bank_unspecified) {
switch(ID->type) {
case iso2022_94:
ID->bank = bank_G0;
break;
case iso2022_94x94:
ID->bank = bank_G1;
break;
/* We use bank G2 to compatible of VT3xx terminals */
case iso2022_96:
case iso2022_96x96: /* not perhaps exists */
if (-1 == terminal_info->bank[bank_G2])
ID->bank = bank_G2;
else
ID->bank = bank_G3;
}
}
}
int iso2022_give_setpos(ID,output_state)
struct iso2022_setid *ID;
screen_info_p output_state;
{
int setpos = -1;
int i;
iso2022_setid_select_bank (ID,output_state);
for (i = 0; i < output_state->set_count; i++) {
if (same_setid(output_state->sets[i],*ID))
setpos = i;
}
return setpos;
}
/* Return setnumber from terminal info */
int set_initial_bank(ret,ID,terminal_info,buffer,size,maybe_signal)
char **ret;
struct iso2022_setid ID;
screen_info_p terminal_info;
char * buffer;
int size;
int maybe_signal;
{
int setpos = -1;
if (ID.bank < 0 || ID.bank >= ISO2022_BANK_NUM)
panic("STRING PANIC",__FILE__,__LINE__,
"set_initial_bank",
"Bad bank",maybe_signal);
setpos = iso2022_give_setpos(&ID,terminal_info);
if (-1 == setpos) {
if (terminal_info->set_count <
sizeof (terminal_info->sets) /
sizeof (terminal_info->sets[0])) {
setpos = terminal_info->set_count++;
} else {
setpos = ID.bank;
DPRINT(Debug,7,(&Debug,
"set_initial_bank: Too many sets on output state, replacing set %d\n",
setpos));
}
terminal_info->sets[setpos] = ID;
terminal_info->width[setpos] = -1; /* Initially no width */
}
terminal_info->bank[ID.bank] = setpos;
if (maybe_signal) {
if (!*ret)
*ret = iso2022_setid_stream(ID,buffer,size);
else {
char buffer1[128];
char *c = iso2022_setid_stream(ID,buffer1,sizeof buffer1);
*ret = strfcat(buffer,c,size);
}
} else {
char *c = iso2022_setid_stream(ID,NULL,0);
*ret = strmcat(*ret,c);
free(c);
}
return setpos;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1