|
|
/* 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
|