home *** CD-ROM | disk | FTP | other *** search
/ Languages Around the World / LanguageWorld.iso / language / japanese / win_prog / win_jwp / clpboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-31  |  27.6 KB  |  1,061 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5.  
  6. static BOOL ExternalDestroy = TRUE;
  7.  
  8. static FILEOPTIONS *clipboard = NULL;
  9. static PARAGRAPH far *curpara;
  10.  
  11. static int OriginalLineLength;
  12. static KANJI LastDataKanji;
  13. static int CBPos;
  14. static BOOL CurrentlyInKanji;
  15. static long int CurrentBlockSize;
  16. static BYTE far *DataPtr;
  17. static int DataPos;
  18.  
  19. static FILEPARAHEADER far *fpara = NULL;
  20. static BOOL FormatFirstLastLine = FALSE;
  21. static int NumberOfParagraphs = 0;
  22.  
  23.  
  24. /* Variables used for JWP --> Clipboard */
  25.  
  26. static HANDLE DataHandle;         /* Handle of DataPtr */
  27.  
  28.  
  29. /* Variables used for Clipboard --> JWP */
  30.  
  31. static KANJI far *InsBuffer;        /* Block to hold the insertion buffer */
  32. static int InsPos;
  33.  
  34.  
  35.  
  36. void BlockDelete (FILEOPTIONS *f, POSITION start, POSITION stop)
  37. {
  38.     int len;
  39.     POSITION p;
  40.  
  41.     if (PARAOF(start) == PARAOF(stop)) {
  42.         DeleteString (f, start, POS2ABS(stop) - POS2ABS(start) + 1,
  43.             OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MINIMAL);
  44.         return;
  45.     }
  46.  
  47.     p = start;
  48.  
  49.     /* First delete the last portions of the first paragraph */
  50.  
  51.     if (POSOF(p) > 0) {
  52.         len = unitlen(&UNITOF(p, POSOF(p)));
  53.         DeleteString (f, p, len, 0);
  54.  
  55.         CHAROF(p, POSOF(p)) = '\b';         /* Join the next paragraph */
  56.         CHAROF(p, POSOF(p) + 1) = 0;
  57.         f->nr_bytes++;
  58.  
  59.         PARAOF(p) = PARAOF(p)->next;
  60.         LINEOF(p) = PARAOF(p)->lines;
  61.         POSOF(p) = 0;
  62.     }
  63.  
  64.     /* Delete the middle paragraphs */
  65.  
  66.     for (; PARAOF(p) != PARAOF(stop); ) {
  67.         f->nr_bytes -= (unitlen(PARAOF(p)->text) - 1);
  68.         CHAROF(p, 0) = '\b';
  69.         CHAROF(p, 1) = 0;
  70.  
  71.         PARAOF(p) = PARAOF(p)->next;
  72.         LINEOF(p) = PARAOF(p)->lines;
  73.         POSOF(p) = 0;
  74.     }
  75.  
  76.     /* Finally we delete the first portion of the last paragraph */
  77.     /* and update the whole thing                                */
  78.  
  79.     len = POS2ABS(stop);
  80.  
  81.     if (len >= 0) {
  82.         if (CHAROF(stop,POSOF(stop))) len++;
  83.  
  84.         DeleteString (f, p, len, 0);
  85.     }
  86.  
  87.     /* Set the cursor position */
  88.  
  89.     f->current = p;
  90.  
  91.     ReformatParagraph (f, start, PARAOF(start)->next, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MINIMAL);
  92. }
  93.  
  94.  
  95. void BlockReplace (FILEOPTIONS *f, POSITION start, POSITION stop, KANJI far *buf)
  96. {
  97.     int len;
  98.     POSITION p;
  99.  
  100.     if (PARAOF(start) == PARAOF(stop)) {
  101.         ReplaceString (f, start, POS2ABS(stop) - POS2ABS(start) + 1, buf,
  102.             OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MINIMAL);
  103.         return;
  104.     }
  105.  
  106.     p = start;
  107.  
  108.     /* First replace the last portions of the first paragraph */
  109.  
  110.     len = unitlen(&UNITOF(p, POSOF(p)));
  111.     ReplaceString (f, p, len, buf, 0);
  112.     len = unitlen(PARAOF(p)->text);
  113.  
  114.     CHAROF(p, len) = '\b';         /* Join the next paragraph */
  115.     CHAROF(p, len + 1) = 0;
  116.     f->nr_bytes++;
  117.  
  118.     PARAOF(p) = PARAOF(p)->next;
  119.     LINEOF(p) = PARAOF(p)->lines;
  120.     POSOF(p) = 0;
  121.  
  122.     /* Delete the middle paragraphs */
  123.  
  124.     for (; PARAOF(p) != PARAOF(stop); ) {
  125.         f->nr_bytes -= (unitlen(PARAOF(p)->text) - 1);
  126.         CHAROF(p, 0) = '\b';
  127.         CHAROF(p, 1) = 0;
  128.  
  129.         PARAOF(p) = PARAOF(p)->next;
  130.         LINEOF(p) = PARAOF(p)->lines;
  131.         POSOF(p) = 0;
  132.     }
  133.  
  134.     /* Finally we delete the first portion of the last paragraph */
  135.     /* and update the whole thing                                */
  136.  
  137.     len = POS2ABS(stop);
  138.  
  139.     if (CHAROF(stop,POSOF(stop))) len++;
  140.  
  141.     DeleteString (f, p, len, 0);
  142.  
  143.     f->current = p;                /* Set the cursor position */
  144.  
  145.     ReformatParagraph (f, start, PARAOF(start)->next, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MINIMAL);
  146. }
  147.  
  148.  
  149.  
  150. static long int HowMuchData (void)
  151. {
  152.     int i;
  153.     long int len;
  154.     PARAGRAPH far *p;
  155.  
  156.     /* How much data? */
  157.  
  158.     for (p = clipboard->paragraph, len = 0L; p != NULL; p = p->next) {
  159.         for (i = 0; p->text[i].kanji; i++) len += (ISKANJI(p->text[i].kanji) ? 2 : 1);
  160.         len += 1L;   /* for \n */
  161.     }
  162.  
  163.     return (len);
  164. }
  165.  
  166.  
  167.  
  168. static HANDLE PrepareEUCData (void)
  169. {
  170.     int i;
  171.     long int len;
  172.     HANDLE handle;
  173.     PARAGRAPH far *p;
  174.     BYTE far *cp;
  175.  
  176.     if (clipboard == NULL) {
  177.         ErrorMessage(global.hwnd, "Funny! Clipboard is empty!");
  178.         return (NULL);
  179.     }
  180.  
  181.  
  182.     /* Allocate the data block */
  183.  
  184.     len = HowMuchData() + 5L;
  185.  
  186.     if (len > C64K) {
  187.         ErrorMessage(global.hwnd, "The clipboard cannot hold so much data!  The limit is 64K!");
  188.         return (NULL);
  189.     }
  190.  
  191.     handle = GlobalAlloc(GHND, len);
  192.     cp = (BYTE far *) GlobalLock(handle);
  193.  
  194.     /* Copy data */
  195.  
  196.     for (p = clipboard->paragraph; p != NULL; p = p->next) {
  197.         for (i = 0; p->text[i].kanji; i++, cp++) {
  198.             if (ISKANJI(p->text[i].kanji)) {
  199.                 *cp++ = HIBYTE(p->text[i].kanji) | 0x80;
  200.                 *cp = LOBYTE(p->text[i].kanji) | 0x80;
  201.             } else {
  202.                 *cp = LOBYTE(p->text[i].kanji) & 0x7f;
  203.             }
  204.         }
  205.         *cp++ = '\n';
  206.     }
  207.     *cp++ = '\0';
  208.  
  209.     GlobalUnlock(handle);
  210.     return (handle);
  211. }
  212.  
  213.  
  214.  
  215. static int ToClipboardCharIn (void)
  216. {
  217.     KANJI ch;
  218.  
  219.     if (curpara == NULL) return (EOF);
  220.  
  221.     ch = curpara->text[CBPos].kanji;
  222.  
  223.     if (CurrentlyInKanji) {
  224.         CurrentlyInKanji = FALSE;
  225.         CBPos++;
  226.         return (LOBYTE(ch) | 0x80);
  227.     }
  228.  
  229.     if (!ch) {
  230.         curpara = curpara->next;
  231.         CBPos = 0;
  232.         return ('\n');
  233.     } else if (ISKANJI(ch)) {
  234.         CurrentlyInKanji = TRUE;
  235.         return (HIBYTE(ch) | 0x80);
  236.     } else {
  237.         CBPos++;
  238.         return (LOBYTE(ch) & 0x7f);
  239.     }
  240. }
  241.  
  242.  
  243.  
  244. static void ToClipboardCharOut (int ch)
  245. {
  246.     if (DataPos + 5 >= CurrentBlockSize) {
  247.         /* Reallocate */
  248.         CurrentBlockSize += TEXTBLOCKSIZE;
  249.         if (CurrentBlockSize > C64K) {
  250.             ErrorMessage (global.hwnd, "The clipboard cannot hold so much data!  The limit is 64K!");
  251.             return;
  252.         }
  253.         GlobalUnlock(DataHandle);
  254.         GlobalReAlloc(DataHandle, CurrentBlockSize, GHND);
  255.         DataPtr = (BYTE far *) GlobalLock(DataHandle);
  256.     }
  257.  
  258.     DataPtr[DataPos++] = ch;
  259. }
  260.  
  261.  
  262.  
  263. static int FromClipboardCharIn (void)
  264. {
  265.     KANJI ch;
  266.  
  267.     ch = DataPtr[DataPos++];
  268.     if (!ch) return (EOF);
  269.  
  270.     return (ch);
  271. }
  272.  
  273.  
  274.  
  275. static void FromClipboardCharOut (int ch)
  276. {
  277.     KANJI ch1;
  278.  
  279.     if (ch == '\r') return;
  280.     if (ch == '\n') ch = '\r';
  281.  
  282.     if (CurrentlyInKanji) {
  283.         CurrentlyInKanji = FALSE;
  284.         ch1 = ((LastDataKanji << 8) | (ch & 0x7f));
  285.     } else if (ch & 0x80) {
  286.         CurrentlyInKanji = TRUE;
  287.         LastDataKanji = (ch & 0x7f);
  288.         return;
  289.     } else {
  290.         ch1 = ch;
  291.     }
  292.  
  293.     if (InsPos + 5 >= CurrentBlockSize) {
  294.         /* Reallocate */
  295.         CurrentBlockSize += TEXTBLOCKSIZE;
  296.         if (CurrentBlockSize > (C64K / sizeof(KANJI))) {
  297.             ErrorMessage (global.hwnd, "The clipboard contains too much data!  The limit is 64K!");
  298.             return;
  299.         }
  300.         InsBuffer = BlockRealloc(InsBuffer, CurrentBlockSize * sizeof(KANJI));
  301.     }
  302.  
  303.     InsBuffer[InsPos++] = ch1;
  304. }
  305.  
  306.  
  307.  
  308. static HANDLE PrepareOtherData (FILEFORMAT format)
  309. {
  310.     int i;
  311.     long int len;
  312.  
  313.     if (clipboard == NULL) {
  314.         ErrorMessage(global.hwnd, "Funny! Clipboard is empty!");
  315.         return (NULL);
  316.     }
  317.  
  318.     curpara = clipboard->paragraph;
  319.     CBPos = 0;
  320.  
  321.     len = HowMuchData() + 5L;
  322.  
  323.     if (len > C64K) {
  324.         ErrorMessage (global.hwnd, "The clipboard cannot hold so much data!  The limit is 64K!");
  325.         return (NULL);
  326.     }
  327.  
  328.     i = len / TEXTBLOCKSIZE;
  329.     len = (i + 1) * TEXTBLOCKSIZE;
  330.  
  331.     DataHandle = GlobalAlloc(GHND, len);
  332.     DataPtr = (BYTE far *) GlobalLock(DataHandle);
  333.  
  334.     CurrentBlockSize = len;
  335.     DataPos = 0L;
  336.  
  337.     CurrentlyInKanji = FALSE;
  338.  
  339.     SetupIO(ToClipboardCharIn, ToClipboardCharOut);
  340.     FileExport(format);
  341.  
  342.     GlobalUnlock(DataHandle);
  343.     return (DataHandle);
  344. }
  345.  
  346.  
  347.  
  348. static HANDLE PrepareBitmap (void)
  349. {
  350.     long int height, width, max;
  351.     HBITMAP hbitmap;
  352.     HDC hdc, hdcmem;
  353.     HBRUSH hbrush;
  354.     RECT rect;
  355.     PARAGRAPH far *p;
  356.     ONELINE far *lp;
  357.     BOOL OldDraftView;
  358.  
  359.  
  360.     /* First, reformat it to the original layout */
  361.  
  362.     clipboard->width = OriginalLineLength;
  363.     clipboard->height = 0;
  364.  
  365.     clipboard->linelen = clipboard->width / BASEWIDTH(clipboard);
  366.     if (clipboard->linelen <= 0) clipboard->linelen = 1;
  367.  
  368.     OldDraftView = global.draftview;
  369.     global.draftview = FALSE;
  370.  
  371.     ReformatFile(clipboard);
  372.  
  373.  
  374.     /* How big must the bitmap be? */
  375.  
  376.     width = 0;
  377.     height = 0;
  378.  
  379.     for (p = clipboard->paragraph; p != NULL; p = p->next) {
  380.         for (lp = p->lines; lp != NULL; lp = lp->next) {
  381.             if (lp->length > 0 && ISKANJI(p->text[lp->position + lp->length - 1].kanji)) {
  382.                 if (lp->width - clipboard->leading > width) width = lp->width - clipboard->leading;
  383.             } else {
  384.                 if (lp->width > width) width = lp->width;
  385.             }
  386.             height += lp->height + clipboard->spacing;
  387.         }
  388.     }
  389.  
  390.  
  391.     max = (C64K / width) * 8;
  392.  
  393.     height -= clipboard->spacing;
  394.  
  395.     if (height > max) height = max;
  396.  
  397.  
  398.     /* Create the bitmap */
  399.  
  400.     hdc = GetDC(global.hwnd);
  401.     hdcmem = CreateCompatibleDC(hdc);
  402.     SetTextColor(hdcmem, GetSysColor(COLOR_WINDOWTEXT));
  403.     SetBkColor(hdcmem, GetSysColor(COLOR_WINDOW));
  404.     hbitmap = CreateCompatibleBitmap (hdc, width, height);
  405.     SelectObject(hdcmem, hbitmap);
  406.  
  407.     rect.left = 0;
  408.     rect.right = width;
  409.     rect.top = 0;
  410.     rect.bottom = height;
  411.  
  412.     hbrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  413.     FillRect(hdcmem, &rect, hbrush);
  414.     DeleteObject(hbrush);
  415.  
  416.     RedrawFile(clipboard, hdcmem, 0, clipboard->spacing - LINEGAP(clipboard), &rect, FALSE);
  417.  
  418.     DeleteDC(hdcmem);
  419.     ReleaseDC(global.hwnd, hdc);
  420.  
  421.     global.draftview = OldDraftView;
  422.  
  423.     return (hbitmap);
  424. }
  425.  
  426.  
  427.  
  428. static HANDLE PrepareInternalData (void)
  429. {
  430.     int i;
  431.     long int len;
  432.     FILEPARAHEADER fh;
  433.     PARAGRAPH far *p;
  434.  
  435.     DataHandle = GlobalAlloc(GHND, C64K);
  436.     DataPtr = (BYTE far *) GlobalLock(DataHandle);
  437.  
  438.     /* How many paragraphs? */
  439.  
  440.     for (i = 0, p = clipboard->paragraph; p != NULL; i++, p = p->next);
  441.  
  442.     _fmemcpy(DataPtr, &i, sizeof(int));
  443.     DataPtr += sizeof(int);
  444.  
  445.     for (p = clipboard->paragraph; p != NULL; p = p->next) {
  446.         fh.textsize = unitlen(p->text);
  447.         fh.spacemulti = p->spacemulti;
  448.         fh.firstindent = p->firstindent;
  449.         fh.leftindent = p->leftindent;
  450.         fh.rightindent = p->rightindent;
  451.  
  452.         _fmemcpy(DataPtr, &fh, sizeof(FILEPARAHEADER));
  453.         DataPtr += sizeof(FILEPARAHEADER);
  454.  
  455.         len = ((long int) fh.textsize + 1L) * sizeof(UNIT);
  456.         _fmemcpy(DataPtr, p->text, len);
  457.         DataPtr += len;
  458.     }
  459.  
  460.     GlobalUnlock(DataHandle);
  461.     return (DataHandle);
  462. }
  463.  
  464.  
  465.  
  466. static HANDLE GetCBData (int type)
  467. {
  468.     switch (type) {
  469.         case CF_TEXT:
  470.         case CF_OEMTEXT:
  471.             switch (global.clipboard) {
  472.                 case FF_EUC:     return (PrepareEUCData());
  473.  
  474.                 case FF_UNKNOWN: ErrorMessage(global.hwnd, "Bad clipboard format: Unknown");
  475.                                  return (NULL);
  476.  
  477.                 case FF_NORMAL:  ErrorMessage(global.hwnd, "Bad clipboard format: Normal");
  478.                                  return (NULL);
  479.  
  480.                 default:         return (PrepareOtherData(global.clipboard));
  481.             }
  482.             break;
  483.  
  484.         case CF_BITMAP:
  485.             return (PrepareBitmap());
  486.  
  487.         case CF_OWNERDISPLAY:
  488.             return (PrepareInternalData());
  489.     }
  490.  
  491.     ErrorMessage(global.hwnd, "Bad clipboard format type received: %d", type);
  492.     return (NULL);
  493. }
  494.  
  495.  
  496.  
  497. static BOOL ReformatProc (FILEOPTIONS *f, PARAGRAPH far *p, int n)
  498. {
  499.     if (fpara == NULL) return (FALSE);
  500.  
  501.     if (!FormatFirstLastLine) {
  502.         if (n <= 0) return (FALSE);
  503.         if (n >= NumberOfParagraphs - 1) return (FALSE);
  504.     }
  505.  
  506.     p->spacemulti = fpara[n].spacemulti;
  507.     p->spacing = (f->basefont->height + f->basefont->spacing) * p->spacemulti / 100;
  508.     p->spacing -= f->basefont->height;
  509.     p->firstindent = fpara[n].firstindent;
  510.     p->leftindent = fpara[n].leftindent;
  511.     p->rightindent = fpara[n].rightindent;
  512.  
  513.     return (TRUE);
  514. }
  515.  
  516.  
  517.  
  518. static void ImportInternalCBData (void)
  519. {
  520.     int i, j, n;
  521.     long int len;
  522.     BYTE far *cp;
  523.     HANDLE handle;
  524.     UNIT far *up;
  525.  
  526.     OpenClipboard(global.hwnd);
  527.     handle = GetClipboardData(CF_OWNERDISPLAY);
  528.     cp = DataPtr = (BYTE far *) GlobalLock(handle);
  529.  
  530.     _fmemcpy(&n, DataPtr, sizeof(int));
  531.     DataPtr += sizeof(int);
  532.  
  533.     if (fpara != NULL) FreeBlock(fpara);
  534.     fpara = (FILEPARAHEADER far *) BlockAlloc(n * sizeof(FILEPARAHEADER));
  535.     NumberOfParagraphs = n;
  536.  
  537.     for (i = 0, len = 0L; i < n; i++) {
  538.         _fmemcpy(fpara + i, DataPtr, sizeof(FILEPARAHEADER));
  539.         len += fpara[i].textsize + 1;
  540.         DataPtr += sizeof(FILEPARAHEADER);
  541.         DataPtr += (fpara[i].textsize + 1) * sizeof(UNIT);
  542.     }
  543.  
  544.     /* Now get the text */
  545.  
  546.     InsBuffer = (KANJI far *) BlockAlloc((len + 5) * sizeof(KANJI));
  547.     InsPos = 0;
  548.  
  549.     DataPtr = cp;               /* Rewind to beginning */
  550.     DataPtr += sizeof(int);     /* Skip number of paragraphs */
  551.  
  552.     for (i = 0; i < n; i++) {
  553.         DataPtr += sizeof(FILEPARAHEADER);
  554.         up = (UNIT far *) DataPtr;
  555.         for (j = 0; j < fpara[i].textsize; j++) InsBuffer[InsPos + j] = up[j].kanji;
  556.         DataPtr += (fpara[i].textsize + 1) * sizeof(UNIT);
  557.         InsBuffer[InsPos + j] = '\r';
  558.         InsPos += j + 1;
  559.     }
  560.  
  561.     if (InsPos > 0) InsBuffer[InsPos-1] = 0;
  562.  
  563.     GlobalUnlock(handle);
  564.     CloseClipboard();
  565. }
  566.  
  567.  
  568.  
  569. static KANJI far *ImportOtherCBData (FILEFORMAT format)
  570. {
  571.     HANDLE handle;
  572.  
  573.     if (!IsClipboardFormatAvailable(CF_TEXT) && !IsClipboardFormatAvailable(CF_OEMTEXT))
  574.         return (NULL);
  575.  
  576.     OpenClipboard(global.hwnd);
  577.     if (IsClipboardFormatAvailable(CF_TEXT)) {
  578.         handle = GetClipboardData(CF_TEXT);
  579.     } else if (IsClipboardFormatAvailable(CF_OEMTEXT)) {
  580.         handle = GetClipboardData(CF_OEMTEXT);
  581.     }
  582.  
  583.     DataPtr = (BYTE far *) GlobalLock(handle);
  584.     DataPos = 0;
  585.     CurrentBlockSize = TEXTBLOCKSIZE;
  586.  
  587.     InsBuffer = (KANJI far *) BlockAlloc(CurrentBlockSize * sizeof(KANJI));
  588.     InsPos = 0;
  589.  
  590.     CurrentlyInKanji = FALSE;
  591.  
  592.     SetupIO(FromClipboardCharIn, FromClipboardCharOut);
  593.     FileImport(format);
  594.  
  595.     GlobalUnlock(handle);
  596.     CloseClipboard();
  597.  
  598.     return (InsBuffer);
  599. }
  600.  
  601.  
  602.  
  603. static void ClearCBData (void)
  604. {
  605.     if (clipboard == NULL) return;
  606.  
  607.     CloseFile(clipboard);
  608.  
  609.     FreeMem(clipboard);
  610.  
  611.     clipboard = NULL;
  612. }
  613.  
  614.  
  615.  
  616. void CopyToClipboard (FILEOPTIONS *f)
  617. {
  618.     PARAGRAPH far *p, far *cp;
  619.  
  620.     OpenClipboard(global.hwnd);
  621.     EmptyClipboard();
  622.     ClearCBData();
  623.  
  624.     if (SELPARA1(f) != NULL) {
  625.         SetClipboardData(CF_OWNERDISPLAY, NULL);
  626.         SetClipboardData(CF_TEXT, NULL);
  627.         SetClipboardData(CF_OEMTEXT, NULL);
  628.         SetClipboardData(CF_BITMAP, NULL);
  629.     } else {
  630.         CloseClipboard();
  631.         return;
  632.     }
  633.  
  634.  
  635.     /* Allocate data */
  636.  
  637.     clipboard = (FILEOPTIONS *) MemAlloc(sizeof(FILEOPTIONS));
  638.  
  639.     clipboard->type = FN_CLIPBOARD | FN_NORMAL;
  640.     clipboard->relaxmargin = global.relaxmargin;
  641.     clipboard->nr_lines = 0;
  642.  
  643.     clipboard->basefont = f->basefont;
  644.     clipboard->leading = f->leading;
  645.     clipboard->spacing = f->spacing;
  646.     clipboard->linelen = f->linelen;
  647.  
  648.     OriginalLineLength = f->linelen * BASEWIDTH(f);
  649.  
  650.  
  651.     if (SELPARA1(f) == SELPARA2(f)) {
  652.         cp = clipboard->paragraph = clipboard->eof = StructAlloc(PARAGRAPH);
  653.         _fmemcpy(cp, SELPARA1(f), sizeof(PARAGRAPH));
  654.  
  655.         cp->lines = cp->lastline = StructAlloc(ONELINE);
  656.         cp->lines->next = cp->lines->prev = NULL;
  657.         cp->next = cp->prev = NULL;
  658.         clipboard->nr_lines = 1;
  659.  
  660.         cp->lines->length = SELPOS2(f) - SELPOS1(f) + 1;
  661.         cp->textsize = (cp->lines->length + 2) * sizeof(UNIT);
  662.         cp->text = BlockAlloc(cp->textsize);
  663.  
  664.         _fmemcpy(cp->text, SELPARA1(f)->text + SELPOS1(f),
  665.                  (SELPOS2(f) - SELPOS1(f) + 1) * sizeof(UNIT));
  666.         cp->text[SELPOS2(f) - SELPOS1(f) + 1].kanji = 0;
  667.  
  668.         TOPPARA(clipboard) = clipboard->paragraph;
  669.         TOPLINE(clipboard) = clipboard->paragraph->lines;
  670.  
  671.         clipboard->current = clipboard->top;
  672.         POSOF(clipboard->current) = 0;
  673.  
  674.         clipboard->vscroll = 0;
  675.         CloseClipboard();
  676.         return;
  677.     }
  678.  
  679.     for (p = SELPARA1(f); ; p = p->next) {
  680.         if (clipboard->paragraph == NULL) {
  681.             clipboard->paragraph = cp = StructAlloc(PARAGRAPH);
  682.             _fmemcpy(cp, p, sizeof(PARAGRAPH));
  683.             cp->prev = NULL;
  684.         } else {
  685.             cp->next = StructAlloc(PARAGRAPH);
  686.             _fmemcpy(cp->next, p, sizeof(PARAGRAPH));
  687.             cp->next->prev = cp;
  688.             cp = cp->next;
  689.         }
  690.  
  691.         cp->lines = cp->lastline = StructAlloc(ONELINE);
  692.         cp->lines->next = cp->lines->prev = NULL;
  693.         clipboard->nr_lines++;
  694.  
  695.  
  696.         if (p == SELPARA1(f)) {
  697.             cp->lines->length = unitlen(p->text) - SELPOS1(f);
  698.             cp->textsize = (cp->lines->length + 1) * sizeof(UNIT);
  699.             cp->text = BlockAlloc(cp->textsize);
  700.             _fmemcpy(cp->text, p->text + SELPOS1(f), cp->textsize);
  701.         } else if (p == SELPARA2(f)) {
  702.             cp->lines->length = SELPOS2(f);
  703.             cp->textsize = (cp->lines->length + 2) * sizeof(UNIT);
  704.             cp->text = BlockAlloc(cp->textsize);
  705.             _fmemcpy(cp->text, p->text, cp->textsize);
  706.             cp->text[SELPOS2(f) + 1].kanji = 0;
  707.             break;
  708.         } else {
  709.             cp->lines->length = unitlen(p->text);
  710.             cp->textsize = (cp->lines->length + 1) * sizeof(UNIT);
  711.             cp->text = BlockAlloc(cp->textsize);
  712.             _fmemcpy(cp->text, p->text, cp->textsize);
  713.         }
  714.     }
  715.  
  716.     cp->next = NULL;
  717.     clipboard->eof = cp;
  718.  
  719.     TOPPARA(clipboard) = clipboard->paragraph;
  720.     TOPLINE(clipboard) = clipboard->paragraph->lines;
  721.  
  722.     clipboard->current = clipboard->top;
  723.     POSOF(clipboard->current) = 0;
  724.  
  725.     clipboard->vscroll = 0;
  726.  
  727.     CloseClipboard();
  728. }
  729.  
  730.  
  731.  
  732. BOOL ClipboardFull (void)
  733. {
  734.     HWND hwnd;
  735.     char buffer[MAXLINELEN];
  736.  
  737.     if (IsClipboardFormatAvailable(CF_OWNERDISPLAY)) {
  738.         hwnd = GetClipboardOwner();
  739.         if (hwnd == NULL) goto Next;
  740.  
  741.         GetClassName(hwnd, buffer, MAXLINELEN);
  742.         if (strcmp(buffer, "JWP Frame")) goto Next;
  743.  
  744.         return (TRUE);
  745.     }
  746.  
  747. Next:
  748.  
  749.     if (IsClipboardFormatAvailable(CF_TEXT)) return (TRUE);
  750.     if (IsClipboardFormatAvailable(CF_OEMTEXT)) return (TRUE);
  751.  
  752.     return (FALSE);
  753. }
  754.  
  755.  
  756.  
  757. void InsertFromClipboard (FILEOPTIONS *f)
  758. {
  759.     int i;
  760.     HWND hwnd;
  761.     BOOL Internal;
  762.     char buffer[MAXLINELEN];
  763.  
  764.     Internal = IsClipboardFormatAvailable(CF_OWNERDISPLAY);
  765.  
  766.     if (Internal) {
  767.         hwnd = GetClipboardOwner();
  768.         if (hwnd == NULL) return;
  769.         GetClassName(hwnd, buffer, MAXLINELEN);
  770.         if (strcmp(buffer, "JWP Frame")) return;
  771.  
  772.         ImportInternalCBData();
  773.     } else {
  774.         if (ImportOtherCBData(global.clipboard) == NULL) return;
  775.  
  776.         if (InsPos > 0) if (InsBuffer[InsPos - 1] == '\r') InsPos--;
  777.  
  778.         InsBuffer[InsPos] = 0;
  779.     }
  780.  
  781.  
  782.     /* If it is to an edit control, no line-breaks */
  783.  
  784.     if (!(f->type & FN_NORMAL)) {
  785.         for (i = 0; InsBuffer[i]; i++) {
  786.             if (InsBuffer[i] == '\n' || InsBuffer[i] == '\r' || InsBuffer[i] == '\t') {
  787.                 if (i > 0) {
  788.                     if (ISKANJI(InsBuffer[i-1])) InsBuffer[i] = 0x2121;
  789.                     else InsBuffer[i] = ' ';
  790.                 } else if (InsBuffer[i+1]) {
  791.                     if (ISKANJI(InsBuffer[i+1])) InsBuffer[i] = 0x2121;
  792.                     else InsBuffer[i] = ' ';
  793.                 } else {
  794.                     InsBuffer[i] = 0x2121;
  795.                 }
  796.             }
  797.         }
  798.     }
  799.  
  800.  
  801.     /* Block Replace? */
  802.  
  803.     if (Internal) SetReformatProc(ReformatProc);
  804.  
  805.     if (SELPARA1(f) != NULL && SELTYPE(f) == SEL_SELECTION) {
  806.         POSITION abs, start, stop;
  807.  
  808.         PARAOF(abs) = SELPARA1(f);
  809.         POSOF(abs) = SELPOS1(f);
  810.  
  811.         AbsoluteToPosition(abs, &start);
  812.  
  813.         PARAOF(abs) = SELPARA2(f);
  814.         POSOF(abs) = SELPOS2(f);
  815.  
  816.         AbsoluteToPosition(abs, &stop);
  817.  
  818.         /* Get rid of the selection */
  819.  
  820.         SELPARA1(f) = SELPARA2(f) = NULL;   SELPOS1(f) = SELPOS2(f) = 0;
  821.         SELNOW(f) = FALSE;                  SELTYPE(f) = SEL_SELECTION;
  822.  
  823.         f->current = start;
  824.  
  825.         if (!FindCaret(f, FALSE)) {
  826.             MoveIntoWindow(f);
  827.             InvalidateRect(f->hwnd, NULL, TRUE);
  828.             UpdateWindow(f->hwnd);
  829.         }
  830.  
  831.         /* Move the cursor to the end */
  832.  
  833.         f->current = stop;
  834.         if (CURCHAR(f) >= CURLINE(f)->length) {
  835.             NEXTLINE(f->current);
  836.         } else {
  837.             CURCHAR(f)++;
  838.         }
  839.  
  840.         FormatFirstLastLine = FALSE;
  841.         UndoAddReplace(f, start, f->current);
  842.         if (SELPARA1(f) == SELPARA2(f)) {
  843.             BlockReplace (f, start, stop, InsBuffer);
  844.         } else {
  845.             BlockDelete(f, start, stop);
  846.             InsertString(f, start, InsBuffer, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  847.         }
  848.         UndoFixReplace(f, f->current);
  849.     } else {
  850.         POSITION p;
  851.  
  852.         FormatFirstLastLine = (CURCHAR(f) <= 0);
  853.         p = f->current;
  854.         InsertString (f, f->current, InsBuffer, OP_REFORMAT | OP_UPDATE | OP_MOVESEL | OP_MOVETOEND | OP_MINIMAL);
  855.         UndoAddInsert(f, p, f->current);
  856.     }
  857.  
  858.     if (Internal) SetReformatProc(NULL);
  859.  
  860.     FreeBlock(InsBuffer);
  861. }
  862.  
  863.  
  864.  
  865. void ResetClipboard (void)
  866. {
  867.     if (clipboard == NULL) return;
  868.  
  869.     OpenClipboard(global.hwnd);
  870.     ExternalDestroy = FALSE;
  871.     EmptyClipboard();
  872.     ExternalDestroy = TRUE;
  873.     SetClipboardData(CF_OWNERDISPLAY, NULL);
  874.     SetClipboardData(CF_TEXT, NULL);
  875.     SetClipboardData(CF_OEMTEXT, NULL);
  876.     SetClipboardData(CF_BITMAP, NULL);
  877.     CloseClipboard();
  878. }
  879.  
  880.  
  881.  
  882. LONG ProcessClipboardMessage (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  883. {
  884.     int i, j;
  885.     char buffer[100];
  886.     char far *cp;
  887.     BOOL OldDraftView;
  888.     RECT rect, far *rp;
  889.     PAINTSTRUCT far *ps;
  890.     HANDLE handle;
  891.     POSITION p;
  892.  
  893.  
  894.     switch (message) {
  895.         case WM_RENDERFORMAT:
  896.             SetClipboardData(wParam, GetCBData(wParam));
  897.             return (0);
  898.  
  899.         case WM_DESTROYCLIPBOARD:
  900.             if (ExternalDestroy) ClearCBData();
  901.             return (0);
  902.  
  903.         case WM_RENDERALLFORMATS:
  904.             OpenClipboard(hwnd);
  905.             ExternalDestroy = FALSE;
  906.             EmptyClipboard();
  907.             ExternalDestroy = TRUE;
  908.             SetClipboardData(CF_TEXT, GetCBData(CF_TEXT));
  909.             SetClipboardData(CF_OEMTEXT, GetCBData(CF_OEMTEXT));
  910.             SetClipboardData(CF_BITMAP, GetCBData(CF_BITMAP));
  911.             CloseClipboard();
  912.             return (0);
  913.  
  914.         case WM_ASKCBFORMATNAME:
  915.             sprintf(buffer, "%s Formatted Text", PROGNAME);
  916.             cp = (char far *) lParam;
  917.  
  918.             _fmemcpy(cp, buffer, wParam);
  919.             cp[wParam - 1] = '\0';
  920.             return (0);
  921.  
  922.         case WM_PAINTCLIPBOARD:
  923.             handle = (HANDLE) LOWORD(lParam);
  924.             ps = (PAINTSTRUCT far *) GlobalLock(handle);
  925.             rp = &(ps->rcPaint);
  926.  
  927.             /* Translate the coordinates */
  928.             rp->left -= BORDERSPACE;
  929.             rp->top -= BORDERSPACE;
  930.             rp->right -= BORDERSPACE;
  931.             rp->bottom -= BORDERSPACE;
  932.  
  933.             OldDraftView = global.draftview;
  934.             global.draftview = FALSE;
  935.             RedrawFile(clipboard, ps->hdc, -BORDERSPACE, -BORDERSPACE, rp, FALSE);
  936.             global.draftview = OldDraftView;
  937.  
  938.             GlobalUnlock(handle);
  939.             return (0);
  940.  
  941.         case WM_SIZECLIPBOARD:
  942.             handle = (HANDLE) LOWORD(lParam);
  943.             rp = (RECT far *) GlobalLock(handle);
  944.             rect = *rp;
  945.             GlobalUnlock(handle);
  946.  
  947.             if (rect.right <= 0 || rect.bottom <= 0) return (0);
  948.  
  949.             GetScrollRange((HWND) wParam, SB_VERT, &i, &j);
  950.  
  951.             if (j - i > 0) {
  952.                 clipboard->width = rect.right - BORDERSPACE;
  953.                 clipboard->height = rect.bottom - BORDERSPACE;
  954.  
  955.                 clipboard->linelen = clipboard->width / BASEWIDTH(clipboard);
  956.                 if (clipboard->linelen <= 0) clipboard->linelen = 1;
  957.  
  958.                 OldDraftView = global.draftview;
  959.                 global.draftview = FALSE;
  960.                 ReformatFile(clipboard);
  961.                 global.draftview = OldDraftView;
  962.  
  963.                 if (clipboard->nr_lines > 1) {
  964.                     SetScrollRange((HWND) wParam, SB_VERT, 0, clipboard->nr_lines - 1, FALSE);
  965.                 } else {
  966.                     SetScrollRange((HWND) wParam, SB_VERT, 0, 1, FALSE);
  967.                 }
  968.                 SetScrollPos((HWND) wParam, SB_VERT, clipboard->vscroll, TRUE);
  969.             } else {
  970.                 /* No scroll bar: turn it on */
  971.                 /* Windows will send WM_SIZECLIPBOARD again */
  972.  
  973.                 SetScrollRange((HWND) wParam, SB_VERT, 0, 1, FALSE);
  974.                 SetScrollPos((HWND) wParam, SB_VERT, 0, TRUE);
  975.             }
  976.             return (0);
  977.  
  978.         case WM_VSCROLLCLIPBOARD:
  979.             rect.left = 0;
  980.             rect.top = BORDERSPACE;
  981.             rect.right = clipboard->width + BORDERSPACE;
  982.             rect.bottom = clipboard->height + BORDERSPACE;
  983.  
  984.             switch (LOWORD(lParam)) {
  985.                 case SB_TOP:
  986.                     TOPPARA(clipboard) = clipboard->paragraph;
  987.                     TOPLINE(clipboard) = clipboard->paragraph->lines;
  988.                     clipboard->vscroll = 0;
  989.                     InvalidateRect((HWND) wParam, NULL, TRUE);
  990.                     break;
  991.  
  992.                 case SB_BOTTOM:
  993.                     TOPPARA(clipboard) = clipboard->eof;
  994.                     TOPLINE(clipboard) = clipboard->eof->lastline;
  995.                     clipboard->vscroll = clipboard->nr_lines;
  996.                     InvalidateRect((HWND) wParam, NULL, TRUE);
  997.                     break;
  998.  
  999.                 case SB_LINEUP:
  1000.                     if (!PREVLINE(clipboard->top)) return (0);
  1001.                     i = TOPLINE(clipboard)->height + TOPPARA(clipboard)->spacing;
  1002.                     clipboard->vscroll--;
  1003.                     ScrollWindow((HWND) wParam, 0, i, NULL, &rect);
  1004.                     break;
  1005.  
  1006.                 case SB_LINEDOWN:
  1007.                     i = TOPLINE(clipboard)->height + TOPPARA(clipboard)->spacing;
  1008.  
  1009.                     if (!NEXTLINE(clipboard->top)) return (0);
  1010.                     clipboard->vscroll++;
  1011.                     ScrollWindow((HWND) wParam, 0, -i, NULL, &rect);
  1012.                     break;
  1013.  
  1014.                 case SB_PAGEUP:
  1015.                     i = -(clipboard->spacing - LINEGAP(clipboard));
  1016.                     p = clipboard->top;
  1017.                     do {
  1018.                         i += LINEOF(p)->height + clipboard->spacing;
  1019.                         if (i + LINEGAP(clipboard) > clipboard->height) break;
  1020.                         clipboard->vscroll--;
  1021.                     } while (PREVLINE(p));
  1022.  
  1023.                     clipboard->top = p;
  1024.                     InvalidateRect((HWND) wParam, NULL, TRUE);
  1025.                     break;
  1026.  
  1027.                 case SB_PAGEDOWN:
  1028.                     i = -(clipboard->spacing - LINEGAP(clipboard));
  1029.                     p = clipboard->top;
  1030.                     do {
  1031.                         i += LINEOF(p)->height + clipboard->spacing;
  1032.                         if (i + LINEGAP(clipboard) > clipboard->height) break;
  1033.                         clipboard->vscroll++;
  1034.                     } while (NEXTLINE(p));
  1035.  
  1036.                     clipboard->top = p;
  1037.                     InvalidateRect((HWND) wParam, NULL, TRUE);
  1038.                     break;
  1039.  
  1040.                 case SB_THUMBPOSITION:
  1041.                     clipboard->vscroll = HIWORD(lParam);
  1042.                     i = 0;
  1043.                     PARAOF(p) = clipboard->paragraph;
  1044.                     LINEOF(p) = clipboard->paragraph->lines;
  1045.                     do {
  1046.                        if (i >= clipboard->vscroll) break;
  1047.                        i++;
  1048.                     } while (NEXTLINE(p));
  1049.  
  1050.                     clipboard->top = p;
  1051.                     InvalidateRect((HWND) wParam, NULL, TRUE);
  1052.                     return (0);
  1053.             }
  1054.  
  1055.             SetScrollPos((HWND) wParam, SB_VERT, clipboard->vscroll, TRUE);
  1056.             return (0);
  1057.     }
  1058.  
  1059.     return (DefFrameProc(hwnd, global.clienthwnd, message, wParam, lParam));
  1060. }
  1061.