Menu

Diff of /trunk/src/DiffViewer.cpp [r881] .. [r882]  Maximize  Restore

Switch to side-by-side view

--- a/trunk/src/DiffViewer.cpp
+++ b/trunk/src/DiffViewer.cpp
@@ -253,6 +253,218 @@
                 SWP_SHOWWINDOW);
         }
         break;
+    case IDM_PRINT:
+        {
+            PRINTDLGEX pdlg = {0};
+            pdlg.lStructSize = sizeof(PRINTDLGEX);
+            pdlg.hwndOwner = *this;
+            pdlg.hInstance = NULL;
+            pdlg.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_ALLPAGES | PD_RETURNDC | PD_NOCURRENTPAGE | PD_NOPAGENUMS;
+            pdlg.nMinPage = 1;
+            pdlg.nMaxPage = 0xffffU; // We do not know how many pages in the document
+            pdlg.nCopies = 1;
+            pdlg.hDC = 0;
+            pdlg.nStartPage = START_PAGE_GENERAL;
+
+            // See if a range has been selected
+            size_t startPos = SendEditor(SCI_GETSELECTIONSTART);
+            size_t endPos = SendEditor(SCI_GETSELECTIONEND);
+
+            if (startPos == endPos)
+                pdlg.Flags |= PD_NOSELECTION;
+            else
+                pdlg.Flags |= PD_SELECTION;
+
+            HRESULT hResult = PrintDlgEx(&pdlg);
+            if ((hResult != S_OK) || (pdlg.dwResultAction != PD_RESULT_PRINT))
+                return 0;
+
+            // reset all indicators
+            size_t endpos = SendEditor(SCI_GETLENGTH);
+            for (int i = INDIC_CONTAINER; i <= INDIC_MAX; ++i)
+            {
+                SendEditor(SCI_SETINDICATORCURRENT, i);
+                SendEditor(SCI_INDICATORCLEARRANGE, 0, endpos);
+            }
+            // store and reset UI settings
+            int viewws = (int)SendEditor(SCI_GETVIEWWS);
+            SendEditor(SCI_SETVIEWWS, 0);
+            int edgemode = (int)SendEditor(SCI_GETEDGEMODE);
+            SendEditor(SCI_SETEDGEMODE, EDGE_NONE);
+            SendEditor(SCI_SETWRAPVISUALFLAGS, SC_WRAPVISUALFLAG_END);
+
+            HDC hdc = pdlg.hDC;
+
+            RECT rectMargins, rectPhysMargins;
+            POINT ptPage;
+            POINT ptDpi;
+
+            // Get printer resolution
+            ptDpi.x = GetDeviceCaps(hdc, LOGPIXELSX);    // dpi in X direction
+            ptDpi.y = GetDeviceCaps(hdc, LOGPIXELSY);    // dpi in Y direction
+
+            // Start by getting the physical page size (in device units).
+            ptPage.x = GetDeviceCaps(hdc, PHYSICALWIDTH);   // device units
+            ptPage.y = GetDeviceCaps(hdc, PHYSICALHEIGHT);  // device units
+
+            // Get the dimensions of the unprintable
+            // part of the page (in device units).
+            rectPhysMargins.left = GetDeviceCaps(hdc, PHYSICALOFFSETX);
+            rectPhysMargins.top = GetDeviceCaps(hdc, PHYSICALOFFSETY);
+
+            // To get the right and lower unprintable area,
+            // we take the entire width and height of the paper and
+            // subtract everything else.
+            rectPhysMargins.right = ptPage.x                        // total paper width
+                - GetDeviceCaps(hdc, HORZRES)                       // printable width
+                - rectPhysMargins.left;                             // left unprintable margin
+
+            rectPhysMargins.bottom = ptPage.y                       // total paper height
+                - GetDeviceCaps(hdc, VERTRES)                       // printable height
+                - rectPhysMargins.top;                              // right unprintable margin
+
+            RECT pagesetupMargin;
+            CRegStdDWORD m_regMargLeft   = CRegStdDWORD(L"Software\\TortoiseSVN\\UDiffpagesetupmarginleft", 2540);
+            CRegStdDWORD m_regMargTop    = CRegStdDWORD(L"Software\\TortoiseSVN\\UDiffpagesetupmargintop", 2540);
+            CRegStdDWORD m_regMargRight  = CRegStdDWORD(L"Software\\TortoiseSVN\\UDiffpagesetupmarginright", 2540);
+            CRegStdDWORD m_regMargBottom = CRegStdDWORD(L"Software\\TortoiseSVN\\UDiffpagesetupmarginbottom", 2540);
+
+            pagesetupMargin.left   = (long)(DWORD)m_regMargLeft;
+            pagesetupMargin.top    = (long)(DWORD)m_regMargTop;
+            pagesetupMargin.right  = (long)(DWORD)m_regMargRight;
+            pagesetupMargin.bottom = (long)(DWORD)m_regMargBottom;
+
+            if (pagesetupMargin.left != 0 || pagesetupMargin.right != 0 ||
+                pagesetupMargin.top != 0 || pagesetupMargin.bottom != 0)
+            {
+                RECT rectSetup;
+
+                // Convert the hundredths of millimeters (HiMetric) or
+                // thousandths of inches (HiEnglish) margin values
+                // from the Page Setup dialog to device units.
+                // (There are 2540 hundredths of a mm in an inch.)
+
+                TCHAR localeInfo[3];
+                GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, localeInfo, 3);
+
+                if (localeInfo[0] == '0')
+                {
+                    // Metric system. '1' is US System
+                    rectSetup.left      = MulDiv (pagesetupMargin.left, ptDpi.x, 2540);
+                    rectSetup.top       = MulDiv (pagesetupMargin.top, ptDpi.y, 2540);
+                    rectSetup.right     = MulDiv(pagesetupMargin.right, ptDpi.x, 2540);
+                    rectSetup.bottom    = MulDiv(pagesetupMargin.bottom, ptDpi.y, 2540);
+                }
+                else
+                {
+                    rectSetup.left      = MulDiv(pagesetupMargin.left, ptDpi.x, 1000);
+                    rectSetup.top       = MulDiv(pagesetupMargin.top, ptDpi.y, 1000);
+                    rectSetup.right     = MulDiv(pagesetupMargin.right, ptDpi.x, 1000);
+                    rectSetup.bottom    = MulDiv(pagesetupMargin.bottom, ptDpi.y, 1000);
+                }
+
+                // Don't reduce margins below the minimum printable area
+                rectMargins.left    = max(rectPhysMargins.left, rectSetup.left);
+                rectMargins.top     = max(rectPhysMargins.top, rectSetup.top);
+                rectMargins.right   = max(rectPhysMargins.right, rectSetup.right);
+                rectMargins.bottom  = max(rectPhysMargins.bottom, rectSetup.bottom);
+            }
+            else
+            {
+                rectMargins.left    = rectPhysMargins.left;
+                rectMargins.top     = rectPhysMargins.top;
+                rectMargins.right   = rectPhysMargins.right;
+                rectMargins.bottom  = rectPhysMargins.bottom;
+            }
+
+            // rectMargins now contains the values used to shrink the printable
+            // area of the page.
+
+            // Convert device coordinates into logical coordinates
+            DPtoLP(hdc, (LPPOINT) &rectMargins, 2);
+            DPtoLP(hdc, (LPPOINT)&rectPhysMargins, 2);
+
+            // Convert page size to logical units and we're done!
+            DPtoLP(hdc, (LPPOINT) &ptPage, 1);
+
+
+            DOCINFO di = {sizeof(DOCINFO), 0, 0, 0, 0};
+            di.lpszDocName = L"CommitMonitor UDiff";
+            di.lpszOutput = 0;
+            di.lpszDatatype = 0;
+            di.fwType = 0;
+            if (::StartDoc(hdc, &di) < 0)
+            {
+                ::DeleteDC(hdc);
+                return 0;
+            }
+
+            size_t lengthDoc = SendEditor(SCI_GETLENGTH);
+            size_t lengthDocMax = lengthDoc;
+            size_t lengthPrinted = 0;
+
+            // Requested to print selection
+            if (pdlg.Flags & PD_SELECTION)
+            {
+                if (startPos > endPos)
+                {
+                    lengthPrinted = endPos;
+                    lengthDoc = startPos;
+                }
+                else
+                {
+                    lengthPrinted = startPos;
+                    lengthDoc = endPos;
+                }
+
+                if (lengthDoc > lengthDocMax)
+                    lengthDoc = lengthDocMax;
+            }
+
+            // We must subtract the physical margins from the printable area
+            Sci_RangeToFormat frPrint;
+            frPrint.hdc             = hdc;
+            frPrint.hdcTarget       = hdc;
+            frPrint.rc.left         = rectMargins.left - rectPhysMargins.left;
+            frPrint.rc.top          = rectMargins.top - rectPhysMargins.top;
+            frPrint.rc.right        = ptPage.x - rectMargins.right - rectPhysMargins.left;
+            frPrint.rc.bottom       = ptPage.y - rectMargins.bottom - rectPhysMargins.top;
+            frPrint.rcPage.left     = 0;
+            frPrint.rcPage.top      = 0;
+            frPrint.rcPage.right    = ptPage.x - rectPhysMargins.left - rectPhysMargins.right - 1;
+            frPrint.rcPage.bottom   = ptPage.y - rectPhysMargins.top - rectPhysMargins.bottom - 1;
+
+            // Print each page
+            while (lengthPrinted < lengthDoc)
+            {
+                ::StartPage(hdc);
+
+                frPrint.chrg.cpMin = (long)lengthPrinted;
+                frPrint.chrg.cpMax = (long)lengthDoc;
+
+                lengthPrinted = SendEditor(SCI_FORMATRANGE, true, reinterpret_cast<LPARAM>(&frPrint));
+
+                ::EndPage(hdc);
+            }
+
+            SendEditor(SCI_FORMATRANGE, FALSE, 0);
+
+            ::EndDoc(hdc);
+            ::DeleteDC(hdc);
+
+            if (pdlg.hDevMode != NULL)
+                GlobalFree(pdlg.hDevMode);
+            if (pdlg.hDevNames != NULL)
+                GlobalFree(pdlg.hDevNames);
+            if (pdlg.lpPageRanges != NULL)
+                GlobalFree(pdlg.lpPageRanges);
+
+            // reset the UI
+            SendEditor(SCI_SETVIEWWS, viewws);
+            SendEditor(SCI_SETEDGEMODE, edgemode);
+            SendEditor(SCI_SETWRAPVISUALFLAGS, SC_WRAPVISUALFLAG_NONE);
+        }
+        break;
     default:
         break;
     };