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.
556 lines
13 KiB
556 lines
13 KiB
/* File: D:\WACKER\tdll\termcpy.c (Created: 24-Jan-1994)
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 4 $
|
|
* $Date: 5/09/01 4:38p $
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
#include "stdtyp.h"
|
|
#include "mc.h"
|
|
#include "tdll.h"
|
|
#include "htchar.h"
|
|
#include "session.h"
|
|
#include "backscrl.h"
|
|
#include "assert.h"
|
|
#include <emu\emu.h>
|
|
#include "term.hh"
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* CopyMarkedTextFromTerminal
|
|
*
|
|
* DESCRIPTION:
|
|
* Helper function that gets the marked region and passes the call
|
|
* onto CopyTextFromTerminal().
|
|
*
|
|
* ARGUMENTS:
|
|
* hSession - public session handle
|
|
* ppv - pointer to a buffer pointer
|
|
* pdwCnt - pointer to size variable
|
|
* fIncludeLF - TRUE means include linefeeds.
|
|
*
|
|
* RETURNS:
|
|
* BOOL
|
|
*
|
|
*/
|
|
BOOL CopyMarkedTextFromTerminal(const HSESSION hSession, void **ppv,
|
|
DWORD *pdwCnt, const BOOL fIncludeLF)
|
|
{
|
|
BOOL fReturn;
|
|
ECHAR *pechBuf;
|
|
TCHAR *pszOutput;
|
|
const HWND hwndTerm = sessQueryHwndTerminal(hSession);
|
|
const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwndTerm, GWLP_USERDATA);
|
|
|
|
fReturn = CopyTextFromTerminal(hSession, &hhTerm->ptBeg, &hhTerm->ptEnd,
|
|
ppv, pdwCnt, fIncludeLF);
|
|
|
|
pechBuf = *ppv;
|
|
// Strip Out Any repeated Characters in the string
|
|
StrCharStripDBCSString(pechBuf, (long)StrCharGetEcharByteCount(pechBuf), pechBuf);
|
|
|
|
// hMem currently points to an array of ECHAR's, convert this to
|
|
// TCHARS before giving the results to the caller.
|
|
pszOutput = malloc((ULONG)StrCharGetEcharByteCount(pechBuf) + 1);
|
|
CnvrtECHARtoMBCS(pszOutput, (ULONG)StrCharGetEcharByteCount(pechBuf) + 1,
|
|
pechBuf,StrCharGetEcharByteCount(pechBuf)+1);//mrw:5/17/95
|
|
*(pszOutput + StrCharGetEcharByteCount(pechBuf)) = ETEXT('\0');
|
|
free(pechBuf);
|
|
pechBuf = NULL;
|
|
*ppv = pszOutput;
|
|
*pdwCnt = (ULONG)StrCharGetByteCount(pszOutput);
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* CopyTextFromTerminal
|
|
*
|
|
* DESCRIPTION:
|
|
* A work-horse function that will use the given points as a marked region
|
|
* and do the necessary work to make a copy of the marked text into
|
|
* a new memory region. The marked range can include the backscroll
|
|
* region and cross into the terminal region. The begining and ending
|
|
* points are in terminal coordinates (backscroll lines are numbered
|
|
* -1 to -infinity, terminal lines are numbered 1 to 24, line 0 is the
|
|
* divider line and does not exist for copies but can be included in
|
|
* the range). It is *not* a requirement that the begininig point be
|
|
* less than the ending point.
|
|
*
|
|
* ARGUMENTS:
|
|
* HSESSION hSession - handle to the session.
|
|
* LPPOINT lpptBeg - begining point of marked region.
|
|
* LPPOINT lpptEnd - end point of mark region.
|
|
* void **pv - pointer to buffer pointer
|
|
* DWORD *pdwCnt - pointer to double word for size
|
|
* BOOL fIncludeLF -
|
|
*
|
|
* RETURNS:
|
|
* BOOL
|
|
*
|
|
*/
|
|
BOOL CopyTextFromTerminal(const HSESSION hSession,
|
|
const PPOINT pptBeg,
|
|
const PPOINT pptEnd,
|
|
void **ppv,
|
|
DWORD *pdwCnt,
|
|
const BOOL fIncludeLF)
|
|
{
|
|
int iWant,
|
|
iGot,
|
|
yLn,
|
|
xCol,
|
|
iLen,
|
|
iTmp,
|
|
iRows,
|
|
iCols,
|
|
iTopline,
|
|
iOffset,
|
|
iBkLns,
|
|
iSize;
|
|
DWORD dwSize, dwOldSize;
|
|
ECHAR *lpachTxt;
|
|
ECHAR *lpachBuf;
|
|
ECHAR achTmp[256],
|
|
*pachTmp;
|
|
ECHAR **alpstrTxt;
|
|
long lBeg, lEnd;
|
|
HCURSOR hCursor;
|
|
ECHAR *hMem = 0; // malloc memory
|
|
ECHAR *hMemTmp = 0; // malloc memory
|
|
POINT ptBeg, ptEnd, ptTmp;
|
|
const HWND hwndTerm = sessQueryHwndTerminal(hSession);
|
|
const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwndTerm, GWLP_USERDATA);
|
|
const HBACKSCRL hBackscrl = sessQueryBackscrlHdl(hhTerm->hSession);
|
|
|
|
*ppv = 0;
|
|
*pdwCnt = 0;
|
|
|
|
hCursor = SetCursor(LoadCursor((HINSTANCE)0, IDC_WAIT));
|
|
dwSize = 1; // By starting at one, we always have room for the '\0'.
|
|
|
|
iRows = hhTerm->iRows;
|
|
iCols = hhTerm->iCols;
|
|
iTopline = hhTerm->iTopline;
|
|
alpstrTxt = hhTerm->fplpstrTxt;
|
|
|
|
ptBeg = *pptBeg;
|
|
ptEnd = *pptEnd;
|
|
|
|
/* --- do some range checking for the line number --- */
|
|
|
|
iBkLns = backscrlGetNumLines(hBackscrl);
|
|
iBkLns = -iBkLns;
|
|
|
|
if (ptBeg.y > 0 && ptBeg.y > iRows)
|
|
ptBeg.y = iRows;
|
|
|
|
if (ptBeg.y < 0 && ptBeg.y < iBkLns)
|
|
ptBeg.y = iBkLns;
|
|
|
|
if (ptEnd.y > 0 && ptEnd.y > iRows)
|
|
ptEnd.y = iRows;
|
|
|
|
if (ptEnd.y < 0 && ptEnd.y < iBkLns)
|
|
ptEnd.y = iBkLns;
|
|
|
|
/* --- and do some range checking for the column number --- */
|
|
|
|
if (ptBeg.x < 0) /* negative column doesn't make much sense */
|
|
ptBeg.x = 0;
|
|
|
|
if (ptBeg.x >= iCols)
|
|
ptBeg.x = iCols - 1;
|
|
|
|
if (ptEnd.x < 0) /* see above */
|
|
ptEnd.x = 0;
|
|
|
|
if (ptEnd.x >= iCols)
|
|
ptEnd.x = iCols - 1;
|
|
|
|
/* --- convert to offsets --- */
|
|
|
|
lBeg = (ptBeg.y * iCols) + ptBeg.x;
|
|
lEnd = (ptEnd.y * iCols) + ptEnd.x;
|
|
|
|
if (lBeg == lEnd)
|
|
{
|
|
SetCursor(hCursor);
|
|
return FALSE;
|
|
}
|
|
|
|
sessSetSuspend(hSession, SUSPEND_TERMINAL_COPY);
|
|
|
|
if (lBeg > lEnd)
|
|
{
|
|
ptTmp = ptEnd;
|
|
ptEnd = ptBeg;
|
|
ptBeg = ptTmp;
|
|
}
|
|
|
|
if ((hMem = malloc(dwSize * sizeof(ECHAR))) == 0)
|
|
{
|
|
assert(FALSE);
|
|
SetCursor(hCursor);
|
|
sessClearSuspend(hSession, SUSPEND_TERMINAL_COPY);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get first line of range
|
|
|
|
iGot = 0;
|
|
lpachTxt = 0;
|
|
achTmp[0] = ETEXT('\0');
|
|
|
|
if (ptBeg.y < 0)
|
|
{
|
|
xCol = ptBeg.x;
|
|
yLn = ptBeg.y;
|
|
iWant = ptEnd.y - ptBeg.y + 1;
|
|
|
|
if (iWant > 0)
|
|
{
|
|
while (iWant > 0)
|
|
{
|
|
if (backscrlGetBkLines(hBackscrl, yLn, iWant, &iGot,
|
|
&lpachTxt, &iOffset) == FALSE)
|
|
{
|
|
goto PROCESS_ERROR;
|
|
}
|
|
|
|
lpachTxt += iOffset;
|
|
|
|
// Lets say the user has highlighted an area of the backscroll
|
|
// region that has no data (ie. a blank line). Adding xCol to
|
|
// lpachTxt is incorrect. This for-loop checks for this
|
|
// condition and resets lpachTxt to the beginning of the line.
|
|
// Incidentally, this also sets xCol to 0 which is necessary
|
|
// for subsequent lines to feed in correctly.
|
|
|
|
for (lpachBuf = lpachTxt ; xCol > 0 ; --xCol, ++lpachTxt)
|
|
{
|
|
if (*lpachTxt == ETEXT('\n'))
|
|
{
|
|
lpachTxt = lpachBuf;
|
|
xCol = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
iWant -= iGot;
|
|
|
|
while (iGot-- > 0 && yLn < ptEnd.y && yLn < -1)
|
|
{
|
|
for (pachTmp = achTmp, iTmp = 0 ;
|
|
*lpachTxt != ETEXT('\n') &&
|
|
//
|
|
// Fix for not getting full backscroll buffer
|
|
// in DBCS versions by taking into account the
|
|
// size of the ECHAR. REV: 03/07/2001
|
|
//
|
|
iTmp < MAX_EMUCOLS * sizeof(ECHAR);
|
|
++pachTmp, ++iTmp)
|
|
{
|
|
*pachTmp = *lpachTxt++;
|
|
}
|
|
|
|
// Fail Safe: if the text we received from
|
|
// backscrlGetBkLines() is mangled somehow and we
|
|
// don't see a newline, then abort before we seg.
|
|
|
|
//
|
|
// Fix for not getting full backscroll buffer
|
|
// in DBCS versions by taking into account the
|
|
// size of the ECHAR. REV: 03/07/2001
|
|
//
|
|
|
|
if (iTmp >= MAX_EMUCOLS * sizeof(ECHAR))
|
|
goto PROCESS_ERROR;
|
|
|
|
lpachTxt += 1;
|
|
*pachTmp++ = ETEXT('\r');
|
|
|
|
if (fIncludeLF)
|
|
*pachTmp++ = ETEXT('\n');
|
|
|
|
*pachTmp = ETEXT('\0');
|
|
|
|
hMemTmp = hMem;
|
|
dwOldSize = dwSize - 1;
|
|
dwSize += (DWORD)StrCharGetEcharLen(achTmp);
|
|
hMem = realloc(hMemTmp, dwSize *sizeof(ECHAR));
|
|
|
|
if (hMem == 0)
|
|
goto PROCESS_ERROR;
|
|
|
|
/* remember how a realloc works */
|
|
hMemTmp = (ECHAR *)0;
|
|
|
|
lpachBuf = hMem + dwOldSize;
|
|
iSize = StrCharGetEcharByteCount(achTmp);
|
|
if ( iSize )
|
|
MemCopy(lpachBuf, achTmp, iSize );
|
|
hMem[dwSize - 1] = ETEXT('\0');
|
|
|
|
yLn += 1;
|
|
}
|
|
|
|
if (yLn >= ptEnd.y || yLn >= -1)
|
|
break;
|
|
}
|
|
|
|
// Another bug bytes the dust. Wasn't checking to see if iGot
|
|
// was the reason we exited the loop above. It caused things
|
|
// to seg occassionally.
|
|
|
|
if (iGot >= 0)
|
|
{
|
|
// Last line stuff (could be crossing into terminal area but
|
|
// we still need to clean-up backscroll stuff.
|
|
|
|
if (ptBeg.y == ptEnd.y)
|
|
xCol = ptEnd.x - ptBeg.x;
|
|
|
|
else if (ptEnd.y < 0) /* && ptEnd.x > 0) removed - mrw */
|
|
xCol = ptEnd.x;
|
|
|
|
else
|
|
xCol = iCols;
|
|
|
|
for (pachTmp = achTmp ; xCol-- > 0 && *lpachTxt != ETEXT('\n'); ++pachTmp)
|
|
*pachTmp = *lpachTxt++;
|
|
|
|
if (ptEnd.y >= 0)
|
|
{
|
|
*pachTmp++ = ETEXT('\r');
|
|
|
|
if (fIncludeLF)
|
|
*pachTmp++ = ETEXT('\n');
|
|
}
|
|
|
|
*pachTmp = ETEXT('\0');
|
|
}
|
|
|
|
hMemTmp = hMem;
|
|
dwOldSize = dwSize - 1;
|
|
dwSize += (DWORD)StrCharGetEcharLen(achTmp);
|
|
|
|
hMem = realloc(hMemTmp, dwSize * sizeof(ECHAR));
|
|
|
|
if (hMem == 0)
|
|
goto PROCESS_ERROR;
|
|
|
|
/* remember how a realloc works */
|
|
hMemTmp = (ECHAR *)0;
|
|
|
|
lpachBuf = hMem + dwOldSize;
|
|
iSize = StrCharGetEcharByteCount(achTmp);
|
|
if ( iSize )
|
|
MemCopy(lpachBuf, achTmp, iSize);
|
|
hMem[dwSize - 1] = ETEXT('\0');
|
|
} // end if (iWant > 0)
|
|
|
|
// terminal area...
|
|
|
|
if (ptEnd.y >= 0)
|
|
{
|
|
yLn = 1;
|
|
|
|
while (yLn <= ptEnd.y)
|
|
{
|
|
iTmp = ((yLn + iTopline) % MAX_EMUROWS) - 1;
|
|
|
|
if (iTmp < 0)
|
|
iTmp = MAX_EMUROWS - 1;
|
|
|
|
lpachTxt = alpstrTxt[iTmp];
|
|
|
|
iLen = strlentrunc(lpachTxt, iCols);
|
|
xCol = (yLn == ptEnd.y) ? min(ptEnd.x, iLen) : iLen;
|
|
|
|
for (pachTmp = achTmp ; xCol > 0 ; --xCol)
|
|
*pachTmp++ = *lpachTxt++;
|
|
|
|
if (yLn != ptEnd.y)
|
|
{
|
|
*pachTmp++ = ETEXT('\r');
|
|
|
|
if (fIncludeLF)
|
|
*pachTmp++ = ETEXT('\n');
|
|
}
|
|
|
|
*pachTmp = ETEXT('\0');
|
|
|
|
hMemTmp = hMem;
|
|
dwOldSize = dwSize - 1;
|
|
dwSize += (DWORD)StrCharGetEcharLen(achTmp);
|
|
hMem = realloc(hMemTmp, dwSize * sizeof(ECHAR));
|
|
|
|
if (hMem == 0)
|
|
goto PROCESS_ERROR;
|
|
|
|
/* remember how a realloc works */
|
|
hMemTmp = (ECHAR *)0;
|
|
|
|
lpachBuf = hMem + dwOldSize;
|
|
iSize = StrCharGetEcharByteCount(achTmp);
|
|
if ( iSize )
|
|
MemCopy(lpachBuf, achTmp, iSize );
|
|
hMem[dwSize - 1] = ETEXT('\0');
|
|
|
|
yLn += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
else // terminal only case
|
|
{
|
|
if (ptBeg.y >= 0)
|
|
{
|
|
yLn = ptBeg.y;
|
|
|
|
while (yLn <= ptEnd.y)
|
|
{
|
|
iTmp = ((yLn + iTopline) % MAX_EMUROWS) - 1;
|
|
|
|
if (iTmp < 0)
|
|
iTmp = MAX_EMUROWS - 1;
|
|
|
|
lpachTxt = alpstrTxt[iTmp];
|
|
|
|
if (ptBeg.y == ptEnd.y)
|
|
{
|
|
lpachTxt += ptBeg.x;
|
|
|
|
xCol = min(strlentrunc(lpachTxt, iCols - ptBeg.x),
|
|
ptEnd.x - ptBeg.x);
|
|
}
|
|
|
|
else if (yLn == ptBeg.y)
|
|
{
|
|
lpachTxt += ptBeg.x;
|
|
xCol = strlentrunc(lpachTxt, iCols - ptBeg.x);
|
|
}
|
|
|
|
else if (yLn == ptEnd.y)
|
|
{
|
|
xCol = min(ptEnd.x, strlentrunc(lpachTxt, iCols));
|
|
}
|
|
|
|
else
|
|
{
|
|
xCol = strlentrunc(lpachTxt, iCols);
|
|
}
|
|
|
|
|
|
for (pachTmp = achTmp ; xCol > 0 ; --xCol)
|
|
*pachTmp++ = *lpachTxt++;
|
|
|
|
|
|
if (yLn != ptEnd.y)
|
|
{
|
|
*pachTmp++ = ETEXT('\r');
|
|
|
|
if (fIncludeLF)
|
|
*pachTmp++ = ETEXT('\n');
|
|
}
|
|
|
|
*pachTmp = ETEXT('\0');
|
|
|
|
hMemTmp = hMem;
|
|
dwOldSize = dwSize - 1;
|
|
dwSize += (DWORD)StrCharGetEcharLen(achTmp);
|
|
hMem = realloc(hMemTmp, dwSize * sizeof(ECHAR));
|
|
|
|
if (hMem == 0)
|
|
goto PROCESS_ERROR;
|
|
|
|
/* remember how a realloc works */
|
|
hMemTmp = (ECHAR *)0;
|
|
|
|
lpachBuf = hMem + dwOldSize;
|
|
|
|
iSize = StrCharGetEcharByteCount(achTmp);
|
|
if ( iSize )
|
|
MemCopy(lpachBuf, achTmp, iSize );
|
|
hMem[dwSize - 1] = ETEXT('\0');
|
|
|
|
yLn += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetCursor(hCursor);
|
|
|
|
*ppv = hMem;
|
|
*pdwCnt = (ULONG)StrCharGetEcharByteCount(hMem);
|
|
sessClearSuspend(hSession, SUSPEND_TERMINAL_COPY);
|
|
return TRUE;
|
|
|
|
// process error condition here.
|
|
|
|
PROCESS_ERROR:
|
|
|
|
if (hMem)
|
|
{
|
|
free(hMem);
|
|
hMem = NULL;
|
|
}
|
|
|
|
if (hMemTmp)
|
|
{
|
|
free(hMemTmp);
|
|
hMemTmp = NULL;
|
|
}
|
|
|
|
SetCursor(hCursor);
|
|
sessClearSuspend(hSession, SUSPEND_TERMINAL_COPY);
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* strlentrunc
|
|
*
|
|
* DESCRIPTION:
|
|
* Finds the length of a character buffer less the trailing whitespace.
|
|
*
|
|
* ARGUMENTS:
|
|
* pach - array of t characters
|
|
* iLen - length of buffer
|
|
*
|
|
* RETURNS:
|
|
* new length
|
|
*
|
|
*/
|
|
int strlentrunc(const ECHAR *pach, const int iLen)
|
|
{
|
|
int i;
|
|
|
|
for (i = iLen-1 ; i >= 0 ; --i)
|
|
{
|
|
switch (pach[i])
|
|
{
|
|
/* Whitespace characters */
|
|
case ETEXT('\0'):
|
|
case ETEXT('\t'):
|
|
case ETEXT('\n'):
|
|
case ETEXT('\v'):
|
|
case ETEXT('\f'):
|
|
case ETEXT('\r'):
|
|
case ETEXT(' '):
|
|
break;
|
|
|
|
default:
|
|
return i+1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|