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.

829 lines
23 KiB

  1. /*** winclip.c - windows clipboard editor extension
  2. *
  3. * Copyright <C> 1988, Microsoft Corporation
  4. *
  5. * Purpose:
  6. * Contains the tglcase function.
  7. *
  8. * Revision History:
  9. *
  10. * 28-Jun-1988 LN Created
  11. * 12-Sep-1988 mz Made WhenLoaded match declaration
  12. *
  13. *************************************************************************/
  14. #define EXT_ID " winclip ver 1.00 "##__DATE__
  15. #include <windows.h>
  16. #include <stdlib.h> /* min macro definition */
  17. #include <string.h> /* prototypes for string fcns */
  18. #undef pascal
  19. #include "../../inc/ext.h"
  20. #define M_FALSE ((flagType)0)
  21. #define M_TRUE ((flagType)(-1))
  22. #define BUFLEN_MAX (BUFLEN-1)
  23. /*
  24. ** Internal function prototypes
  25. */
  26. void pascal id (char *);
  27. void EXTERNAL WhenLoaded (void);
  28. flagType pascal EXTERNAL wincopy (unsigned int, ARG far *, flagType);
  29. flagType pascal EXTERNAL wincut (unsigned int, ARG far *, flagType);
  30. flagType pascal EXTERNAL winpaste (unsigned int, ARG far *, flagType);
  31. #ifdef DEBUG
  32. # define DPRINT(p) DoMessage(p)
  33. #else
  34. # define DPRINT(p)
  35. #endif
  36. HWND ghwndClip;
  37. HINSTANCE ghmod;
  38. int gfmtArgType;
  39. void DeleteArg( PFILE pFile, int argType, COL xStart, LINE yStart,
  40. COL xEnd, COL yEnd );
  41. void InsertText( PFILE pFile, LPSTR pszText, DWORD dwInsMode,
  42. COL xStart, LINE yStart );
  43. flagType pascal EXTERNAL WinCutCopy (ARG *pArg, flagType fCut, flagType fClip);
  44. LPSTR EndOfLine( LPSTR psz );
  45. LPSTR EndOfBreak( LPSTR psz );
  46. int ExtendLine( LPSTR psz, int cchSZ, char ch, int cchNew );
  47. /*************************************************************************
  48. **
  49. ** wincopy
  50. ** Toggle the case of alphabetics contaied within the selected argument:
  51. **
  52. ** NOARG - Toggle case of entire current line
  53. ** NULLARG - Toggle case of current line, from cursor to end of line
  54. ** LINEARG - Toggle case of range of lines
  55. ** BOXARG - Toggle case of characters with the selected box
  56. ** NUMARG - Converted to LINEARG before extension is called.
  57. ** MARKARG - Converted to Appropriate ARG form above before extension is
  58. ** called.
  59. **
  60. ** STREAMARG - Not Allowed. Treated as BOXARG
  61. ** TEXTARG - Not Allowed
  62. **
  63. */
  64. flagType pascal EXTERNAL wincopy (
  65. unsigned int argData, /* keystroke invoked with */
  66. ARG *pArg, /* argument data */
  67. flagType fMeta /* indicates preceded by meta */
  68. ) {
  69. return WinCutCopy( pArg, M_FALSE, M_FALSE );
  70. }
  71. flagType pascal EXTERNAL wincut (
  72. unsigned int argData, /* keystroke invoked with */
  73. ARG *pArg, /* argument data */
  74. flagType fMeta /* indicates preceded by meta */
  75. ) {
  76. return WinCutCopy( pArg, M_TRUE, fMeta );
  77. }
  78. flagType pascal EXTERNAL WinCutCopy (ARG *pArg, flagType fCut, flagType fNoClip)
  79. {
  80. PFILE pFile; /* file handle of current file */
  81. COL xStart, xEnd;
  82. LINE yStart, yEnd;
  83. char achLine[BUFLEN];
  84. HANDLE hText;
  85. LPSTR pszText;
  86. int iLine, cchLine;
  87. flagType fRet = M_TRUE;
  88. int argSave, argType;
  89. pFile = FileNameToHandle ("", "");
  90. argSave = argType = pArg->argType;
  91. switch( argType ) {
  92. case BOXARG: /* case switch box */
  93. xStart = pArg->arg.boxarg.xLeft;
  94. xEnd = pArg->arg.boxarg.xRight + 1;
  95. yStart = pArg->arg.boxarg.yTop;
  96. yEnd = pArg->arg.boxarg.yBottom + 1;
  97. /* At this point...
  98. * [xy]Start is Inclusive, [xy]End is EXCLUSIVE of the box arg
  99. */
  100. #ifdef DEBUG
  101. wsprintf( achLine, " BoxDims : %d %d %d %d ", (int)xStart, (int)yStart, (int)xEnd, (int)yEnd);
  102. DoMessage( achLine );
  103. #endif
  104. break;
  105. case NOARG:
  106. /* convert NOARG to a STREAMARG on whole current line */
  107. argType = STREAMARG;
  108. argSave = LINEARG;
  109. xStart = 0;
  110. yStart = pArg->arg.noarg.y;
  111. xEnd = 0;
  112. yEnd = yStart + 1;
  113. break;
  114. case TEXTARG:
  115. /*
  116. * Text args are only for real text. NumArgs and MarkArgs are
  117. * converted to stream or box args by the editor since we say
  118. * we accept NUMARG and MARKARG during initialization.
  119. */
  120. argType = STREAMARG;
  121. argSave = STREAMARG;
  122. xStart = pArg->arg.textarg.x;
  123. xEnd = lstrlen(pArg->arg.textarg.pText) + xStart;
  124. yStart = yEnd = pArg->arg.textarg.y;
  125. break;
  126. case LINEARG: /* case switch line range */
  127. /* convert LINEARG to a STREAMARG so we don't get lots of white space*/
  128. argType = STREAMARG;
  129. xStart = 0;
  130. xEnd = 0;
  131. yStart = pArg->arg.linearg.yStart;
  132. yEnd = pArg->arg.linearg.yEnd + 1;
  133. #ifdef DEBUG
  134. wsprintf( achLine, " LineDims : %d %d %d %d ", (int)xStart, (int)yStart, (int)xEnd, (int)yEnd);
  135. DoMessage( achLine );
  136. #endif
  137. /* At this point...
  138. * [xy]Start is Inclusive, [xy]End is EXCLUSIVE of the line arg
  139. */
  140. break;
  141. case STREAMARG:
  142. /*
  143. * Set Start == first char pos in stream, End == first char pos
  144. * AFTER stream.
  145. */
  146. xStart = pArg->arg.streamarg.xStart;
  147. xEnd = pArg->arg.streamarg.xEnd;
  148. yStart = pArg->arg.streamarg.yStart;
  149. yEnd = pArg->arg.streamarg.yEnd;
  150. #ifdef DEBUG
  151. wsprintf( achLine, " StreamDims : %d %d %d %d ", (int)xStart, (int)yStart, (int)xEnd, (int)yEnd);
  152. DoMessage( achLine );
  153. #endif
  154. break;
  155. default:
  156. #ifdef DEBUG
  157. wsprintf( achLine, " Unknown Arg: 0x%04x", argType );
  158. DoMessage( achLine );
  159. return M_TRUE;
  160. #endif
  161. return M_FALSE;
  162. }
  163. if (!fNoClip) {
  164. if (argType == STREAMARG) {
  165. int cch = 0;
  166. int iChar;
  167. for( iLine = yStart; iLine <= yEnd; iLine++ )
  168. cch += GetLine (iLine, achLine, pFile) + 3;
  169. hText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cch);
  170. if (hText == NULL) {
  171. DoMessage( " winclip: Out of Memory" );
  172. return M_FALSE;
  173. }
  174. pszText = GlobalLock(hText);
  175. iChar = xStart;
  176. for( iLine = yStart; iLine < yEnd; iLine++ ) {
  177. cchLine = GetLine (iLine, achLine, pFile);
  178. /* Incase we start after the end of the line */
  179. if (cchLine < iChar)
  180. cch = 0;
  181. else
  182. cch = cchLine - iChar;
  183. CopyMemory(pszText, &achLine[iChar], cch);
  184. pszText += cch;
  185. strcpy( pszText, "\r\n" );
  186. pszText += 2;
  187. iChar = 0;
  188. }
  189. /* Get partial last line */
  190. if (xEnd != 0) {
  191. cchLine = GetLine (iLine, achLine, pFile);
  192. /* if line is short, then pad it out */
  193. cchLine = ExtendLine( achLine, cchLine, ' ', xEnd );
  194. if (cchLine < iChar)
  195. cchLine = 0;
  196. else
  197. cchLine = xEnd - iChar;
  198. CopyMemory(pszText, &achLine[iChar], cchLine);
  199. pszText += cchLine;
  200. }
  201. } else {
  202. int cchBox = xEnd - xStart;
  203. hText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
  204. (yEnd - yStart) * (cchBox + 3));
  205. if (hText == NULL) {
  206. DoMessage( " winclip: Out of Memory" );
  207. return M_FALSE;
  208. }
  209. pszText = GlobalLock(hText);
  210. for( iLine = yStart; iLine < yEnd; iLine++ ) {
  211. cchLine = GetLine (iLine, achLine, pFile);
  212. if (argType == BOXARG)
  213. cchLine = ExtendLine( achLine, cchLine, ' ', xEnd );
  214. if (cchLine < xStart )
  215. cchLine = 0;
  216. else
  217. cchLine -= xStart;
  218. cchLine = min(cchLine, cchBox);
  219. CopyMemory(pszText, &achLine[xStart], cchLine);
  220. pszText += cchLine;
  221. strcpy( pszText, "\r\n" );
  222. pszText += 2;
  223. }
  224. }
  225. *pszText = '\0';
  226. GlobalUnlock(hText);
  227. if (OpenClipboard(ghwndClip)) {
  228. EmptyClipboard();
  229. /*
  230. * Set the text into the clipboard
  231. */
  232. if (SetClipboardData(CF_TEXT, hText) == hText) {
  233. /*
  234. * Remember the Arg type for pasting back
  235. */
  236. if (gfmtArgType != 0) {
  237. DWORD *pdw;
  238. HANDLE hArgType = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
  239. sizeof(DWORD));
  240. if (hArgType != NULL && (pdw = GlobalLock(hArgType)) != NULL) {
  241. *pdw = (DWORD)(argSave);
  242. GlobalUnlock(hArgType);
  243. SetClipboardData(gfmtArgType, hArgType);
  244. }
  245. }
  246. } else {
  247. /* An error occured writing text to clipboard */
  248. wsprintf(achLine, " winclip: Error (%ld) setting data",
  249. GetLastError());
  250. DoMessage( achLine );
  251. fRet = M_FALSE;
  252. }
  253. CloseClipboard();
  254. }
  255. }
  256. /*
  257. * No need to free the handle, USER32 will do it (yes it keeps
  258. * track of the client side handle) when we set the next clipboard
  259. * data. (Love that Win3.1 compatibility!)
  260. */
  261. if (fRet && fCut)
  262. DeleteArg( pFile, argType, xStart, yStart, xEnd, yEnd );
  263. return fRet;
  264. }
  265. /*************************************************************************
  266. **
  267. ** winpaste
  268. ** Toggle the case of alphabetics contaied within the selected argument:
  269. **
  270. ** NOARG - Toggle case of entire current line
  271. ** NULLARG - Toggle case of current line, from cursor to end of line
  272. ** LINEARG - Toggle case of range of lines
  273. ** BOXARG - Toggle case of characters with the selected box
  274. ** NUMARG - Converted to LINEARG before extension is called.
  275. ** MARKARG - Converted to Appropriate ARG form above before extension is
  276. ** called.
  277. **
  278. ** STREAMARG - Not Allowed. Treated as BOXARG
  279. ** TEXTARG - Not Allowed
  280. **
  281. */
  282. flagType pascal EXTERNAL winpaste (
  283. unsigned int argData, /* keystroke invoked with */
  284. ARG *pArg, /* argument data */
  285. flagType fMeta /* indicates preceded by meta */
  286. )
  287. {
  288. PFILE pFile; /* file handle of current file */
  289. COL xStart, xEnd;
  290. LINE yStart, yEnd;
  291. int argType;
  292. UINT fmtData = CF_TEXT;
  293. DWORD dwInsMode = STREAMARG;
  294. HANDLE hText;
  295. LPSTR pszText;
  296. /*
  297. * Get the clipboard text and insertion type
  298. */
  299. if (pArg->argType == TEXTARG) {
  300. int i, j;
  301. char achLine[3 + 1 + 3 + 1 + 1 + BUFLEN + 1 + 1 + 5 + 1];
  302. char *p;
  303. /*
  304. * Quick hack to make text arg pastes work like the do in MEP
  305. */
  306. j = pArg->arg.textarg.cArg;
  307. if (j > 2)
  308. j = 2;
  309. achLine[0] = '\0';
  310. for( i = 0; i < j; i++ )
  311. lstrcat(achLine, "arg ");
  312. p = achLine + lstrlen(achLine);
  313. wsprintf( p, "\"%s\" paste", pArg->arg.textarg.pText );
  314. return fExecute( achLine );
  315. }
  316. /* if no text then return FALSE */
  317. if (!IsClipboardFormatAvailable(fmtData)) {
  318. /* No text, try display text */
  319. fmtData = CF_DSPTEXT;
  320. if (!IsClipboardFormatAvailable(fmtData)) {
  321. /* bummer! no text at all, return FALSE */
  322. DoMessage( " winclip: invalid clipboard format" );
  323. return M_FALSE;
  324. }
  325. }
  326. if (!OpenClipboard(ghwndClip))
  327. return M_FALSE;
  328. hText = GetClipboardData(fmtData);
  329. if (hText == NULL || (pszText = GlobalLock(hText)) == NULL) {
  330. CloseClipboard();
  331. return M_FALSE;
  332. }
  333. /* Get insert mode */
  334. if (IsClipboardFormatAvailable(gfmtArgType)) {
  335. DWORD *pdw;
  336. HANDLE hInsMode;
  337. hInsMode = GetClipboardData(gfmtArgType);
  338. if (hInsMode != NULL && (pdw = GlobalLock(hInsMode)) != NULL) {
  339. dwInsMode = *pdw;
  340. GlobalUnlock(hInsMode);
  341. }
  342. }
  343. pFile = FileNameToHandle ("", "");
  344. argType = pArg->argType;
  345. switch( argType ) {
  346. case BOXARG: /* case switch box */
  347. /*
  348. * Set [xy]Start inclusive of box arg,
  349. * [xy]End exclusive of box arg.
  350. */
  351. xStart = pArg->arg.boxarg.xLeft;
  352. xEnd = pArg->arg.boxarg.xRight + 1;
  353. yStart = pArg->arg.boxarg.yTop;
  354. yEnd = pArg->arg.boxarg.yBottom + 1;
  355. break;
  356. case LINEARG: /* case switch line range */
  357. /*
  358. * Set [xy]Start inclusive of line arg,
  359. * [xy]End exclusive of line arg.
  360. */
  361. xStart = 0;
  362. xEnd = BUFLEN + 1;
  363. yStart = pArg->arg.linearg.yStart;
  364. yEnd = pArg->arg.linearg.yEnd + 1;
  365. break;
  366. case STREAMARG:
  367. /*
  368. * Set [xy]Start inclusive of stream
  369. * xEnd is EXCLUSIVE of stream
  370. * yEnd is INCLUSIVE of stream
  371. */
  372. xStart = pArg->arg.streamarg.xStart;
  373. xEnd = pArg->arg.streamarg.xEnd;
  374. yStart = pArg->arg.streamarg.yStart;
  375. yEnd = pArg->arg.streamarg.yEnd;
  376. break;
  377. case NOARG:
  378. xStart = pArg->arg.noarg.x;
  379. xEnd = xStart + 1;
  380. yStart = pArg->arg.noarg.y;
  381. yEnd = yStart + 1;
  382. break;
  383. default:
  384. GlobalUnlock(hText);
  385. CloseClipboard();
  386. return M_FALSE;
  387. }
  388. /*
  389. * Delete any selection
  390. */
  391. DeleteArg( pFile, argType, xStart, yStart, xEnd, yEnd );
  392. /*
  393. * Insert new text with correct mode
  394. */
  395. InsertText( pFile, pszText, dwInsMode, xStart, yStart );
  396. GlobalUnlock(hText);
  397. CloseClipboard();
  398. return M_TRUE;
  399. }
  400. /*************************************************************************
  401. **
  402. ** windel
  403. **
  404. **
  405. */
  406. flagType pascal EXTERNAL windel (
  407. unsigned int argData, /* keystroke invoked with */
  408. ARG *pArg, /* argument data */
  409. flagType fMeta /* indicates preceded by meta */
  410. )
  411. {
  412. int argType = pArg->argType;
  413. if (argType == NOARG)
  414. return fExecute("delete");
  415. if (argType == NULLARG) {
  416. int c, x, y;
  417. c = pArg->arg.nullarg.cArg;
  418. x = pArg->arg.nullarg.x;
  419. y = pArg->arg.nullarg.y;
  420. pArg->argType = STREAMARG;
  421. pArg->arg.streamarg.xStart = x;
  422. pArg->arg.streamarg.xEnd = 0;
  423. pArg->arg.streamarg.yStart = y;
  424. pArg->arg.streamarg.yEnd = y + 1;
  425. pArg->arg.streamarg.cArg = c;
  426. }
  427. return WinCutCopy (pArg, M_TRUE, fMeta);
  428. }
  429. /*************************************************************************
  430. **
  431. ** WhenLoaded
  432. ** Executed when extension gets loaded. Identify self & assign default
  433. ** keystroke.
  434. **
  435. ** Entry:
  436. ** none
  437. */
  438. void EXTERNAL WhenLoaded () {
  439. #if 0
  440. WNDCLASS wc;
  441. ghmod = GetModuleHandle(NULL);
  442. wc.style = 0;
  443. wc.lpfnWndProc = DefWindowProc;
  444. wc.cbClsExtra = 0;
  445. wc.cbWndExtra = 0;
  446. wc.hInstance = ghmod;
  447. wc.hIcon = NULL;
  448. wc.hCursor = NULL;
  449. wc.hbrBackground = NULL;
  450. wc.lpszMenuName = NULL; /* Name of menu resource in .RC file. */
  451. wc.lpszClassName = "WinClipWClass"; /* Name used in call to CreateWindow. */
  452. if (RegisterClass(&wc) && (ghwndClip = CreateWindow( "WinClipWClass",
  453. "ClipWindow", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL,
  454. ghmod, NULL)) != NULL ) {
  455. id(" Windows Clipboard Extentions for MEP,");
  456. } else {
  457. DoMessage( " winclip: Initialization failed!" );
  458. }
  459. #else
  460. ghwndClip = NULL; //assign clipboard to this thread instead
  461. #endif
  462. gfmtArgType = RegisterClipboardFormat( "MEP Arg Type" );
  463. #if 0
  464. //SetKey ("wincut", "ctrl+x");
  465. SetKey ("wincopy", "ctrl+c");
  466. SetKey ("winpaste", "ctrl+v");
  467. #endif
  468. }
  469. /*************************************************************************
  470. **
  471. ** id
  472. ** identify ourselves, along with any passed informative message.
  473. **
  474. ** Entry:
  475. ** pszMsg = Pointer to asciiz message, to which the extension name
  476. ** and version are appended prior to display.
  477. */
  478. void pascal id (char *pszFcn) {
  479. char buf[80] = {0};
  480. strncat (buf,pszFcn, sizeof(buf)-1);
  481. strncat (buf,EXT_ID, sizeof(buf)-1 - strlen(buf));
  482. DoMessage (buf);
  483. }
  484. /*************************************************************************
  485. **
  486. ** Switch communication table to the editor.
  487. ** This extension defines no switches.
  488. */
  489. struct swiDesc swiTable[] = {
  490. {0, 0, 0}
  491. };
  492. /*************************************************************************
  493. **
  494. ** Command communication table to the editor.
  495. ** Defines the name, location and acceptable argument types.
  496. */
  497. struct cmdDesc cmdTable[] = {
  498. {"wincopy", (funcCmd) wincopy, 0, KEEPMETA | NOARG | BOXARG | LINEARG | STREAMARG | MARKARG | NULLEOL | NUMARG },
  499. {"wincut", (funcCmd) wincut, 0, NOARG | BOXARG | LINEARG | STREAMARG | MARKARG | NULLEOL | NUMARG | MODIFIES},
  500. {"windel", (funcCmd) windel, 0, NOARG | BOXARG | LINEARG | STREAMARG | NULLARG | MODIFIES},
  501. {"winpaste", (funcCmd) winpaste,0, KEEPMETA | NOARG | BOXARG | LINEARG | STREAMARG | TEXTARG | MODIFIES},
  502. {0, 0, 0}
  503. };
  504. void DeleteArg( PFILE pFile, int argType, COL xStart, LINE yStart,
  505. COL xEnd, COL yEnd ) {
  506. switch( argType ) {
  507. case STREAMARG:
  508. DelStream(pFile, xStart, yStart, xEnd, yEnd);
  509. break;
  510. case LINEARG:
  511. DelStream(pFile, 0, yStart, 0, yEnd);
  512. break;
  513. case BOXARG: {
  514. LINE iLine;
  515. for( iLine = yStart; iLine < yEnd; iLine++ ) {
  516. DelStream( pFile, xStart, iLine, xEnd, iLine );
  517. }
  518. break;
  519. }
  520. default:
  521. break;
  522. }
  523. }
  524. void InsertText( PFILE pFile, LPSTR pszText, DWORD dwInsMode, COL xStart,
  525. LINE yStart ) {
  526. char ch;
  527. int cchLine, cchText, cchCopy;
  528. LPSTR pszNL;
  529. char achLine[BUFLEN];
  530. char achEnd[BUFLEN];
  531. switch( dwInsMode ) {
  532. case STREAMARG:
  533. /*
  534. * Split current line,
  535. * tack first line from buffer to end of new line
  536. * put the new lines in file
  537. * shove the last line to the beggining of the 2nd half of the line
  538. */
  539. DPRINT( " Stream Paste" );
  540. if ( *pszText == '\0' )
  541. break;
  542. pszNL = EndOfLine(pszText);
  543. cchLine = GetLine( yStart, achLine, pFile );
  544. if (cchLine < xStart)
  545. cchLine = ExtendLine( achLine, cchLine, ' ', xStart );
  546. cchText = (int)(pszNL - pszText);
  547. if (xStart + cchText >= BUFLEN_MAX) {
  548. cchText = BUFLEN_MAX - xStart;
  549. pszNL = pszText + cchText;
  550. }
  551. strcpy( achEnd, &achLine[xStart] );
  552. cchLine -= xStart;
  553. CopyMemory( &achLine[xStart], pszText, cchText );
  554. cchText += xStart;
  555. achLine[cchText] = '\0';
  556. while( *pszNL ) {
  557. PutLine( yStart++, achLine, pFile );
  558. CopyLine( NULL, pFile, 0, 0, yStart );
  559. pszText = EndOfBreak(pszNL);
  560. pszNL = EndOfLine(pszText);
  561. cchText = (int)(pszNL - pszText);
  562. CopyMemory( achLine, pszText, cchText );
  563. achLine[cchText] = '\0';
  564. }
  565. cchCopy = 0;
  566. if (cchLine + cchText > BUFLEN_MAX) {
  567. cchCopy = (cchLine + cchText) - BUFLEN_MAX;
  568. cchLine = cchLine - cchCopy;
  569. }
  570. CopyMemory( &achLine[cchText], achEnd, cchLine );
  571. achLine[cchLine+cchText] = '\0';
  572. PutLine( yStart++, achLine, pFile );
  573. if (cchCopy != 0) {
  574. CopyLine( NULL, pFile, 0, 0, yStart );
  575. CopyMemory( achLine, &achEnd[cchLine], cchCopy );
  576. achLine[cchCopy] = '\0';
  577. PutLine( yStart++, achLine, pFile);
  578. }
  579. break;
  580. case BOXARG:
  581. /*
  582. * Insert the text as a block into the middle of each line.
  583. * This could be tricky since we need to pad all short lines
  584. * out with spaces to match the lenght of the longest line
  585. * in the text.
  586. */
  587. DPRINT( " Box Paste" );
  588. while( *pszText ) {
  589. pszNL = EndOfLine(pszText);
  590. cchLine = GetLine( yStart, achLine, pFile );
  591. if (cchLine < xStart)
  592. cchLine = ExtendLine( achLine, cchLine, ' ', xStart );
  593. cchText = (int)(pszNL - pszText);
  594. if (cchLine + cchText > BUFLEN_MAX)
  595. cchText = BUFLEN_MAX - cchLine;
  596. /* insert text in middle of line */
  597. strcpy( achEnd, &achLine[xStart] );
  598. CopyMemory( &achLine[xStart], pszText, cchText );
  599. strcpy( &achLine[xStart + cchText], achEnd );
  600. /* put line in file */
  601. PutLine( yStart++, achLine, pFile );
  602. pszText = EndOfBreak(pszNL);
  603. }
  604. break;
  605. case LINEARG:
  606. /*
  607. * shove the lines in the buffer before the current line
  608. */
  609. DPRINT( " Line Paste" );
  610. while( *pszText ) {
  611. pszNL = EndOfLine(pszText);
  612. ch = *pszNL;
  613. *pszNL = '\0';
  614. CopyLine( NULL, pFile, 0, 0, yStart );
  615. PutLine( yStart++, pszText, pFile);
  616. *pszNL = ch;
  617. pszText = EndOfBreak(pszNL);
  618. }
  619. break;
  620. default:
  621. break;
  622. }
  623. }
  624. LPSTR EndOfLine( LPSTR psz ) {
  625. int c;
  626. c = 0;
  627. while( *psz && *psz != '\r' && *psz != '\n' && c++ < BUFLEN_MAX )
  628. psz++;
  629. return psz;
  630. }
  631. LPSTR EndOfBreak( LPSTR psz ) {
  632. char chSkip;
  633. switch( *psz ) {
  634. case '\r':
  635. chSkip = '\n';
  636. break;
  637. case '\n':
  638. chSkip = '\r';
  639. break;
  640. default:
  641. return psz;
  642. }
  643. if (*(++psz) == chSkip)
  644. psz++;
  645. return psz;
  646. }
  647. int ExtendLine( LPSTR psz, int cchLine, char ch, int cchTotal ) {
  648. if ( cchLine >= cchTotal )
  649. return cchLine;
  650. if (cchTotal > BUFLEN_MAX)
  651. cchTotal = BUFLEN_MAX;
  652. psz = &psz[cchLine];
  653. while( cchLine++ < cchTotal )
  654. *psz++ = ch;
  655. *psz = '\0';
  656. return cchLine;
  657. }