194 lines
5.0 KiB
C
194 lines
5.0 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2009 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
#include "gtm_unistd.h"
|
|
|
|
#include <signal.h>
|
|
#include "gtm_string.h"
|
|
#include <errno.h>
|
|
#include <wctype.h>
|
|
#include <wchar.h>
|
|
|
|
#include "io.h"
|
|
#include "iottdef.h"
|
|
#include "gtmio.h"
|
|
#include "gt_timer.h"
|
|
#include "send_msg.h"
|
|
#include "error.h"
|
|
#include "dollarx.h"
|
|
#include "iott_flush_time.h"
|
|
#ifdef UNICODE_SUPPORTED
|
|
#include "gtm_icu_api.h"
|
|
#include "gtm_utf8.h"
|
|
#endif
|
|
|
|
GBLREF io_pair io_curr_device;
|
|
GBLREF io_pair io_std_device;
|
|
GBLREF bool prin_out_dev_failure;
|
|
GBLREF boolean_t gtm_utf8_mode;
|
|
|
|
void iott_write_buffered_text(io_desc *io_ptr, char *text, int textlen);
|
|
|
|
void iott_write_buffered_text(io_desc *io_ptr, char *text, int textlen)
|
|
{
|
|
d_tt_struct *tt_ptr;
|
|
int buff_left, status;
|
|
error_def(ERR_NOPRINCIO);
|
|
error_def(ERR_TERMWRITE);
|
|
|
|
tt_ptr = io_ptr->dev_sp;
|
|
assert(tt_ptr->write_active == FALSE);
|
|
tt_ptr->write_active = TRUE;
|
|
buff_left = IOTT_BUFF_LEN - (int)((tt_ptr->tbuffp - tt_ptr->ttybuff));
|
|
assert(buff_left > IOTT_BUFF_MIN || prin_out_dev_failure);
|
|
if (buff_left < textlen)
|
|
{
|
|
iott_flush_buffer(io_ptr, TRUE);
|
|
buff_left = IOTT_BUFF_LEN;
|
|
}
|
|
if (textlen <= buff_left)
|
|
{
|
|
memcpy((void *)tt_ptr->tbuffp, text, textlen);
|
|
tt_ptr->tbuffp += textlen;
|
|
buff_left -= textlen;
|
|
if (buff_left <= IOTT_BUFF_MIN)
|
|
iott_flush_buffer(io_ptr, FALSE); /* tt_ptr->write_active = FALSE */
|
|
else
|
|
tt_ptr->write_active = FALSE;
|
|
} else
|
|
{
|
|
DOWRITERC(tt_ptr->fildes, text, textlen, status);
|
|
tt_ptr->write_active = FALSE;
|
|
if (0 == status)
|
|
{
|
|
if (io_ptr == io_std_device.out)
|
|
{ /* ------------------------------------------------
|
|
* set prin_out_dev_failure to FALSE in case it
|
|
* had been set TRUE earlier and is now working.
|
|
* for eg. a write fails and the next write works.
|
|
* ------------------------------------------------
|
|
*/
|
|
prin_out_dev_failure = FALSE;
|
|
}
|
|
} else /* (0 != status) */
|
|
{
|
|
if (io_ptr == io_std_device.out)
|
|
{
|
|
if (!prin_out_dev_failure)
|
|
prin_out_dev_failure = TRUE;
|
|
else
|
|
{
|
|
send_msg(VARLSTCNT(1) ERR_NOPRINCIO);
|
|
/* rts_error(VARLSTCNT(1) ERR_NOPRINCIO); This causes a core dump */
|
|
stop_image_no_core();
|
|
}
|
|
}
|
|
rts_error(VARLSTCNT(3) ERR_TERMWRITE, 0, status);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void iott_write(mstr *v)
|
|
{
|
|
unsigned str_len;
|
|
unsigned len;
|
|
int status, this_width, char_width, avail_width;
|
|
char *str;
|
|
unsigned char *ptr, *ptrnext, *ptrtop;
|
|
io_desc *io_ptr, *flush_parm;
|
|
d_tt_struct *tt_ptr;
|
|
boolean_t utf8_active = FALSE;
|
|
wint_t codepoint;
|
|
error_def(ERR_TERMWRITE);
|
|
error_def(ERR_ZINTRECURSEIO);
|
|
|
|
str_len = v->len;
|
|
if (0 != str_len)
|
|
{
|
|
str = v->addr;
|
|
io_ptr = io_curr_device.out;
|
|
tt_ptr = (d_tt_struct *)io_ptr->dev_sp;
|
|
if (tt_ptr->mupintr)
|
|
rts_error(VARLSTCNT(1) ERR_ZINTRECURSEIO);
|
|
UNICODE_ONLY(utf8_active = gtm_utf8_mode ? (CHSET_M != io_ptr->ochset) : FALSE;)
|
|
for (; ;)
|
|
{
|
|
if (FALSE == io_ptr->wrap)
|
|
len = str_len;
|
|
else
|
|
{
|
|
if ((io_ptr->dollar.x >= io_ptr->width) && (START == io_ptr->esc_state))
|
|
{
|
|
iott_write_buffered_text(io_ptr, STR_AND_LEN(NATIVE_TTEOL));
|
|
io_ptr->dollar.y++;
|
|
io_ptr->dollar.x = 0;
|
|
}
|
|
if (START != io_ptr->esc_state)
|
|
len = str_len; /* write all if in escape sequence */
|
|
#ifdef UNICODE_SUPPORTED
|
|
else if (utf8_active)
|
|
{
|
|
ptrtop = (unsigned char *)str + str_len;
|
|
avail_width = io_ptr->width - io_ptr->dollar.x;
|
|
for (this_width = 0, ptr = (unsigned char *)str; ptr < ptrtop; ptr = ptrnext)
|
|
{
|
|
ptrnext = UTF8_MBTOWC(ptr, ptrtop, codepoint);
|
|
if (WEOF == codepoint)
|
|
UTF8_BADCHAR(0, ptr, ptrtop, 0, NULL);
|
|
GTM_IO_WCWIDTH(codepoint, char_width);
|
|
if ((this_width + char_width) > avail_width)
|
|
break;
|
|
this_width += char_width;
|
|
}
|
|
len = (int)(ptr - (unsigned char *)str);
|
|
if (0 == len)
|
|
{
|
|
if (char_width <= io_ptr->width)
|
|
{
|
|
io_ptr->dollar.x = io_ptr->width; /* force wrap */
|
|
continue;
|
|
} else
|
|
rts_error(VARLSTCNT(1) ERR_TERMWRITE);
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
if ((io_ptr->dollar.x + str_len) <= io_ptr->width)
|
|
len = str_len;
|
|
else
|
|
len = io_ptr->width - io_ptr->dollar.x;
|
|
}
|
|
assert(0 != len);
|
|
iott_write_buffered_text(io_ptr, str, len);
|
|
|
|
dollarx(io_ptr, (uchar_ptr_t)str, (uchar_ptr_t)str + len);
|
|
str_len -= len;
|
|
if (0 >= (signed)str_len)
|
|
break;
|
|
str += len;
|
|
}
|
|
|
|
if (FALSE == tt_ptr->timer_set)
|
|
{
|
|
flush_parm = io_ptr;
|
|
tt_ptr->timer_set = TRUE;
|
|
start_timer((TID)io_ptr,
|
|
IOTT_FLUSH_WAIT,
|
|
&iott_flush_time,
|
|
SIZEOF(flush_parm),
|
|
(char *)&flush_parm);
|
|
}
|
|
|
|
}
|
|
}
|