mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
466 lines
9 KiB
C++
466 lines
9 KiB
C++
#include "CtrlLib.h"
|
|
|
|
#ifdef GUI_WIN
|
|
#ifndef PLATFORM_WINCE
|
|
|
|
#include <commdlg.h>
|
|
#pragma comment(lib, "comdlg32.lib")
|
|
|
|
#endif
|
|
#else
|
|
|
|
#include <PdfDraw/PdfDraw.h>
|
|
|
|
#endif
|
|
|
|
NAMESPACE_UPP
|
|
|
|
#ifdef GUI_WIN
|
|
|
|
#ifndef PLATFORM_WINCE
|
|
|
|
#include <commdlg.h>
|
|
#pragma comment(lib, "comdlg32.lib")
|
|
|
|
struct Win32PrintDlg_ : PRINTDLG {
|
|
Win32PrintDlg_() {
|
|
memset(this, 0, sizeof(PRINTDLG));
|
|
lStructSize = sizeof(PRINTDLG);
|
|
}
|
|
~Win32PrintDlg_() {
|
|
if(hDevMode)
|
|
::GlobalFree(hDevMode);
|
|
if(hDevNames)
|
|
::GlobalFree(hDevNames);
|
|
}
|
|
};
|
|
|
|
PrinterJob::PrinterJob(const char *_name)
|
|
{
|
|
name = _name;
|
|
landscape = false;
|
|
from = to = 1;
|
|
current = 1;
|
|
}
|
|
|
|
PrinterJob::~PrinterJob()
|
|
{
|
|
}
|
|
|
|
bool PrinterJob::Execute0(bool dodlg)
|
|
{
|
|
pdlg = new Win32PrintDlg_;
|
|
PRINTDLG& dlg = *pdlg;
|
|
dlg.Flags = PD_DISABLEPRINTTOFILE|PD_NOSELECTION|PD_HIDEPRINTTOFILE|PD_RETURNDEFAULT;
|
|
dlg.nFromPage = current;
|
|
dlg.nToPage = current;
|
|
dlg.nMinPage = from;
|
|
dlg.nMaxPage = to;
|
|
if(from != to)
|
|
dlg.Flags |= PD_ALLPAGES;
|
|
dlg.hwndOwner = 0;
|
|
dlg.Flags |= PD_RETURNDEFAULT;
|
|
dlg.nCopies = 1;
|
|
if(!PrintDlg(&dlg)) return false;
|
|
if(dlg.hDevMode) {
|
|
DEVMODE *pDevMode = (DEVMODE*)::GlobalLock(dlg.hDevMode);
|
|
pDevMode->dmOrientation = landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
|
|
::GlobalUnlock(dlg.hDevMode);
|
|
}
|
|
HDC hdc;
|
|
if(dodlg) {
|
|
dlg.Flags = PD_DISABLEPRINTTOFILE|PD_NOSELECTION|PD_HIDEPRINTTOFILE|PD_RETURNDC|PD_USEDEVMODECOPIESANDCOLLATE;
|
|
Vector< Ptr<Ctrl> > disabled = DisableCtrls(Ctrl::GetTopCtrls());
|
|
bool b = PrintDlg(&dlg);
|
|
EnableCtrls(disabled);
|
|
if(!b) return false;
|
|
hdc = dlg.hDC;
|
|
}
|
|
else {
|
|
DEVNAMES *p = (DEVNAMES *)::GlobalLock(dlg.hDevNames);
|
|
const char *driver = (const char *)p + p->wDriverOffset;
|
|
const char *device = (const char *)p + p->wDeviceOffset;
|
|
if(dlg.hDevMode) {
|
|
DEVMODE *pDevMode = (DEVMODE*)::GlobalLock(dlg.hDevMode);
|
|
hdc = CreateDC(driver, device, NULL, pDevMode);
|
|
::GlobalUnlock(dlg.hDevMode);
|
|
}
|
|
else
|
|
hdc = CreateDC(driver, device, NULL, NULL);
|
|
}
|
|
if(dlg.hDevMode)
|
|
::GlobalFree(dlg.hDevMode);
|
|
if(dlg.hDevNames)
|
|
::GlobalFree(dlg.hDevNames);
|
|
if(hdc) {
|
|
draw = new PrintDraw(hdc, Nvl(name, Ctrl::GetAppName()));
|
|
page.Clear();
|
|
if(!(dlg.Flags & PD_PAGENUMS)) {
|
|
dlg.nFromPage = dlg.nMinPage;
|
|
dlg.nToPage = dlg.nMaxPage;
|
|
}
|
|
for(int i = dlg.nFromPage - 1; i <= dlg.nToPage - 1; i++)
|
|
page.Add(i);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool PrinterJob::Execute()
|
|
{
|
|
return Execute0(true);
|
|
}
|
|
|
|
Draw& PrinterJob::GetDraw()
|
|
{
|
|
if(!draw) {
|
|
Execute0(false);
|
|
if(!draw)
|
|
draw = new NilDraw;
|
|
}
|
|
return *draw;
|
|
}
|
|
|
|
PrinterJob& PrinterJob::MinMaxPage(int minpage, int maxpage)
|
|
{
|
|
from = minpage + 1;
|
|
to = maxpage + 1;
|
|
return *this;
|
|
}
|
|
|
|
PrinterJob& PrinterJob::CurrentPage(int i)
|
|
{
|
|
current = i + 1;
|
|
return *this;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef PLATFORM_X11
|
|
|
|
struct PageSizeName {
|
|
const char *name;
|
|
int cx, cy;
|
|
|
|
Size GetDots() const { return Size(6000 * cx / 254, 6000 * cy / 254); }
|
|
}
|
|
static const PageName2Size[] = {
|
|
{ "A0", 841, 1189 },
|
|
{ "A1", 594, 841 },
|
|
{ "A2", 420, 594 },
|
|
{ "A3", 297, 420 },
|
|
{ "A4", 210, 297 },
|
|
{ "A5", 148, 210 },
|
|
{ "A6", 105, 148 },
|
|
{ "A7", 74, 105 },
|
|
{ "A8", 52, 74 },
|
|
{ "A9", 37, 52 },
|
|
{ "B0", 1030, 1456 },
|
|
{ "B1", 728, 1030 },
|
|
{ "B10", 32, 45 },
|
|
{ "B2", 515, 728 },
|
|
{ "B3", 364, 515 },
|
|
{ "B4", 257, 364 },
|
|
{ "B5", 182, 257 },
|
|
{ "B6", 128, 182 },
|
|
{ "B7", 91, 128 },
|
|
{ "B8", 64, 91 },
|
|
{ "B9", 45, 64 },
|
|
{ "C5E", 163, 229 },
|
|
{ "Comm10E", 105, 241 },
|
|
{ "DLE", 110, 220 },
|
|
{ "Executive", 191, 254 },
|
|
{ "Folio", 210, 330 },
|
|
{ "Ledger", 432, 279 },
|
|
{ "Legal", 216, 356 },
|
|
{ "Letter", 216, 279 },
|
|
{ "Tabloid", 279, 432 }
|
|
};
|
|
|
|
const PageSizeName *FindPageSize(const String& name)
|
|
{
|
|
for(int i = 0; i < __countof(PageName2Size); i++)
|
|
if(PageName2Size[i].name == name)
|
|
return &PageName2Size[i];
|
|
return NULL;
|
|
}
|
|
|
|
String System(const char *cmd, const String& in)
|
|
{
|
|
String ofn = GetTempFileName();
|
|
String ifn = GetTempFileName();
|
|
SaveFile(ifn, in);
|
|
String c = cmd;
|
|
c << " >" << ofn;
|
|
if(in.GetCount())
|
|
c << " <" << ifn;
|
|
String q;
|
|
if(system(c) >= 0)
|
|
q = LoadFile(ofn);
|
|
FileDelete(ofn);
|
|
FileDelete(ifn);
|
|
return q;
|
|
}
|
|
|
|
String System(const char *cmd)
|
|
{
|
|
return System(cmd, Null);
|
|
}
|
|
|
|
class PrinterDlg : public WithPrinterLayout<TopWindow> {
|
|
typedef PrinterDlg CLASSNAME;
|
|
|
|
public:
|
|
void FillOpt(const String& s, const char *id, DropList& dl, bool pgsz);
|
|
void SyncPrinterOptions();
|
|
|
|
PrinterDlg();
|
|
bool IsCanceled();
|
|
|
|
private:
|
|
void StandardizePrinterName(String& printerName);
|
|
void OnOK();
|
|
|
|
private:
|
|
bool canceled;
|
|
};
|
|
|
|
void PrinterDlg::FillOpt(const String& s, const char *id, DropList& dl, bool pgsz)
|
|
{
|
|
int a = s.Find('/');
|
|
int b = s.Find(':');
|
|
if(a > 0 && b > a) {
|
|
String opt = ToLower(s.Mid(0, a));
|
|
if(opt == id) {
|
|
Vector<String> v = Split(~s + b + 1, ' ');
|
|
dl.Enable();
|
|
for(int i = 0; i < v.GetCount(); i++) {
|
|
String o = v[i];
|
|
if(o[0] == '*') {
|
|
o = o.Mid(1);
|
|
dl <<= o;
|
|
}
|
|
if(!pgsz || FindPageSize(o))
|
|
dl.Add(o);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinterDlg::SyncPrinterOptions()
|
|
{
|
|
Vector<String> l = Split(System("lpoptions -d " + String(~printer) + " -l"), '\n');
|
|
paper.Disable();
|
|
paper.Clear();
|
|
slot.Disable();
|
|
slot.Clear();
|
|
for(int i = 0; i < l.GetCount(); i++) {
|
|
FillOpt(l[i], "pagesize", paper, true);
|
|
FillOpt(l[i], "inputslot", slot, false);
|
|
}
|
|
}
|
|
|
|
PrinterDlg::PrinterDlg() : canceled(true)
|
|
{
|
|
CtrlLayoutOKCancel(*this, "Print");
|
|
printer <<= THISBACK(SyncPrinterOptions);
|
|
ok <<= THISBACK(OnOK);
|
|
npage.Add(1);
|
|
npage.Add(2);
|
|
npage.Add(4);
|
|
npage.Add(6);
|
|
npage.Add(9);
|
|
npage.Add(16);
|
|
npage <<= 1;
|
|
copies <<= 1;
|
|
landscape <<= 0;
|
|
range <<= 0;
|
|
Vector<String> l = Split(System("lpstat -a"), '\n');
|
|
for(int i = 0; i < l.GetCount(); i++) {
|
|
Vector<String> w = Split(l[i], ' ');
|
|
if(w.GetCount())
|
|
printer.Add(w[0]);
|
|
}
|
|
String h = System("lpstat -d");
|
|
int q = h.Find(':');
|
|
if(q >= 0) {
|
|
String p = h.Mid(q + 1);
|
|
StandardizePrinterName(p);
|
|
if(printer.HasKey(p)) {
|
|
printer <<= p;
|
|
SyncPrinterOptions();
|
|
return;
|
|
}
|
|
}
|
|
if(printer.GetCount()) {
|
|
printer.SetIndex(0);
|
|
SyncPrinterOptions();
|
|
}
|
|
}
|
|
|
|
bool PrinterDlg::IsCanceled()
|
|
{
|
|
return canceled;
|
|
}
|
|
|
|
void PrinterDlg::StandardizePrinterName(String& printerName)
|
|
{
|
|
printerName.Replace(" ", "");
|
|
printerName.Replace("\r", "");
|
|
printerName.Replace("\n", "");
|
|
}
|
|
|
|
void PrinterDlg::OnOK()
|
|
{
|
|
canceled = false;
|
|
Close();
|
|
}
|
|
|
|
Size PrinterJob::GetDefaultPageSize(String *name)
|
|
{
|
|
static const char PageSize[] = "Page Size:";
|
|
Size sz(6000 * 210 / 254, 6000 * 297 / 254);
|
|
|
|
//default printer properties
|
|
Vector<String> dpp = Split(System("lpoptions -l"), '\n');
|
|
|
|
for (int i = 0; i < dpp.GetCount(); i++){
|
|
int pos = dpp[i].Find(PageSize);
|
|
if (pos >= 0){
|
|
pos += sizeof(PageSize);
|
|
pos = dpp[i].Find('*', pos);
|
|
//return A4 if there is not default page size
|
|
if (pos < 0) return sz;
|
|
//skip '*'
|
|
pos++;
|
|
int len = dpp[i].Find(' ', pos);
|
|
if (len < 0) len = dpp[i].GetLength();
|
|
len -= pos;
|
|
//page name
|
|
String nm = dpp[i].Mid(pos, len);
|
|
if(name)
|
|
*name = nm;
|
|
const PageSizeName *p = FindPageSize(nm);
|
|
if(p) {
|
|
sz = p->GetDots();
|
|
return sz;
|
|
}
|
|
}
|
|
}
|
|
//return A4 if there is not default page size
|
|
return sz;
|
|
}
|
|
|
|
PrinterJob::PrinterJob(const char *_name)
|
|
{
|
|
name = _name;
|
|
landscape = false;
|
|
from = to = 0;
|
|
current = 0;
|
|
pgsz = GetDefaultPageSize();
|
|
dlgSuccess = false;
|
|
}
|
|
|
|
PrinterJob::~PrinterJob()
|
|
{
|
|
}
|
|
|
|
bool PrinterJob::Execute0()
|
|
{
|
|
PrinterDlg dlg;
|
|
dlg.from <<= from + 1;
|
|
dlg.to <<= to + 1;
|
|
dlg.from.Min(from + 1).Max(to + 1);
|
|
dlg.to.Min(from + 1).Max(to + 1);
|
|
dlg.from.Enable(from != to);
|
|
dlg.to.Enable(from != to);
|
|
dlg.range.EnableCase(1, from != to);
|
|
dlg.range.EnableCase(2, from != to);
|
|
String h;
|
|
GetDefaultPageSize(&h);
|
|
h.IsEmpty() ? dlg.paper <<= "A4" : dlg.paper <<= h;
|
|
|
|
dlg.Run();
|
|
if(dlg.IsCanceled())
|
|
return false;
|
|
|
|
options.Clear();
|
|
options << "-d " << ~dlg.printer;
|
|
options << " -o media=";
|
|
dlg.paper.GetIndex() < 0 ? options << ~dlg.slot : options << ~dlg.paper << "," << ~dlg.slot;
|
|
if(dlg.landscape)
|
|
options << " -o landscape";
|
|
options << " -o number-up=" << ~dlg.npage;
|
|
options << " -n " << ~dlg.copies;
|
|
if(dlg.collate)
|
|
options << " -o Collate=True";
|
|
page.Clear();
|
|
switch(dlg.range) {
|
|
case 0:
|
|
for(int i = from; i <= to; i++)
|
|
page.Add(i);
|
|
break;
|
|
case 1:
|
|
page.Add(current);
|
|
break;
|
|
case 2:
|
|
for(int i = (int)~dlg.from - 1; i <= (int)~dlg.to - 1; i++)
|
|
page.Add(i);
|
|
break;
|
|
}
|
|
pgsz = Size(5100, 6600);
|
|
|
|
const PageSizeName *p = FindPageSize(~dlg.paper);
|
|
if(p)
|
|
pgsz = p->GetDots();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PrinterJob::Execute()
|
|
{
|
|
dlgSuccess = Execute0();
|
|
return dlgSuccess;
|
|
}
|
|
|
|
struct PrinterDraw : PdfDraw {
|
|
String options;
|
|
bool canceled;
|
|
|
|
PrinterDraw(Size sz) : PdfDraw(sz), canceled(true) {}
|
|
~PrinterDraw() {
|
|
if(!canceled && !IsEmpty()) {
|
|
System("lp " + options, Finish());
|
|
}
|
|
}
|
|
};
|
|
|
|
Draw& PrinterJob::GetDraw()
|
|
{
|
|
if(!draw) {
|
|
PrinterDraw *pd = new PrinterDraw(pgsz);
|
|
pd->canceled = !dlgSuccess;
|
|
pd->options = options;
|
|
draw = pd;
|
|
}
|
|
return *draw;
|
|
}
|
|
|
|
PrinterJob& PrinterJob::MinMaxPage(int minpage, int maxpage)
|
|
{
|
|
from = minpage;
|
|
to = maxpage;
|
|
return *this;
|
|
}
|
|
|
|
PrinterJob& PrinterJob::CurrentPage(int i)
|
|
{
|
|
current = i;
|
|
return *this;
|
|
}
|
|
|
|
#endif
|
|
|
|
END_UPP_NAMESPACE
|