/*
 * Wordpad implementation - Printing and print preview functions
 *
 * Copyright 2007 by Alexander N. Sørnes <alex@thehandofagony.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <windows.h>
#include <richedit.h>
#include <commctrl.h>

#include "wordpad.h"

typedef struct _previewinfo
{
    int page;
    int pages;
    HDC hdc;
    HDC hdcSized;
    RECT window;
    LPWSTR wszFileName;
} previewinfo, *ppreviewinfo;

static HGLOBAL devMode;
static HGLOBAL devNames;

static RECT margins;
static previewinfo preview;

static const WCHAR var_pagemargin[] = {'P','a','g','e','M','a','r','g','i','n',0};

static LPWSTR get_print_file_filter(HWND hMainWnd)
{
    static WCHAR wszPrintFilter[MAX_STRING_LEN*2+6+4+1];
    const WCHAR files_prn[] = {'*','.','P','R','N',0};
    const WCHAR files_all[] = {'*','.','*','\0'};
    LPWSTR p;
    HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE);

    p = wszPrintFilter;
    LoadStringW(hInstance, STRING_PRINTER_FILES_PRN, p, MAX_STRING_LEN);
    p += lstrlenW(p) + 1;
    lstrcpyW(p, files_prn);
    p += lstrlenW(p) + 1;
    LoadStringW(hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN);
    p += lstrlenW(p) + 1;
    lstrcpyW(p, files_all);
    p += lstrlenW(p) + 1;
    *p = 0;

    return wszPrintFilter;
}

void registry_set_pagemargins(HKEY hKey)
{
    RegSetValueExW(hKey, var_pagemargin, 0, REG_BINARY, (LPBYTE)&margins, sizeof(RECT));
}

void registry_read_pagemargins(HKEY hKey)
{
    DWORD size = sizeof(RECT);

    if(!hKey || RegQueryValueExW(hKey, var_pagemargin, 0, NULL, (LPBYTE)&margins,
                     &size) != ERROR_SUCCESS || size != sizeof(RECT))
    {
        margins.top = 1417;
        margins.bottom = 1417;
        margins.left = 1757;
        margins.right = 1757;
    }
}

static void AddTextButton(HWND hRebarWnd, int string, int command, int id)
{
    REBARBANDINFOW rb;
    HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hRebarWnd, GWLP_HINSTANCE);
    WCHAR text[MAX_STRING_LEN];
    HWND hButton;

    LoadStringW(hInstance, string, text, MAX_STRING_LEN);
    hButton = CreateWindowW(WC_BUTTONW, text,
                            WS_VISIBLE | WS_CHILD, 5, 5, 100, 15,
                            hRebarWnd, (HMENU)command, hInstance, NULL);

    rb.cbSize = sizeof(rb);
    rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
    rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
    rb.hwndChild = hButton;
    rb.cyChild = rb.cyMinChild = 22;
    rb.cx = rb.cxMinChild = 90;
    rb.cxIdeal = 100;
    rb.wID = id;

    SendMessageW(hRebarWnd, RB_INSERTBAND, -1, (LPARAM)&rb);
}

static HDC make_dc(void)
{
    if(devNames && devMode)
    {
        LPDEVNAMES dn = GlobalLock(devNames);
        LPDEVMODEW dm = GlobalLock(devMode);
        HDC ret;

        ret = CreateDCW((LPWSTR)dn + dn->wDriverOffset,
                         (LPWSTR)dn + dn->wDeviceOffset, 0, dm);

        GlobalUnlock(dn);
        GlobalUnlock(dm);

        return ret;
    } else
    {
        return 0;
    }
}

static LONG twips_to_centmm(int twips)
{
    return MulDiv(twips, 1000, 567);
}

LONG centmm_to_twips(int mm)
{
    return MulDiv(mm, 567, 1000);
}

static LONG twips_to_pixels(int twips, int dpi)
{
    float ret = ((float)twips / ((float)567 * 2.54)) * (float)dpi;
    return (LONG)ret;
}

static LONG devunits_to_twips(int units, int dpi)
{
    float ret = ((float)units / (float)dpi) * (float)567 * 2.54;
    return (LONG)ret;
}


static RECT get_print_rect(HDC hdc)
{
    RECT rc;
    int width, height;

    if(hdc)
    {
        int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
        int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
        width = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALWIDTH), dpiX);
        height = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALHEIGHT), dpiY);
    } else
    {
        width = centmm_to_twips(18500);
        height = centmm_to_twips(27000);
    }

    rc.left = margins.left;
    rc.right = width - margins.right;
    rc.top = margins.top;
    rc.bottom = height - margins.bottom;

    return rc;
}

void target_device(HWND hMainWnd, DWORD wordWrap)
{
    HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
    HDC hdc = make_dc();
    int width = 0;

    if(wordWrap == ID_WORDWRAP_MARGIN)
    {
        RECT rc = get_print_rect(hdc);
        width = rc.right;
    }

    if(!hdc)
    {
        HDC hMaindc = GetDC(hMainWnd);
        hdc = CreateCompatibleDC(hMaindc);
        ReleaseDC(hMainWnd, hMaindc);
    }

    SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, (WPARAM)hdc, width);

    DeleteDC(hdc);
}

static LPWSTR dialog_print_to_file(HWND hMainWnd)
{
    OPENFILENAMEW ofn;
    static WCHAR file[MAX_PATH] = {'O','U','T','P','U','T','.','P','R','N',0};
    static const WCHAR defExt[] = {'P','R','N',0};
    static LPWSTR file_filter;

    if(!file_filter)
        file_filter = get_print_file_filter(hMainWnd);

    ZeroMemory(&ofn, sizeof(ofn));

    ofn.lStructSize = sizeof(ofn);
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
    ofn.hwndOwner = hMainWnd;
    ofn.lpstrFilter = file_filter;
    ofn.lpstrFile = (LPWSTR)file;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrDefExt = (LPWSTR)defExt;

    if(GetSaveFileNameW(&ofn))
        return (LPWSTR)file;
    else
        return FALSE;
}

static int get_num_pages(HWND hEditorWnd, FORMATRANGE fr)
{
    int page = 0;

    do
    {
        page++;
        fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE,
                                     (LPARAM)&fr);
    }
    while(fr.chrg.cpMin && fr.chrg.cpMin < fr.chrg.cpMax);

    return page;
}

static void char_from_pagenum(HWND hEditorWnd, FORMATRANGE *fr, int page)
{
    int i;

    for(i = 1; i <= page; i++)
    {
        if(i == page)
            break;

        fr->chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)fr);
    }
}

static void print(LPPRINTDLGW pd, LPWSTR wszFileName)
{
    FORMATRANGE fr;
    DOCINFOW di;
    HWND hEditorWnd = GetDlgItem(pd->hwndOwner, IDC_EDITOR);
    int printedPages = 0;

    fr.hdc = pd->hDC;
    fr.hdcTarget = pd->hDC;

    fr.rc = get_print_rect(fr.hdc);
    fr.rcPage.left = 0;
    fr.rcPage.right = fr.rc.right + margins.right;
    fr.rcPage.top = 0;
    fr.rcPage.bottom = fr.rc.bottom + margins.bottom;

    ZeroMemory(&di, sizeof(di));
    di.cbSize = sizeof(di);
    di.lpszDocName = wszFileName;

    if(pd->Flags & PD_PRINTTOFILE)
    {
        di.lpszOutput = dialog_print_to_file(pd->hwndOwner);
        if(!di.lpszOutput)
            return;
    }

    if(pd->Flags & PD_SELECTION)
    {
        SendMessageW(hEditorWnd, EM_EXGETSEL, 0, (LPARAM)&fr.chrg);
    } else
    {
        GETTEXTLENGTHEX gt;
        gt.flags = GTL_DEFAULT;
        gt.codepage = 1200;
        fr.chrg.cpMin = 0;
        fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);

        if(pd->Flags & PD_PAGENUMS)
            char_from_pagenum(hEditorWnd, &fr, pd->nToPage);
    }

    StartDocW(fr.hdc, &di);
    do
    {
        if(StartPage(fr.hdc) <= 0)
            break;

        fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr);

        if(EndPage(fr.hdc) <= 0)
            break;

        printedPages++;
        if((pd->Flags & PD_PAGENUMS) && (printedPages > (pd->nToPage - pd->nFromPage)))
            break;
    }
    while(fr.chrg.cpMin && fr.chrg.cpMin < fr.chrg.cpMax);

    EndDoc(fr.hdc);
    SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);
}

void dialog_printsetup(HWND hMainWnd)
{
    PAGESETUPDLGW ps;

    ZeroMemory(&ps, sizeof(ps));
    ps.lStructSize = sizeof(ps);
    ps.hwndOwner = hMainWnd;
    ps.Flags = PSD_INHUNDREDTHSOFMILLIMETERS | PSD_MARGINS;
    ps.rtMargin.left = twips_to_centmm(margins.left);
    ps.rtMargin.right = twips_to_centmm(margins.right);
    ps.rtMargin.top = twips_to_centmm(margins.top);
    ps.rtMargin.bottom = twips_to_centmm(margins.bottom);
    ps.hDevMode = devMode;
    ps.hDevNames = devNames;

    if(PageSetupDlgW(&ps))
    {
        margins.left = centmm_to_twips(ps.rtMargin.left);
        margins.right = centmm_to_twips(ps.rtMargin.right);
        margins.top = centmm_to_twips(ps.rtMargin.top);
        margins.bottom = centmm_to_twips(ps.rtMargin.bottom);
        devMode = ps.hDevMode;
        devNames = ps.hDevNames;
    }
}

void get_default_printer_opts(void)
{
    PRINTDLGW pd;
    ZeroMemory(&pd, sizeof(pd));

    ZeroMemory(&pd, sizeof(pd));
    pd.lStructSize = sizeof(pd);
    pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
    pd.hDevMode = devMode;

    PrintDlgW(&pd);

    devMode = pd.hDevMode;
    devNames = pd.hDevNames;
}

void print_quick(LPWSTR wszFileName)
{
    PRINTDLGW pd;

    ZeroMemory(&pd, sizeof(pd));
    pd.hDC = make_dc();

    print(&pd, wszFileName);
}

void dialog_print(HWND hMainWnd, LPWSTR wszFileName)
{
    PRINTDLGW pd;
    HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);
    int from = 0;
    int to = 0;

    ZeroMemory(&pd, sizeof(pd));
    pd.lStructSize = sizeof(pd);
    pd.hwndOwner = hMainWnd;
    pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE;
    pd.nMinPage = 1;
    pd.nMaxPage = -1;
    pd.hDevMode = devMode;
    pd.hDevNames = devNames;

    SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&from, (LPARAM)&to);
    if(from == to)
        pd.Flags |= PD_NOSELECTION;

    if(PrintDlgW(&pd))
    {
        devMode = pd.hDevMode;
        devNames = pd.hDevNames;
        print(&pd, wszFileName);
    }
}

static void preview_bar_show(HWND hMainWnd, BOOL show)
{
    HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
    int i;

    if(show)
    {
        REBARBANDINFOW rb;
        HWND hStatic;

        AddTextButton(hReBar, STRING_PREVIEW_PRINT, ID_PRINT, BANDID_PREVIEW_BTN1);
        AddTextButton(hReBar, STRING_PREVIEW_NEXTPAGE, ID_PREVIEW_NEXTPAGE, BANDID_PREVIEW_BTN2);
        AddTextButton(hReBar, STRING_PREVIEW_PREVPAGE, ID_PREVIEW_PREVPAGE, BANDID_PREVIEW_BTN3);
        AddTextButton(hReBar, STRING_PREVIEW_CLOSE, ID_FILE_EXIT, BANDID_PREVIEW_BTN4);

        hStatic = CreateWindowW(WC_STATICW, NULL,
                                WS_VISIBLE | WS_CHILD, 0, 0, 0, 0,
                                hReBar, NULL, NULL, NULL);

        rb.cbSize = sizeof(rb);
        rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID;
        rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
        rb.hwndChild = hStatic;
        rb.cyChild = rb.cyMinChild = 22;
        rb.cx = rb.cxMinChild = 90;
        rb.cxIdeal = 100;
        rb.wID = BANDID_PREVIEW_BUFFER;

        SendMessageW(hReBar, RB_INSERTBAND, -1, (LPARAM)&rb);
    } else
    {
        for(i = 0; i <= PREVIEW_BUTTONS; i++)
            SendMessageW(hReBar, RB_DELETEBAND, SendMessageW(hReBar, RB_IDTOINDEX, BANDID_PREVIEW_BTN1+i, 0), 0);
    }
}

void init_preview(HWND hMainWnd, LPWSTR wszFileName)
{
    preview.page = 1;
    preview.hdc = 0;
    preview.wszFileName = wszFileName;
    preview_bar_show(hMainWnd, TRUE);
}

void close_preview(HWND hMainWnd)
{
    preview.window.right = 0;
    preview.window.bottom = 0;
    preview.page = 0;
    preview.pages = 0;

    preview_bar_show(hMainWnd, FALSE);
}

BOOL preview_isactive(void)
{
    return preview.page != 0;
}

LRESULT print_preview(HWND hMainWnd)
{
    FORMATRANGE fr;
    GETTEXTLENGTHEX gt;
    HDC hdc;
    RECT window, background;
    HBITMAP hBitmapCapture, hBitmapScaled;
    int bmWidth, bmHeight, bmNewWidth, bmNewHeight;
    float ratioWidth, ratioHeight, ratio;
    int xOffset, yOffset;
    int barheight;
    HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR);
    PAINTSTRUCT ps;

    hdc = BeginPaint(hMainWnd, &ps);
    GetClientRect(hMainWnd, &window);

    fr.hdcTarget = make_dc();
    fr.rc = get_print_rect(fr.hdcTarget);
    fr.rcPage.left = 0;
    fr.rcPage.top = 0;
    fr.rcPage.bottom = fr.rc.bottom + margins.bottom;
    fr.rcPage.right = fr.rc.right + margins.right;

    bmWidth = twips_to_pixels(fr.rcPage.right, GetDeviceCaps(hdc, LOGPIXELSX));
    bmHeight = twips_to_pixels(fr.rcPage.bottom, GetDeviceCaps(hdc, LOGPIXELSY));

    hBitmapCapture = CreateCompatibleBitmap(hdc, bmWidth, bmHeight);

    if(!preview.hdc)
    {
        RECT paper;
        HWND hEditorWnd = GetDlgItem(hMainWnd, IDC_EDITOR);

        preview.hdc = CreateCompatibleDC(hdc);
        fr.hdc = preview.hdc;
        gt.flags = GTL_DEFAULT;
        gt.codepage = 1200;
        fr.chrg.cpMin = 0;
        fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, 0);

        paper.left = 0;
        paper.right = bmWidth;
        paper.top = 0;
        paper.bottom = bmHeight;

        if(!preview.pages)
            preview.pages = get_num_pages(hEditorWnd, fr);

        SelectObject(preview.hdc, hBitmapCapture);

        char_from_pagenum(hEditorWnd, &fr, preview.page);

        FillRect(preview.hdc, &paper, GetStockObject(WHITE_BRUSH));
        SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
        SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0);

        EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_PREVPAGE), preview.page > 1);
        EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NEXTPAGE), preview.page < preview.pages);
    }

    barheight = SendMessageW(hReBar, RB_GETBARHEIGHT, 0, 0);
    ratioWidth = ((float)window.right - 20.0) / (float)bmHeight;
    ratioHeight = ((float)window.bottom - 20.0 - (float)barheight) / (float)bmHeight;

    if(ratioWidth > ratioHeight)
        ratio = ratioHeight;
    else
        ratio = ratioWidth;

    bmNewWidth = (int)((float)bmWidth * ratio);
    bmNewHeight = (int)((float)bmHeight * ratio);
    hBitmapScaled = CreateCompatibleBitmap(hdc, bmNewWidth, bmNewHeight);

    xOffset = ((window.right - bmNewWidth) / 2);
    yOffset = ((window.bottom - bmNewHeight + barheight) / 2);

    if(window.right != preview.window.right || window.bottom != preview.window.bottom)
    {
        DeleteDC(preview.hdcSized),
                 preview.hdcSized = CreateCompatibleDC(hdc);
                 SelectObject(preview.hdcSized, hBitmapScaled);

                 StretchBlt(preview.hdcSized, 0, 0, bmNewWidth, bmNewHeight, preview.hdc, 0, 0, bmWidth, bmHeight, SRCCOPY);
    }

    window.top = barheight;
    FillRect(hdc, &window, GetStockObject(GRAY_BRUSH));

    SelectObject(hdc, hBitmapScaled);

    background.left = xOffset - 2;
    background.right = xOffset + bmNewWidth + 2;
    background.top = yOffset - 2;
    background.bottom = yOffset + bmNewHeight + 2;

    FillRect(hdc, &background, GetStockObject(BLACK_BRUSH));

    BitBlt(hdc, xOffset, yOffset, bmNewWidth, bmNewHeight, preview.hdcSized, 0, 0, SRCCOPY);

    DeleteDC(fr.hdcTarget);
    preview.window = window;

    EndPaint(hMainWnd, &ps);

    return 0;
}

LRESULT preview_command(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    switch(LOWORD(wParam))
    {
        case ID_FILE_EXIT:
            PostMessageW(hWnd, WM_CLOSE, 0, 0);
            break;

        case ID_PREVIEW_NEXTPAGE:
        case ID_PREVIEW_PREVPAGE:
        {
            HWND hReBar = GetDlgItem(hWnd, IDC_REBAR);
            RECT rc;

            if(LOWORD(wParam) == ID_PREVIEW_NEXTPAGE)
                preview.page++;
            else
                preview.page--;

            preview.hdc = 0;
            preview.window.right = 0;

            GetClientRect(hWnd, &rc);
            rc.top += SendMessageW(hReBar, RB_GETBARHEIGHT, 0, 0);
            InvalidateRect(hWnd, &rc, TRUE);
        }
        break;

        case ID_PRINT:
            dialog_print(hWnd, preview.wszFileName);
            SendMessageW(hWnd, WM_CLOSE, 0, 0);
            break;
    }

    return 0;
}
