Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1367 lines
30 KiB

/* File: D:\WACKER\emu\minitelf.c (Created: 12-Apr-1994)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 1 $
* $Date: 10/05/98 12:28p $
*/
#include <windows.h>
#pragma hdrstop
#include <tdll\stdtyp.h>
#include <tdll\tdll.h>
#include <tdll\session.h>
#include <tdll\print.h>
#include <tdll\capture.h>
#include <tdll\assert.h>
#include <tdll\mc.h>
#include <tdll\update.h>
#include "emu.h"
#include "emu.hh"
#include "emuid.h"
#include "minitel.hh"
static void minitel_clear_imgrow(const HHEMU hhEmu, const int row);
#if defined(INCL_MINITEL)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelLinefeed
*
* DESCRIPTION:
* Linefeeds work differently in minitel. In page mode we wrap to line
* one (not zero) when at the bottom.
*
* ARGUMENTS:
* hhEmu - private emulator handle.
*
* RETURNS:
* void
*
*/
void minitelLinefeed(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = hhEmu->pvPrivate;
const ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow];
const PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
printEchoString(hhEmu->hPrintEcho, (ECHAR *)tp,
emuRowLen(hhEmu, hhEmu->emu_currow)); // mrw,3/1/95
// see page 97, bottom of page
//
if (hhEmu->emu_currow == 0)
{
hhEmu->emu_charattr = pstPRI->minitel_saved_attr;
(*hhEmu->emu_setcurpos)(hhEmu, pstPRI->minitel_saved_row,
pstPRI->minitel_saved_col);
pstPRI->minitelG1Active = pstPRI->minitel_saved_minitelG1Active;
pstPRI->stLatentAttr = pstPRI->saved_stLatentAttr;
pstPRI->minitelUseSeparatedMosaics =
pstPRI->saved_minitelUseSeparatedMosaics;
}
else if (hhEmu->emu_currow == hhEmu->bottom_margin)
{
if (pstPRI->fScrollMode)
minitel_scrollup(hhEmu, 1);
else
(*hhEmu->emu_setcurpos)(hhEmu, 1, hhEmu->emu_curcol);
}
else
{
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow + 1,
hhEmu->emu_curcol);
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelBackspace
*
* DESCRIPTION:
* Backspaces are goofy. They wrap to the previous line. In scroll mode
* they cause scrolling if in line 1
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelBackspace(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = hhEmu->pvPrivate;
if (hhEmu->emu_curcol > 0)
{
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow,
hhEmu->emu_curcol-1);
}
else if (hhEmu->emu_currow == 1)
{
if (pstPRI->fScrollMode)
{
minitel_scrolldown(hhEmu, (hhEmu->emu_charattr.dblhilo) ? 2 : 1);
}
else
{
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_maxrow,
hhEmu->emu_maxcol);
}
}
else
{
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow-1,
hhEmu->emu_maxcol);
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelVerticalTab
*
* DESCRIPTION:
* Vertical tabs work differently. They move the cursor up and wrap or
* scroll depending on the mode.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelVerticalTab(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = hhEmu->pvPrivate;
// VT sequence not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
if (hhEmu->emu_currow == 1)
{
if (pstPRI->fScrollMode)
{
minitel_scrolldown(hhEmu, (hhEmu->emu_charattr.dblhilo) ? 2 : 1);
}
else
{
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_maxrow,
hhEmu->emu_curcol);
}
}
else
{
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow-1,
hhEmu->emu_curcol);
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelCursorUp
*
* DESCRIPTION:
* Moves cursor up n rows but not into row 00
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelCursorUp(const HHEMU hhEmu)
{
int nlines, row;
// CSI sequences not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
nlines = hhEmu->num_param[hhEmu->num_param_cnt];
if (nlines < 1)
nlines = 1;
row = hhEmu->emu_currow;
row -= nlines;
if (row < 1)
row = 1;
(*hhEmu->emu_setcurpos)(hhEmu, row, hhEmu->emu_curcol);
ANSI_Pn_Clr(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelCursorDirect
*
* DESCRIPTION:
* Moves cursor to specified coordinates but not row 00
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelCursorDirect(const HHEMU hhEmu)
{
int row, col;
// CSI functions not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
row = hhEmu->num_param[0];
col = hhEmu->num_param_cnt > 0 ? hhEmu->num_param[1] : 0;
if (row < 1)
row = 1;
if (col < 1)
col = 1;
if (row > hhEmu->emu_maxrow + 1)
row = hhEmu->emu_maxrow + 1;
if (col > hhEmu->emu_maxcol + 1)
col = hhEmu->emu_maxcol + 1;
// Again, can't go to row 00 with this call.
(*hhEmu->emu_setcurpos)(hhEmu, row, col - 1);
ANSI_Pn_Clr(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelFormFeed
*
* DESCRIPTION:
* Clears rows 1 thru 24 leaving row 00 alone.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelFormFeed(const HHEMU hhEmu)
{
(*hhEmu->emu_setcurpos)(hhEmu, 1, 0);
minitelClearScreen(hhEmu, 0);
minitelReset(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelClearScreen
*
* DESCRIPTION:
* Works similar to the standard function but also has to clear the
* latent attribute and all serial attributes.
*
* ARGUMENTS:
* int iHow - dirction to clear screen.
*
* RETURNS:
* void
*
*/
void minitelClearScreen(const HHEMU hhEmu, const int iHow)
{
#define BLACK_MOSAIC ETEXT('\xff')
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
int i;
int r;
PSTMINITEL pstMT;
STMINITEL stMT;
ECHAR *pText;
PSTATTR pstAttr;
STATTR stAttr;
// CSI sequences not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
memset(&stMT, 0, sizeof(stMT));
stMT.ismosaic = 1;
memset(&stAttr, 0, sizeof(stAttr));
stAttr.txtclr = VC_BRT_WHITE;
stAttr.bkclr = VC_BLACK;
switch (iHow)
{
case 0: // cursor to end of screen inclusive
default:
pstMT = pstPRI->apstMT[hhEmu->emu_imgrow];
pText = hhEmu->emu_apText[hhEmu->emu_imgrow];
pstAttr = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
for (i = hhEmu->emu_curcol ; i < MAX_EMUCOLS ; ++i)
{
*pstMT++ = stMT;
*pText++ = BLACK_MOSAIC;
*pstAttr++ = stAttr;
}
for (r = hhEmu->emu_currow+1 ; r < MAX_EMUROWS ; ++r)
{
i = row_index(hhEmu, r);
pstMT = pstPRI->apstMT[i];
pText = hhEmu->emu_apText[i];
pstAttr = hhEmu->emu_apAttr[i];
for (i = 0 ; i < MAX_EMUCOLS ; ++i)
{
*pstMT++ = stMT;
*pText++ = BLACK_MOSAIC;
*pstAttr++ = stAttr;
}
}
updateLine(sessQueryUpdateHdl(hhEmu->hSession), hhEmu->emu_currow,
hhEmu->emu_maxrow);
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol;
break;
case 1: // beginning of screen to cursor inclusive
for (r = 1 ; r < hhEmu->emu_currow ; ++r)
{
i = row_index(hhEmu, r);
pstMT = pstPRI->apstMT[i];
pText = hhEmu->emu_apText[i];
pstAttr = hhEmu->emu_apAttr[i];
for (i = 0 ; i < MAX_EMUCOLS ; ++i)
{
*pstMT++ = stMT;
*pText++ = BLACK_MOSAIC;
*pstAttr++ = stAttr;
}
}
pstMT = pstPRI->apstMT[hhEmu->emu_imgrow];
pText = hhEmu->emu_apText[hhEmu->emu_imgrow];
pstAttr = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
for (i = 0 ; i <= hhEmu->emu_curcol ; ++i)
{
*pstMT++ = stMT;
*pText++ = BLACK_MOSAIC;
*pstAttr++ = stAttr;
}
updateLine(sessQueryUpdateHdl(hhEmu->hSession),
0, hhEmu->emu_currow);
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol + 1;
break;
case 2: // entire screen (cursor position not changed)
for (r = 1 ; r < MAX_EMUROWS ; ++r)
{
i = row_index(hhEmu, r);
pstMT = pstPRI->apstMT[i];
pText = hhEmu->emu_apText[i];
pstAttr = hhEmu->emu_apAttr[i];
hhEmu->emu_aiEnd[r] = EMU_BLANK_LINE;
for (i = 0 ; i < MAX_EMUCOLS ; ++i)
{
*pstMT++ = stMT;
*pText++ = BLACK_MOSAIC;
*pstAttr++ = stAttr;
}
}
updateLine(sessQueryUpdateHdl(hhEmu->hSession),
0, hhEmu->emu_maxrow);
break;
}
minitelRecordSeparator(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelClrScrn
*
* DESCRIPTION:
* Front end for minitelClearScreen() that reads the PSN argument,
* converts it, and passes it to minitelClearScreen. Called from
* the state tables.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelClrScrn(const HHEMU hhEmu)
{
minitelClearScreen(hhEmu, hhEmu->selector[0]);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelRecordSepartor
*
* DESCRIPTION:
* Record Separtor has special duties in Minitel. In general it homes
* the cursor and returns the emulator to what's called an SI condition.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelRecordSeparator(const HHEMU hhEmu)
{
(*hhEmu->emu_setcurpos)(hhEmu, 1, 0);
minitelReset(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelClearLine
*
* DESCRIPTION:
* Handles the various clear line functions like cursor to end, beg to
* cursor, etc.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelClearLine(const HHEMU hhEmu, const int iHow)
{
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
int i;
ECHAR *pText = hhEmu->emu_apText[hhEmu->emu_imgrow];
PSTMINITEL pstMT = pstPRI->apstMT[hhEmu->emu_imgrow];
PSTATTR pstAttr = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
const HUPDATE hUpdate= sessQueryUpdateHdl(hhEmu->hSession);
STMINITEL stMT;
STATTR stAttr;
// CSI sequences not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
memset(&stMT, 0, sizeof(stMT));
stMT.ismosaic = 1;
memset(&stAttr, 0, sizeof(stAttr));
stAttr.txtclr = VC_BRT_WHITE;
stAttr.bkclr = VC_BLACK;
switch (iHow)
{
case 0: // cursor to end of line inclusive
default:
for (i = hhEmu->emu_curcol ; i < MAX_EMUCOLS ; ++i)
{
*pText++ = BLACK_MOSAIC;
*pstMT++ = stMT;
*pstAttr++ = stAttr;
}
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol - 1;
updateChar(hUpdate, hhEmu->emu_currow,
hhEmu->emu_curcol, MAX_EMUCOLS);
break;
case 1: // beginning of line to cursor inclusive
for (i = 0 ; i <= hhEmu->emu_curcol ; ++i)
{
*pText++ = BLACK_MOSAIC;
*pstMT++ = stMT;
*pstAttr++ = stAttr;
}
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol + 1;
updateChar(hUpdate, hhEmu->emu_currow, 0, hhEmu->emu_curcol);
break;
case 2: // entire line
for (i = 0 ; i < MAX_EMUCOLS ; ++i)
{
*pText++ = BLACK_MOSAIC;
*pstMT++ = stMT;
*pstAttr++ = stAttr;
}
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = EMU_BLANK_LINE;
updateLine(hUpdate, hhEmu->emu_currow, hhEmu->emu_currow);
break;
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelClrLn
*
* DESCRIPTION:
* Driver for minitelClearLine().
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelClrLn(const HHEMU hhEmu)
{
minitelClearLine(hhEmu, hhEmu->selector[0]);
return;
}
#if 0
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelDel
*
* DESCRIPTION:
* code 0x7F (Del) deletes the cursor location and moves the cursor
* one position right.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelDel(const HHEMU hhEmu)
{
hhEmu->emu_apText[hhEmu->emu_imgrow][hhEmu->emu_curcol] = ETEXT('\x5F');
hhEmu->emu_ap
if (hhEmu->emu_aiEnd[hhEmu->emu_imgrow] == hhEmu->emu_curcol)
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol - 1;
minitelHorzTab(hhEmu);
return;
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelHorzTab
*
* DESCRIPTION:
* minitel cursor has some special characteristics. Minitel is always
* in wrap mode, so we wrap to begining of next row when beyond the
* last column. Also, when at bottom, wrap to line 1. Also, if in
* row 0, column 40, ignore.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelHorzTab(const HHEMU hhEmu)
{
int row = hhEmu->emu_currow;
int col = hhEmu->emu_curcol;
if (col >= hhEmu->emu_maxcol)
{
if (hhEmu->emu_currow == 0)
return;
if (hhEmu->emu_currow >= hhEmu->emu_maxrow)
row = 1;
else
row += 1;
col = 0;
}
else
{
col += 1;
}
(*hhEmu->emu_setcurpos)(hhEmu, row, col);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelRepeat
*
* DESCRIPTION:
* Repeat code displays the last displayed character x number of
* times where x is the current emu_code coming in.
* I don't think wrapping is effective here.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelRepeat(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
int x;
// Already did range checking in state table to get here.
// Repeat number is only the first six significant bits.
x = max(0, hhEmu->emu_code-0x40);
hhEmu->emu_code = pstPRI->minitel_last_char;
while (x-- > 0)
minitelGraphic(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelCancel
*
* DESCRIPTION:
* Fills current row from cursor position to end of row with spaces
* in the current character set current attributes. Cursor doesn't move.
* Doco says this is not a delimiter.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelCancel(const HHEMU hhEmu)
{
int i;
int iMax;
int fModified;
const int row = hhEmu->emu_currow;
const int col = hhEmu->emu_curcol;
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
hhEmu->emu_code = ETEXT('\x20');
// Ah, the life of the undocumented. The documentation says
// that this guys does not validate, colors, act as a delimiter
// and fills with spaces. Wrong. It does validate the color.
// As such its a delimiter. If the the current active char
// set is G1, then it fills with mosaics, not spaces.
//
fModified = pstPRI->stLatentAttr.fModified;
iMax = hhEmu->emu_maxcol;
// minitelGraphic checks the InCancel flag and if TRUE suppresses
// linewrap. mrw:5/3/95
//
pstPRI->fInCancel = TRUE;
for (i = hhEmu->emu_curcol ; i <= iMax ; ++i)
{
minitelGraphic(hhEmu);
}
pstPRI->fInCancel = FALSE;
// Ok, even though we validated the background color, we haven't
// changed the state of the latent attribute (also undocumented).
// So set it back to whatever is was before we entered this lovely
// mess of a function - mrw
//
pstPRI->stLatentAttr.fModified = fModified;
(*hhEmu->emu_setcurpos)(hhEmu, row, col);
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_maxcol;
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelUSRow
*
* DESCRIPTION:
* Intermediate function that collects the row number
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelUSRow(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
pstPRI->us_row_code = hhEmu->emu_code;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelUSCol
*
* DESCRIPTION:
* Interestingly, columns are numbered from 1 to 40. Unit seperators
* are ugly little beasts. They indicate a row, col combo, but only
* if in a certain range. Also, an obsolite sequence US,3/X,3/Y where
* 0 < X < 3, 0 < Y < 9 and XY < 24 is not suppose to be used but
* often is.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelUSCol(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
int us_col_code = hhEmu->emu_code;
int us_col = us_col_code - 0x41;
int us_row = pstPRI->us_row_code - 0x40;
if (us_row >= 0 && us_row <= hhEmu->emu_maxrow &&
us_col >= 0 && us_col <= hhEmu->emu_maxcol)
{
if (us_row == 0)
{
// p.97, bottom of page
//
if (hhEmu->emu_currow != 0)
{
pstPRI->minitel_saved_attr = hhEmu->emu_charattr;
pstPRI->minitel_saved_row = hhEmu->emu_currow;
pstPRI->minitel_saved_col = hhEmu->emu_curcol;
pstPRI->saved_stLatentAttr = pstPRI->stLatentAttr;
pstPRI->minitel_saved_minitelG1Active =
pstPRI->minitelG1Active;
pstPRI->saved_minitelUseSeparatedMosaics =
pstPRI->minitelUseSeparatedMosaics;
}
}
(*hhEmu->emu_setcurpos)(hhEmu, us_row, us_col);
minitelReset(hhEmu);
}
else if (pstPRI->us_row_code >= 0x30 &&
pstPRI->us_row_code < 0x33 &&
us_col_code >= 0x30 &&
us_col_code <= 0x39)
{
us_row = ((pstPRI->us_row_code - 0x30) * 10) + (us_col_code - 0x30);
if (us_row > 24)
return;
if (us_row == 0)
{
if (hhEmu->emu_currow != 0)
{
pstPRI->minitel_saved_attr = hhEmu->emu_charattr;
pstPRI->minitel_saved_row = hhEmu->emu_currow;
pstPRI->minitel_saved_col = hhEmu->emu_curcol;
pstPRI->saved_stLatentAttr = pstPRI->stLatentAttr;
pstPRI->minitel_saved_minitelG1Active =
pstPRI->minitelG1Active;
pstPRI->saved_minitelUseSeparatedMosaics =
pstPRI->minitelUseSeparatedMosaics;
}
}
(*hhEmu->emu_setcurpos)(hhEmu, us_row, 0);
minitelReset(hhEmu);
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelDelChars
*
* DESCRIPTION:
* Deletes n characters from cursor position inclusive.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelDelChars(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
int i, n;
ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow]+hhEmu->emu_curcol;
STATTR stAttr;
PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow]+hhEmu->emu_curcol;
STMINITEL stMT;
PSTMINITEL pstMT = pstPRI->apstMT[hhEmu->emu_imgrow];
// CSI sequences not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
n = min(hhEmu->emu_maxcol, hhEmu->num_param[0]);
i = max(0, hhEmu->emu_maxcol - hhEmu->emu_curcol - n);
/* --- Move characters down --- */
memmove(tp, tp+n, (unsigned)i * sizeof(ECHAR));
memmove(ap, ap+n, (unsigned)i * sizeof(STATTR));
memmove(pstMT, pstMT+n, (unsigned)i * sizeof(STMINITEL));
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] =
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - i;
/* --- Fill remainder of line --- */
tp += i;
ap += i;
memset(&stAttr, 0, sizeof(stAttr));
stAttr.txtclr = VC_BRT_WHITE;
stAttr.bkclr = VC_BLACK;
memset(&stMT, 0, sizeof(stMT));
stMT.ismosaic = (unsigned)pstPRI->minitelG1Active;
for (n = max(0, hhEmu->emu_maxcol - i) ; n > 0 ; --n)
{
*tp++ = EMU_BLANK_CHAR;
*ap++ = stAttr;
*pstMT++ = stMT;
}
updateChar(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_currow,
hhEmu->emu_curcol,
hhEmu->emu_maxcol);
ANSI_Pn_Clr(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelInsChars
*
* DESCRIPTION:
* Inserts n characters from cursor position inclusive
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelInsChars(const HHEMU hhEmu)
{
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
int i, n;
ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow]+hhEmu->emu_curcol;
STATTR stAttr;
PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow]+hhEmu->emu_curcol;
STMINITEL stMT;
PSTMINITEL pstMT = pstPRI->apstMT[hhEmu->emu_imgrow];
// CSI sequences not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
n = min(hhEmu->emu_maxcol, hhEmu->num_param[0]);
i = max(0, hhEmu->emu_maxcol - hhEmu->emu_curcol - n);
/* --- Move stuff down --- */
memmove(tp+n, tp, (unsigned)i * sizeof(ECHAR));
memmove(ap+n, tp, (unsigned)i * sizeof(STATTR));
memmove(pstMT+n, pstMT, (unsigned)i * sizeof(STMINITEL));
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] =
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + i;
/* --- Fill the gap --- */
memset(&stAttr, 0, sizeof(stAttr));
stAttr.txtclr = VC_BRT_WHITE;
stAttr.bkclr = VC_BLACK;
memset(&stMT, 0, sizeof(stMT));
stMT.ismosaic = (unsigned)pstPRI->minitelG1Active;
while (--i >= 0)
{
*tp++ = EMU_BLANK_CHAR;
*ap++ = stAttr;
*pstMT++ = stMT;
}
updateChar(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_currow,
hhEmu->emu_curcol,
hhEmu->emu_maxcol);
ANSI_Pn_Clr(hhEmu);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelDelRows
*
* DESCRIPTION:
* Deletes n rows from the current row.
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelDelRows(const HHEMU hhEmu)
{
int r, r1;
int c, i, n;
STATTR stAttr;
STMINITEL stMT;
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
// CSI sequences not available in row 0
//
if (hhEmu->emu_currow == 0)
return;
n = min(hhEmu->emu_maxrow, hhEmu->num_param[0]);
i = max(0, hhEmu->emu_maxrow - hhEmu->emu_currow - n);
for (i = 0 ; i < n ; ++i)
{
if ((hhEmu->emu_currow+i+n) > hhEmu->emu_maxrow)
break;
r = row_index(hhEmu, hhEmu->emu_currow+i);
r1 = row_index(hhEmu, hhEmu->emu_currow+i+n);
MemCopy(hhEmu->emu_apText[r],
hhEmu->emu_apText[r1],
sizeof(ECHAR) * (unsigned)(hhEmu->emu_maxcol+1));
MemCopy(hhEmu->emu_apAttr[r],
hhEmu->emu_apAttr[r1],
sizeof(STATTR) * (unsigned)(hhEmu->emu_maxcol+1));
MemCopy(pstPRI->apstMT[r],
pstPRI->apstMT[r1],
sizeof(STMINITEL) * (unsigned)(hhEmu->emu_maxcol+1));
hhEmu->emu_aiEnd[r] = hhEmu->emu_aiEnd[r1];
}
memset(&stAttr, 0, sizeof(stAttr));
stAttr.txtclr = VC_BRT_WHITE;
stAttr.bkclr = VC_BLACK;
memset(&stMT, 0, sizeof(stMT));
stMT.ismosaic = (unsigned)pstPRI->minitelG1Active;
for (n = max(0, hhEmu->emu_maxrow - i) ; n <= hhEmu->emu_maxrow ; ++n)
{
r = row_index(hhEmu, n);
for (c = 0 ; c <= hhEmu->emu_maxcol ; ++c)
{
hhEmu->emu_apText[r][c] = EMU_BLANK_CHAR;
hhEmu->emu_apAttr[r][c] = stAttr;
pstPRI->apstMT[r][c] = stMT;
hhEmu->emu_aiEnd[r] = EMU_BLANK_LINE;
}
}
updateLine(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_currow,
hhEmu->emu_maxrow);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelInsRows
*
* DESCRIPTION:
* Inserts n rows from current row inclusive
*
* ARGUMENTS:
* void
*
* RETURNS:
* void
*
*/
void minitelInsRows(const HHEMU hhEmu)
{
int r, r1;
int c, i, n;
STATTR stAttr;
STMINITEL stMT;
const PSTMTPRIVATE pstPRI = (PSTMTPRIVATE)hhEmu->pvPrivate;
if (hhEmu->emu_currow == 0)
return;
n = min(hhEmu->emu_maxrow, hhEmu->num_param[0]);
i = max(0, hhEmu->emu_maxrow - hhEmu->emu_currow - n);
for (i = 0 ; i < n ; ++i)
{
if ((hhEmu->emu_currow+i+n) > hhEmu->emu_maxrow)
break;
r = row_index(hhEmu, hhEmu->emu_currow+i);
r1 = row_index(hhEmu, hhEmu->emu_currow+i+n);
MemCopy(hhEmu->emu_apText[r1],
hhEmu->emu_apText[r],
sizeof(ECHAR) * (unsigned)(hhEmu->emu_maxcol+1));
MemCopy(hhEmu->emu_apAttr[r1],
hhEmu->emu_apAttr[r],
sizeof(STATTR) * (unsigned)(hhEmu->emu_maxcol+1));
MemCopy(pstPRI->apstMT[r1],
pstPRI->apstMT[r],
sizeof(STMINITEL) * (unsigned)(hhEmu->emu_maxcol+1));
hhEmu->emu_aiEnd[r1] = hhEmu->emu_aiEnd[r];
}
memset(&stAttr, 0, sizeof(stAttr));
stAttr.txtclr = VC_BRT_WHITE;
stAttr.bkclr = VC_BLACK;
memset(&stMT, 0, sizeof(stMT));
stMT.ismosaic = (unsigned)pstPRI->minitelG1Active;
for (n = hhEmu->emu_currow ; n < (hhEmu->emu_maxrow - i) ; ++n)
{
r = row_index(hhEmu, n);
for (c = 0 ; c <= hhEmu->emu_maxcol ; ++c)
{
hhEmu->emu_apText[r][c] = EMU_BLANK_CHAR;
hhEmu->emu_apAttr[r][c] = stAttr;
pstPRI->apstMT[r][c] = stMT;
hhEmu->emu_aiEnd[r] = EMU_BLANK_LINE;
}
}
updateLine(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_currow,
hhEmu->emu_maxrow);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitelHomeHostCursor
*
* DESCRIPTION:
* Sets cursor to home position which is 1, 0 in this case.
*
* ARGUMENTS:
* hhEmu - private emulator handle
*
* RETURNS:
* 0=OK,else error.
*
*/
int minitelHomeHostCursor(const HHEMU hhEmu)
{
if (hhEmu == 0)
{
assert(0);
return -1;
}
(*hhEmu->emu_setcurpos)(hhEmu, 1, 0);
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitel_scrollup
*
* DESCRIPTION:
* Mintels of course scroll differently. Actually, its the way they
* clear lines that keeps us from using the standard stuff.
*
* ARGUMENTS:
* hhEmu - private emulator handle.
* nlines - number of lines to scroll.
*
* RETURNS:
* void
*
*/
void minitel_scrollup(const HHEMU hhEmu, int nlines)
{
register INT row;
INT nrows, iLen, iThisRow;
ECHAR *lp; /* line pointer */
INT nScrlInc; /* needed for call to Vid routine at bottom of func */
if (nlines <= 0)
return;
hhEmu->scr_scrollcnt += nlines;
nScrlInc = nlines = min(nlines,
hhEmu->bottom_margin - hhEmu->top_margin + 1);
for (row = hhEmu->top_margin; row < (hhEmu->top_margin + nlines); ++row)
{
iThisRow = row_index(hhEmu, row);
lp = hhEmu->emu_apText[iThisRow];
iLen = emuRowLen(hhEmu, iThisRow);
minitel_clear_imgrow(hhEmu, row);
}
if (hhEmu->top_margin == 0 && hhEmu->bottom_margin == hhEmu->emu_maxrow)
{
hhEmu->emu_imgtop = row_index(hhEmu, nlines);
}
else if (nlines < (hhEmu->bottom_margin - hhEmu->top_margin + 1))
{
nrows = hhEmu->bottom_margin - hhEmu->top_margin + 1 - nlines;
for (row = hhEmu->top_margin; nrows > 0; --nrows, ++row)
{
INT c;
PSTATTR pstAttr, pstAttr2;
PSTMINITEL pstMT, pstMT2;
memmove(hhEmu->emu_apText[row_index(hhEmu, row)],
hhEmu->emu_apText[row_index(hhEmu, row + nlines)],
(size_t)hhEmu->emu_maxcol + 2);
hhEmu->emu_aiEnd[row_index(hhEmu, row + nlines)] =
hhEmu->emu_aiEnd[row_index(hhEmu, row)];
pstAttr = hhEmu->emu_apAttr[row_index(hhEmu, row)];
pstAttr2 = hhEmu->emu_apAttr[row_index(hhEmu, row + nlines)];
for (c = 0 ; c <= hhEmu->emu_maxcol ; ++c)
pstAttr[c] = pstAttr2[c];
pstMT = ((PSTMTPRIVATE)hhEmu->pvPrivate)->apstMT[row_index(hhEmu, row)];
pstMT2= ((PSTMTPRIVATE)hhEmu->pvPrivate)->apstMT[row_index(hhEmu, row + nlines)];
for (c = 0 ; c <= hhEmu->emu_maxcol ; ++c)
pstMT[c] = pstMT2[c];
}
for (row = hhEmu->bottom_margin; nlines > 0; --nlines, --row)
minitel_clear_imgrow(hhEmu, row);
}
hhEmu->emu_imgrow = row_index(hhEmu, hhEmu->emu_currow);
updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->top_margin,
hhEmu->bottom_margin,
nScrlInc,
hhEmu->emu_imgtop,
TRUE);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitel_scrolldown
*
* DESCRIPTION:
* Minitel of course works differently. Mostly is has more work to
* clear a line.
*
* ARGUMENTS:
* hhEmu - private emulator handle
* nlines - number of lines to scroll
*
* RETURNS:
* void
*
*/
void minitel_scrolldown(const HHEMU hhEmu, int nlines)
{
register int row, nrows;
int toprow, botmrow;
int nScrlInc;
if (nlines <= 0)
return;
hhEmu->scr_scrollcnt -= nlines;
nScrlInc = nlines;
toprow = hhEmu->top_margin;
botmrow = hhEmu->bottom_margin;
if (hhEmu->top_margin == 0 && hhEmu->bottom_margin == hhEmu->emu_maxrow)
{
hhEmu->emu_imgtop = row_index(hhEmu, -nlines);
}
else if (nlines < hhEmu->bottom_margin - hhEmu->top_margin + 1)
{
nrows = hhEmu->bottom_margin - hhEmu->top_margin + 1 - nlines;
for (row = hhEmu->bottom_margin; nrows > 0; --nrows, --row)
{
int c;
PSTATTR pstAttr, pstAttr2;
PSTMINITEL pstMT, pstMT2;
memmove(hhEmu->emu_apText[row_index(hhEmu, row)],
hhEmu->emu_apText[row_index(hhEmu, row - nlines)],
(size_t)(hhEmu->emu_maxcol+2));
hhEmu->emu_aiEnd[row_index(hhEmu, row - nlines)] =
hhEmu->emu_aiEnd[row_index(hhEmu, row)];
pstAttr = hhEmu->emu_apAttr[row_index(hhEmu, row)];
pstAttr2 = hhEmu->emu_apAttr[row_index(hhEmu, row - nlines)];
for (c = 0 ; c <= hhEmu->emu_maxcol ; ++c)
pstAttr[c] = pstAttr2[c];
pstMT = ((PSTMTPRIVATE)hhEmu->pvPrivate)->apstMT[row_index(hhEmu, row)];
pstMT2= ((PSTMTPRIVATE)hhEmu->pvPrivate)->apstMT[row_index(hhEmu, row + nlines)];
for (c = 0 ; c <= hhEmu->emu_maxcol ; ++c)
pstMT[c] = pstMT2[c];
}
}
for (row = hhEmu->top_margin; nlines > 0; --nlines, ++row)
minitel_clear_imgrow(hhEmu, row);
hhEmu->emu_imgrow = row_index(hhEmu, hhEmu->emu_currow);
updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
toprow, botmrow, -nScrlInc, hhEmu->emu_imgtop, TRUE);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* minitel_clear_imgrow
*
* DESCRIPTION:
* minitel's have to do more work to clear a line.
*
* ARGUMENTS:
* hhEmu - private minitel handle.
* row - row to clear
*
* RETURNS:
* void
*
*/
static void minitel_clear_imgrow(const HHEMU hhEmu, const int row)
{
const int save_row = hhEmu->emu_currow;
const int save_imgrow = hhEmu->emu_imgrow;
hhEmu->emu_currow = row;
hhEmu->emu_imgrow = row_index(hhEmu, row);
minitelClearLine(hhEmu, 2);
hhEmu->emu_currow = save_row;
hhEmu->emu_imgrow = save_imgrow;
return;
}
#endif // INCL_MINITEL