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.
829 lines
23 KiB
829 lines
23 KiB
/*** winclip.c - windows clipboard editor extension
|
|
*
|
|
* Copyright <C> 1988, Microsoft Corporation
|
|
*
|
|
* Purpose:
|
|
* Contains the tglcase function.
|
|
*
|
|
* Revision History:
|
|
*
|
|
* 28-Jun-1988 LN Created
|
|
* 12-Sep-1988 mz Made WhenLoaded match declaration
|
|
*
|
|
*************************************************************************/
|
|
#define EXT_ID " winclip ver 1.00 "##__DATE__
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h> /* min macro definition */
|
|
#include <string.h> /* prototypes for string fcns */
|
|
|
|
#undef pascal
|
|
#include "../../inc/ext.h"
|
|
|
|
#define M_FALSE ((flagType)0)
|
|
#define M_TRUE ((flagType)(-1))
|
|
|
|
#define BUFLEN_MAX (BUFLEN-1)
|
|
|
|
/*
|
|
** Internal function prototypes
|
|
*/
|
|
void pascal id (char *);
|
|
void EXTERNAL WhenLoaded (void);
|
|
flagType pascal EXTERNAL wincopy (unsigned int, ARG far *, flagType);
|
|
flagType pascal EXTERNAL wincut (unsigned int, ARG far *, flagType);
|
|
flagType pascal EXTERNAL winpaste (unsigned int, ARG far *, flagType);
|
|
|
|
#ifdef DEBUG
|
|
# define DPRINT(p) DoMessage(p)
|
|
#else
|
|
# define DPRINT(p)
|
|
#endif
|
|
|
|
HWND ghwndClip;
|
|
HINSTANCE ghmod;
|
|
int gfmtArgType;
|
|
|
|
void DeleteArg( PFILE pFile, int argType, COL xStart, LINE yStart,
|
|
COL xEnd, COL yEnd );
|
|
|
|
void InsertText( PFILE pFile, LPSTR pszText, DWORD dwInsMode,
|
|
COL xStart, LINE yStart );
|
|
flagType pascal EXTERNAL WinCutCopy (ARG *pArg, flagType fCut, flagType fClip);
|
|
LPSTR EndOfLine( LPSTR psz );
|
|
LPSTR EndOfBreak( LPSTR psz );
|
|
int ExtendLine( LPSTR psz, int cchSZ, char ch, int cchNew );
|
|
|
|
/*************************************************************************
|
|
**
|
|
** wincopy
|
|
** Toggle the case of alphabetics contaied within the selected argument:
|
|
**
|
|
** NOARG - Toggle case of entire current line
|
|
** NULLARG - Toggle case of current line, from cursor to end of line
|
|
** LINEARG - Toggle case of range of lines
|
|
** BOXARG - Toggle case of characters with the selected box
|
|
** NUMARG - Converted to LINEARG before extension is called.
|
|
** MARKARG - Converted to Appropriate ARG form above before extension is
|
|
** called.
|
|
**
|
|
** STREAMARG - Not Allowed. Treated as BOXARG
|
|
** TEXTARG - Not Allowed
|
|
**
|
|
*/
|
|
flagType pascal EXTERNAL wincopy (
|
|
unsigned int argData, /* keystroke invoked with */
|
|
ARG *pArg, /* argument data */
|
|
flagType fMeta /* indicates preceded by meta */
|
|
) {
|
|
|
|
return WinCutCopy( pArg, M_FALSE, M_FALSE );
|
|
}
|
|
|
|
flagType pascal EXTERNAL wincut (
|
|
unsigned int argData, /* keystroke invoked with */
|
|
ARG *pArg, /* argument data */
|
|
flagType fMeta /* indicates preceded by meta */
|
|
) {
|
|
|
|
return WinCutCopy( pArg, M_TRUE, fMeta );
|
|
}
|
|
|
|
flagType pascal EXTERNAL WinCutCopy (ARG *pArg, flagType fCut, flagType fNoClip)
|
|
{
|
|
PFILE pFile; /* file handle of current file */
|
|
COL xStart, xEnd;
|
|
LINE yStart, yEnd;
|
|
char achLine[BUFLEN];
|
|
HANDLE hText;
|
|
LPSTR pszText;
|
|
int iLine, cchLine;
|
|
flagType fRet = M_TRUE;
|
|
int argSave, argType;
|
|
|
|
pFile = FileNameToHandle ("", "");
|
|
|
|
|
|
argSave = argType = pArg->argType;
|
|
|
|
switch( argType ) {
|
|
case BOXARG: /* case switch box */
|
|
xStart = pArg->arg.boxarg.xLeft;
|
|
xEnd = pArg->arg.boxarg.xRight + 1;
|
|
yStart = pArg->arg.boxarg.yTop;
|
|
yEnd = pArg->arg.boxarg.yBottom + 1;
|
|
|
|
/* At this point...
|
|
* [xy]Start is Inclusive, [xy]End is EXCLUSIVE of the box arg
|
|
*/
|
|
|
|
#ifdef DEBUG
|
|
wsprintf( achLine, " BoxDims : %d %d %d %d ", (int)xStart, (int)yStart, (int)xEnd, (int)yEnd);
|
|
DoMessage( achLine );
|
|
#endif
|
|
break;
|
|
|
|
case NOARG:
|
|
/* convert NOARG to a STREAMARG on whole current line */
|
|
argType = STREAMARG;
|
|
argSave = LINEARG;
|
|
xStart = 0;
|
|
yStart = pArg->arg.noarg.y;
|
|
xEnd = 0;
|
|
yEnd = yStart + 1;
|
|
break;
|
|
|
|
case TEXTARG:
|
|
/*
|
|
* Text args are only for real text. NumArgs and MarkArgs are
|
|
* converted to stream or box args by the editor since we say
|
|
* we accept NUMARG and MARKARG during initialization.
|
|
*/
|
|
argType = STREAMARG;
|
|
argSave = STREAMARG;
|
|
xStart = pArg->arg.textarg.x;
|
|
xEnd = lstrlen(pArg->arg.textarg.pText) + xStart;
|
|
yStart = yEnd = pArg->arg.textarg.y;
|
|
break;
|
|
|
|
case LINEARG: /* case switch line range */
|
|
/* convert LINEARG to a STREAMARG so we don't get lots of white space*/
|
|
argType = STREAMARG;
|
|
xStart = 0;
|
|
xEnd = 0;
|
|
yStart = pArg->arg.linearg.yStart;
|
|
yEnd = pArg->arg.linearg.yEnd + 1;
|
|
#ifdef DEBUG
|
|
wsprintf( achLine, " LineDims : %d %d %d %d ", (int)xStart, (int)yStart, (int)xEnd, (int)yEnd);
|
|
DoMessage( achLine );
|
|
#endif
|
|
|
|
/* At this point...
|
|
* [xy]Start is Inclusive, [xy]End is EXCLUSIVE of the line arg
|
|
*/
|
|
|
|
break;
|
|
|
|
case STREAMARG:
|
|
/*
|
|
* Set Start == first char pos in stream, End == first char pos
|
|
* AFTER stream.
|
|
*/
|
|
xStart = pArg->arg.streamarg.xStart;
|
|
xEnd = pArg->arg.streamarg.xEnd;
|
|
yStart = pArg->arg.streamarg.yStart;
|
|
yEnd = pArg->arg.streamarg.yEnd;
|
|
#ifdef DEBUG
|
|
wsprintf( achLine, " StreamDims : %d %d %d %d ", (int)xStart, (int)yStart, (int)xEnd, (int)yEnd);
|
|
DoMessage( achLine );
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
#ifdef DEBUG
|
|
wsprintf( achLine, " Unknown Arg: 0x%04x", argType );
|
|
DoMessage( achLine );
|
|
return M_TRUE;
|
|
#endif
|
|
return M_FALSE;
|
|
}
|
|
|
|
if (!fNoClip) {
|
|
if (argType == STREAMARG) {
|
|
int cch = 0;
|
|
int iChar;
|
|
|
|
for( iLine = yStart; iLine <= yEnd; iLine++ )
|
|
cch += GetLine (iLine, achLine, pFile) + 3;
|
|
|
|
hText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cch);
|
|
|
|
if (hText == NULL) {
|
|
DoMessage( " winclip: Out of Memory" );
|
|
return M_FALSE;
|
|
}
|
|
|
|
pszText = GlobalLock(hText);
|
|
|
|
|
|
iChar = xStart;
|
|
|
|
for( iLine = yStart; iLine < yEnd; iLine++ ) {
|
|
cchLine = GetLine (iLine, achLine, pFile);
|
|
|
|
/* Incase we start after the end of the line */
|
|
if (cchLine < iChar)
|
|
cch = 0;
|
|
else
|
|
cch = cchLine - iChar;
|
|
|
|
CopyMemory(pszText, &achLine[iChar], cch);
|
|
pszText += cch;
|
|
strcpy( pszText, "\r\n" );
|
|
pszText += 2;
|
|
iChar = 0;
|
|
|
|
}
|
|
|
|
/* Get partial last line */
|
|
if (xEnd != 0) {
|
|
cchLine = GetLine (iLine, achLine, pFile);
|
|
|
|
/* if line is short, then pad it out */
|
|
cchLine = ExtendLine( achLine, cchLine, ' ', xEnd );
|
|
|
|
if (cchLine < iChar)
|
|
cchLine = 0;
|
|
else
|
|
cchLine = xEnd - iChar;
|
|
|
|
CopyMemory(pszText, &achLine[iChar], cchLine);
|
|
pszText += cchLine;
|
|
}
|
|
|
|
} else {
|
|
int cchBox = xEnd - xStart;
|
|
|
|
hText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
|
|
(yEnd - yStart) * (cchBox + 3));
|
|
|
|
if (hText == NULL) {
|
|
DoMessage( " winclip: Out of Memory" );
|
|
return M_FALSE;
|
|
}
|
|
|
|
pszText = GlobalLock(hText);
|
|
|
|
for( iLine = yStart; iLine < yEnd; iLine++ ) {
|
|
cchLine = GetLine (iLine, achLine, pFile);
|
|
|
|
if (argType == BOXARG)
|
|
cchLine = ExtendLine( achLine, cchLine, ' ', xEnd );
|
|
|
|
if (cchLine < xStart )
|
|
cchLine = 0;
|
|
else
|
|
cchLine -= xStart;
|
|
|
|
cchLine = min(cchLine, cchBox);
|
|
|
|
CopyMemory(pszText, &achLine[xStart], cchLine);
|
|
pszText += cchLine;
|
|
strcpy( pszText, "\r\n" );
|
|
pszText += 2;
|
|
|
|
}
|
|
}
|
|
|
|
*pszText = '\0';
|
|
|
|
GlobalUnlock(hText);
|
|
|
|
if (OpenClipboard(ghwndClip)) {
|
|
EmptyClipboard();
|
|
|
|
/*
|
|
* Set the text into the clipboard
|
|
*/
|
|
if (SetClipboardData(CF_TEXT, hText) == hText) {
|
|
/*
|
|
* Remember the Arg type for pasting back
|
|
*/
|
|
if (gfmtArgType != 0) {
|
|
DWORD *pdw;
|
|
HANDLE hArgType = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
|
|
sizeof(DWORD));
|
|
|
|
if (hArgType != NULL && (pdw = GlobalLock(hArgType)) != NULL) {
|
|
*pdw = (DWORD)(argSave);
|
|
|
|
GlobalUnlock(hArgType);
|
|
|
|
SetClipboardData(gfmtArgType, hArgType);
|
|
}
|
|
}
|
|
} else {
|
|
/* An error occured writing text to clipboard */
|
|
|
|
wsprintf(achLine, " winclip: Error (%ld) setting data",
|
|
GetLastError());
|
|
DoMessage( achLine );
|
|
fRet = M_FALSE;
|
|
}
|
|
|
|
CloseClipboard();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* No need to free the handle, USER32 will do it (yes it keeps
|
|
* track of the client side handle) when we set the next clipboard
|
|
* data. (Love that Win3.1 compatibility!)
|
|
*/
|
|
if (fRet && fCut)
|
|
DeleteArg( pFile, argType, xStart, yStart, xEnd, yEnd );
|
|
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*************************************************************************
|
|
**
|
|
** winpaste
|
|
** Toggle the case of alphabetics contaied within the selected argument:
|
|
**
|
|
** NOARG - Toggle case of entire current line
|
|
** NULLARG - Toggle case of current line, from cursor to end of line
|
|
** LINEARG - Toggle case of range of lines
|
|
** BOXARG - Toggle case of characters with the selected box
|
|
** NUMARG - Converted to LINEARG before extension is called.
|
|
** MARKARG - Converted to Appropriate ARG form above before extension is
|
|
** called.
|
|
**
|
|
** STREAMARG - Not Allowed. Treated as BOXARG
|
|
** TEXTARG - Not Allowed
|
|
**
|
|
*/
|
|
flagType pascal EXTERNAL winpaste (
|
|
unsigned int argData, /* keystroke invoked with */
|
|
ARG *pArg, /* argument data */
|
|
flagType fMeta /* indicates preceded by meta */
|
|
)
|
|
{
|
|
PFILE pFile; /* file handle of current file */
|
|
COL xStart, xEnd;
|
|
LINE yStart, yEnd;
|
|
int argType;
|
|
UINT fmtData = CF_TEXT;
|
|
DWORD dwInsMode = STREAMARG;
|
|
HANDLE hText;
|
|
LPSTR pszText;
|
|
|
|
/*
|
|
* Get the clipboard text and insertion type
|
|
*/
|
|
if (pArg->argType == TEXTARG) {
|
|
int i, j;
|
|
char achLine[3 + 1 + 3 + 1 + 1 + BUFLEN + 1 + 1 + 5 + 1];
|
|
char *p;
|
|
|
|
/*
|
|
* Quick hack to make text arg pastes work like the do in MEP
|
|
*/
|
|
j = pArg->arg.textarg.cArg;
|
|
if (j > 2)
|
|
j = 2;
|
|
|
|
achLine[0] = '\0';
|
|
for( i = 0; i < j; i++ )
|
|
lstrcat(achLine, "arg ");
|
|
|
|
p = achLine + lstrlen(achLine);
|
|
wsprintf( p, "\"%s\" paste", pArg->arg.textarg.pText );
|
|
return fExecute( achLine );
|
|
}
|
|
|
|
/* if no text then return FALSE */
|
|
if (!IsClipboardFormatAvailable(fmtData)) {
|
|
|
|
/* No text, try display text */
|
|
fmtData = CF_DSPTEXT;
|
|
|
|
if (!IsClipboardFormatAvailable(fmtData)) {
|
|
/* bummer! no text at all, return FALSE */
|
|
DoMessage( " winclip: invalid clipboard format" );
|
|
return M_FALSE;
|
|
}
|
|
}
|
|
|
|
if (!OpenClipboard(ghwndClip))
|
|
return M_FALSE;
|
|
|
|
hText = GetClipboardData(fmtData);
|
|
if (hText == NULL || (pszText = GlobalLock(hText)) == NULL) {
|
|
CloseClipboard();
|
|
return M_FALSE;
|
|
}
|
|
|
|
|
|
/* Get insert mode */
|
|
|
|
if (IsClipboardFormatAvailable(gfmtArgType)) {
|
|
DWORD *pdw;
|
|
HANDLE hInsMode;
|
|
|
|
hInsMode = GetClipboardData(gfmtArgType);
|
|
|
|
if (hInsMode != NULL && (pdw = GlobalLock(hInsMode)) != NULL) {
|
|
dwInsMode = *pdw;
|
|
|
|
GlobalUnlock(hInsMode);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pFile = FileNameToHandle ("", "");
|
|
|
|
argType = pArg->argType;
|
|
|
|
switch( argType ) {
|
|
case BOXARG: /* case switch box */
|
|
/*
|
|
* Set [xy]Start inclusive of box arg,
|
|
* [xy]End exclusive of box arg.
|
|
*/
|
|
xStart = pArg->arg.boxarg.xLeft;
|
|
xEnd = pArg->arg.boxarg.xRight + 1;
|
|
yStart = pArg->arg.boxarg.yTop;
|
|
yEnd = pArg->arg.boxarg.yBottom + 1;
|
|
break;
|
|
|
|
case LINEARG: /* case switch line range */
|
|
/*
|
|
* Set [xy]Start inclusive of line arg,
|
|
* [xy]End exclusive of line arg.
|
|
*/
|
|
xStart = 0;
|
|
xEnd = BUFLEN + 1;
|
|
yStart = pArg->arg.linearg.yStart;
|
|
yEnd = pArg->arg.linearg.yEnd + 1;
|
|
break;
|
|
|
|
case STREAMARG:
|
|
/*
|
|
* Set [xy]Start inclusive of stream
|
|
* xEnd is EXCLUSIVE of stream
|
|
* yEnd is INCLUSIVE of stream
|
|
*/
|
|
xStart = pArg->arg.streamarg.xStart;
|
|
xEnd = pArg->arg.streamarg.xEnd;
|
|
yStart = pArg->arg.streamarg.yStart;
|
|
yEnd = pArg->arg.streamarg.yEnd;
|
|
break;
|
|
|
|
case NOARG:
|
|
xStart = pArg->arg.noarg.x;
|
|
xEnd = xStart + 1;
|
|
yStart = pArg->arg.noarg.y;
|
|
yEnd = yStart + 1;
|
|
break;
|
|
|
|
default:
|
|
GlobalUnlock(hText);
|
|
CloseClipboard();
|
|
return M_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Delete any selection
|
|
*/
|
|
DeleteArg( pFile, argType, xStart, yStart, xEnd, yEnd );
|
|
|
|
/*
|
|
* Insert new text with correct mode
|
|
*/
|
|
InsertText( pFile, pszText, dwInsMode, xStart, yStart );
|
|
|
|
GlobalUnlock(hText);
|
|
CloseClipboard();
|
|
|
|
return M_TRUE;
|
|
}
|
|
|
|
/*************************************************************************
|
|
**
|
|
** windel
|
|
**
|
|
**
|
|
*/
|
|
flagType pascal EXTERNAL windel (
|
|
unsigned int argData, /* keystroke invoked with */
|
|
ARG *pArg, /* argument data */
|
|
flagType fMeta /* indicates preceded by meta */
|
|
)
|
|
{
|
|
int argType = pArg->argType;
|
|
|
|
if (argType == NOARG)
|
|
return fExecute("delete");
|
|
|
|
if (argType == NULLARG) {
|
|
int c, x, y;
|
|
c = pArg->arg.nullarg.cArg;
|
|
x = pArg->arg.nullarg.x;
|
|
y = pArg->arg.nullarg.y;
|
|
|
|
pArg->argType = STREAMARG;
|
|
pArg->arg.streamarg.xStart = x;
|
|
pArg->arg.streamarg.xEnd = 0;
|
|
pArg->arg.streamarg.yStart = y;
|
|
pArg->arg.streamarg.yEnd = y + 1;
|
|
pArg->arg.streamarg.cArg = c;
|
|
}
|
|
|
|
return WinCutCopy (pArg, M_TRUE, fMeta);
|
|
}
|
|
|
|
/*************************************************************************
|
|
**
|
|
** WhenLoaded
|
|
** Executed when extension gets loaded. Identify self & assign default
|
|
** keystroke.
|
|
**
|
|
** Entry:
|
|
** none
|
|
*/
|
|
void EXTERNAL WhenLoaded () {
|
|
|
|
#if 0
|
|
WNDCLASS wc;
|
|
|
|
ghmod = GetModuleHandle(NULL);
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = DefWindowProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = ghmod;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = NULL;
|
|
wc.hbrBackground = NULL;
|
|
wc.lpszMenuName = NULL; /* Name of menu resource in .RC file. */
|
|
wc.lpszClassName = "WinClipWClass"; /* Name used in call to CreateWindow. */
|
|
|
|
if (RegisterClass(&wc) && (ghwndClip = CreateWindow( "WinClipWClass",
|
|
"ClipWindow", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL,
|
|
ghmod, NULL)) != NULL ) {
|
|
id(" Windows Clipboard Extentions for MEP,");
|
|
} else {
|
|
DoMessage( " winclip: Initialization failed!" );
|
|
}
|
|
#else
|
|
ghwndClip = NULL; //assign clipboard to this thread instead
|
|
#endif
|
|
|
|
gfmtArgType = RegisterClipboardFormat( "MEP Arg Type" );
|
|
|
|
#if 0
|
|
//SetKey ("wincut", "ctrl+x");
|
|
SetKey ("wincopy", "ctrl+c");
|
|
SetKey ("winpaste", "ctrl+v");
|
|
#endif
|
|
}
|
|
|
|
/*************************************************************************
|
|
**
|
|
** id
|
|
** identify ourselves, along with any passed informative message.
|
|
**
|
|
** Entry:
|
|
** pszMsg = Pointer to asciiz message, to which the extension name
|
|
** and version are appended prior to display.
|
|
*/
|
|
void pascal id (char *pszFcn) {
|
|
char buf[80] = {0};
|
|
|
|
strncat (buf,pszFcn, sizeof(buf)-1);
|
|
strncat (buf,EXT_ID, sizeof(buf)-1 - strlen(buf));
|
|
DoMessage (buf);
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
**
|
|
** Switch communication table to the editor.
|
|
** This extension defines no switches.
|
|
*/
|
|
struct swiDesc swiTable[] = {
|
|
{0, 0, 0}
|
|
};
|
|
|
|
/*************************************************************************
|
|
**
|
|
** Command communication table to the editor.
|
|
** Defines the name, location and acceptable argument types.
|
|
*/
|
|
struct cmdDesc cmdTable[] = {
|
|
{"wincopy", (funcCmd) wincopy, 0, KEEPMETA | NOARG | BOXARG | LINEARG | STREAMARG | MARKARG | NULLEOL | NUMARG },
|
|
{"wincut", (funcCmd) wincut, 0, NOARG | BOXARG | LINEARG | STREAMARG | MARKARG | NULLEOL | NUMARG | MODIFIES},
|
|
{"windel", (funcCmd) windel, 0, NOARG | BOXARG | LINEARG | STREAMARG | NULLARG | MODIFIES},
|
|
{"winpaste", (funcCmd) winpaste,0, KEEPMETA | NOARG | BOXARG | LINEARG | STREAMARG | TEXTARG | MODIFIES},
|
|
{0, 0, 0}
|
|
};
|
|
|
|
|
|
void DeleteArg( PFILE pFile, int argType, COL xStart, LINE yStart,
|
|
COL xEnd, COL yEnd ) {
|
|
|
|
switch( argType ) {
|
|
|
|
case STREAMARG:
|
|
DelStream(pFile, xStart, yStart, xEnd, yEnd);
|
|
break;
|
|
|
|
case LINEARG:
|
|
DelStream(pFile, 0, yStart, 0, yEnd);
|
|
break;
|
|
|
|
|
|
case BOXARG: {
|
|
LINE iLine;
|
|
|
|
for( iLine = yStart; iLine < yEnd; iLine++ ) {
|
|
DelStream( pFile, xStart, iLine, xEnd, iLine );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsertText( PFILE pFile, LPSTR pszText, DWORD dwInsMode, COL xStart,
|
|
LINE yStart ) {
|
|
char ch;
|
|
int cchLine, cchText, cchCopy;
|
|
LPSTR pszNL;
|
|
char achLine[BUFLEN];
|
|
char achEnd[BUFLEN];
|
|
|
|
switch( dwInsMode ) {
|
|
case STREAMARG:
|
|
/*
|
|
* Split current line,
|
|
* tack first line from buffer to end of new line
|
|
* put the new lines in file
|
|
* shove the last line to the beggining of the 2nd half of the line
|
|
*/
|
|
DPRINT( " Stream Paste" );
|
|
if ( *pszText == '\0' )
|
|
break;
|
|
|
|
|
|
pszNL = EndOfLine(pszText);
|
|
|
|
cchLine = GetLine( yStart, achLine, pFile );
|
|
|
|
if (cchLine < xStart)
|
|
cchLine = ExtendLine( achLine, cchLine, ' ', xStart );
|
|
|
|
cchText = (int)(pszNL - pszText);
|
|
if (xStart + cchText >= BUFLEN_MAX) {
|
|
cchText = BUFLEN_MAX - xStart;
|
|
pszNL = pszText + cchText;
|
|
}
|
|
|
|
strcpy( achEnd, &achLine[xStart] );
|
|
cchLine -= xStart;
|
|
|
|
CopyMemory( &achLine[xStart], pszText, cchText );
|
|
cchText += xStart;
|
|
achLine[cchText] = '\0';
|
|
|
|
|
|
while( *pszNL ) {
|
|
PutLine( yStart++, achLine, pFile );
|
|
CopyLine( NULL, pFile, 0, 0, yStart );
|
|
|
|
pszText = EndOfBreak(pszNL);
|
|
pszNL = EndOfLine(pszText);
|
|
|
|
cchText = (int)(pszNL - pszText);
|
|
|
|
CopyMemory( achLine, pszText, cchText );
|
|
achLine[cchText] = '\0';
|
|
}
|
|
|
|
cchCopy = 0;
|
|
if (cchLine + cchText > BUFLEN_MAX) {
|
|
cchCopy = (cchLine + cchText) - BUFLEN_MAX;
|
|
cchLine = cchLine - cchCopy;
|
|
}
|
|
|
|
CopyMemory( &achLine[cchText], achEnd, cchLine );
|
|
achLine[cchLine+cchText] = '\0';
|
|
PutLine( yStart++, achLine, pFile );
|
|
|
|
if (cchCopy != 0) {
|
|
CopyLine( NULL, pFile, 0, 0, yStart );
|
|
CopyMemory( achLine, &achEnd[cchLine], cchCopy );
|
|
achLine[cchCopy] = '\0';
|
|
PutLine( yStart++, achLine, pFile);
|
|
}
|
|
break;
|
|
|
|
case BOXARG:
|
|
/*
|
|
* Insert the text as a block into the middle of each line.
|
|
* This could be tricky since we need to pad all short lines
|
|
* out with spaces to match the lenght of the longest line
|
|
* in the text.
|
|
*/
|
|
|
|
DPRINT( " Box Paste" );
|
|
while( *pszText ) {
|
|
pszNL = EndOfLine(pszText);
|
|
|
|
cchLine = GetLine( yStart, achLine, pFile );
|
|
|
|
if (cchLine < xStart)
|
|
cchLine = ExtendLine( achLine, cchLine, ' ', xStart );
|
|
|
|
cchText = (int)(pszNL - pszText);
|
|
if (cchLine + cchText > BUFLEN_MAX)
|
|
cchText = BUFLEN_MAX - cchLine;
|
|
|
|
/* insert text in middle of line */
|
|
strcpy( achEnd, &achLine[xStart] );
|
|
CopyMemory( &achLine[xStart], pszText, cchText );
|
|
strcpy( &achLine[xStart + cchText], achEnd );
|
|
|
|
/* put line in file */
|
|
PutLine( yStart++, achLine, pFile );
|
|
|
|
pszText = EndOfBreak(pszNL);
|
|
}
|
|
break;
|
|
|
|
case LINEARG:
|
|
/*
|
|
* shove the lines in the buffer before the current line
|
|
*/
|
|
DPRINT( " Line Paste" );
|
|
while( *pszText ) {
|
|
pszNL = EndOfLine(pszText);
|
|
ch = *pszNL;
|
|
*pszNL = '\0';
|
|
CopyLine( NULL, pFile, 0, 0, yStart );
|
|
PutLine( yStart++, pszText, pFile);
|
|
*pszNL = ch;
|
|
pszText = EndOfBreak(pszNL);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
LPSTR EndOfLine( LPSTR psz ) {
|
|
int c;
|
|
|
|
c = 0;
|
|
while( *psz && *psz != '\r' && *psz != '\n' && c++ < BUFLEN_MAX )
|
|
psz++;
|
|
|
|
return psz;
|
|
}
|
|
|
|
LPSTR EndOfBreak( LPSTR psz ) {
|
|
char chSkip;
|
|
|
|
switch( *psz ) {
|
|
case '\r':
|
|
chSkip = '\n';
|
|
break;
|
|
|
|
case '\n':
|
|
chSkip = '\r';
|
|
break;
|
|
|
|
default:
|
|
return psz;
|
|
|
|
}
|
|
|
|
if (*(++psz) == chSkip)
|
|
psz++;
|
|
|
|
return psz;
|
|
}
|
|
|
|
|
|
int ExtendLine( LPSTR psz, int cchLine, char ch, int cchTotal ) {
|
|
|
|
if ( cchLine >= cchTotal )
|
|
return cchLine;
|
|
|
|
if (cchTotal > BUFLEN_MAX)
|
|
cchTotal = BUFLEN_MAX;
|
|
|
|
psz = &psz[cchLine];
|
|
|
|
while( cchLine++ < cchTotal )
|
|
*psz++ = ch;
|
|
|
|
*psz = '\0';
|
|
|
|
return cchLine;
|
|
}
|