1343 lines
31 KiB
C++
Executable File
1343 lines
31 KiB
C++
Executable File
#include <stdlib.h>
|
|
#include <xvt.h>
|
|
|
|
#if XVT_OS==XVT_OS_SCOUNIX
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#else
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
#define STYLE_NUM 4
|
|
|
|
#include <mask.h>
|
|
#include <utility.h>
|
|
#include <viswin.h>
|
|
#include <applicat.h>
|
|
#include <extcdecl.h>
|
|
|
|
#include <printer.h>
|
|
#include <execp.h>
|
|
#include <bagn001a.h>
|
|
#include <strstream.h>
|
|
|
|
struct PrDesc {
|
|
TTextfile* _txt;
|
|
PRINT_RCD* _prcd;
|
|
bool _graphics;
|
|
int _formlen;
|
|
int _charsize;
|
|
int _lines_per_inch;
|
|
} PrintWhat;
|
|
|
|
|
|
#define LINES_PER_INCH (6.0)
|
|
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
|
|
#include <windows.h>
|
|
|
|
void TPrinter::_get_windows_printer_names(TToken_string& t)
|
|
{
|
|
char* buf = new char[4096]; // ammazzao'
|
|
GetProfileString("devices", NULL, "", buf, 4096);
|
|
|
|
for(int i = 0; i < 4095; i++)
|
|
{
|
|
if (buf[i] == '\0' && buf[i+1] == '\0')
|
|
break;
|
|
if (buf[i] == '\0' && buf[i+1] != '\0')
|
|
buf[i] = '|';
|
|
}
|
|
t = buf;
|
|
delete buf;
|
|
}
|
|
|
|
|
|
BOOLEAN TPrinter::start_winprint(long data)
|
|
{
|
|
PrDesc* pd = (PrDesc*)data;
|
|
TTextfile& txt = *(pd->_txt);
|
|
TPrintwin pw(pd->_prcd, txt, pd->_charsize);
|
|
pw.print_background(pd->_graphics);
|
|
pw.do_print();
|
|
return pw.aborted();
|
|
}
|
|
#endif
|
|
|
|
|
|
// utils del caz
|
|
HIDDEN void read_int(const char* s, int& n, int& cnt)
|
|
{
|
|
static char nbuf[10]; int j = 0;
|
|
while (!isdigit(s[cnt])) cnt++;
|
|
while (isdigit(s[cnt])) nbuf[j++] = s[cnt++];
|
|
nbuf[j] = '\0'; n = atoi(nbuf);
|
|
}
|
|
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
void TPrinter::set_win_formlen()
|
|
{
|
|
long pw, ph, phr, pvr;
|
|
xvt_escape(XVT_ESC_GET_PRINTER_INFO, _print_rcd, &ph, &pw, &pvr, &phr);
|
|
if (pvr != 0)
|
|
{
|
|
_formlen = (int)((ph/pvr)*_lines_per_inch);
|
|
_dots_per_line = (int)(pvr/_lines_per_inch);
|
|
_vert_offset = (int)(ph % (long)(_formlen * _dots_per_line));
|
|
_horz_offset = 0; // not implemented (font dependent)
|
|
}
|
|
else warning_box("Il driver di stampante non e' valido. Non stampare prima di averlo"
|
|
" reinstallato");
|
|
}
|
|
#endif
|
|
|
|
|
|
void TPrinter::_parse_background()
|
|
{
|
|
char op; int x1, x2, y1, y2;
|
|
TToken_string tt(20);
|
|
TString txt(80);
|
|
TArray pix; char ch; int cnt = 0;
|
|
|
|
while ((ch = _bg_desc[cnt++]) != '\0')
|
|
{
|
|
op = ch; tt = ""; char bf[2]; bf[1] = '\0';
|
|
switch (op)
|
|
{
|
|
case ' ': // ignore whitespace
|
|
case '\t':
|
|
case '\n':
|
|
continue;
|
|
break;
|
|
case 'l': // line
|
|
case 'b': // box
|
|
case 'r': // round box
|
|
cnt++; read_int(_bg_desc,x1,cnt); read_int(_bg_desc,y1,cnt);
|
|
read_int(_bg_desc,x2,cnt); read_int(_bg_desc,y2,cnt); cnt++;
|
|
tt << op; tt.add(x1-1); tt.add(y1-1); tt.add(x2-1); tt.add(y2-1);
|
|
break;
|
|
case 't': // text
|
|
cnt++;
|
|
read_int(_bg_desc,x1,cnt); read_int(_bg_desc,y1,cnt);
|
|
cnt++; txt = "";
|
|
while ((ch = _bg_desc[cnt++]) != '}') txt << ch;
|
|
tt << op; tt.add(x1-1); tt.add(y1-1); tt.add(txt);
|
|
break;
|
|
case 'P': // set pen style
|
|
case 'B': // set brush
|
|
case 'W': // set line width
|
|
case 'C': // set pen color
|
|
tt << op; bf[0] = _bg_desc[cnt++]; tt.add(bf);
|
|
break;
|
|
default:
|
|
yesnofatal_box("Unknown background opcode: %c", op);
|
|
break;
|
|
}
|
|
pix.add(tt);
|
|
}
|
|
|
|
// now build row descriptions
|
|
|
|
// colors are listed in printapp:
|
|
|
|
char curcol = 'n';
|
|
char curpen = 'n';
|
|
char curpat = 'n';
|
|
char curwid = '1';
|
|
|
|
for (int l = 0; l < _formlen; l++)
|
|
{
|
|
|
|
TString* rwd = (TString*)_background.objptr(l);
|
|
if (rwd == NULL)
|
|
{
|
|
_background.add(rwd = new TString,l);
|
|
if (curcol != 'n') (*rwd) << 'C' << curcol;
|
|
if (curpat != 'n') (*rwd) << 'B' << curpat;
|
|
if (curwid != '1') (*rwd) << 'W' << curwid;
|
|
if (curpen != 'n') (*rwd) << 'P' << curcol;
|
|
}
|
|
for (int j = 0; j < pix.items(); j++)
|
|
{
|
|
TToken_string& tt = (TToken_string&)pix[j];
|
|
tt.restart();
|
|
|
|
// la stringa contiene l'opcode piu' i parametri in binario,
|
|
// incrementati di 1 per evitare lo 0
|
|
|
|
switch(*(tt.get(0)))
|
|
{
|
|
case 'b':
|
|
x1 = tt.get_int(1)+1; y1 = tt.get_int(2)+1;
|
|
x2 = tt.get_int(3)+1; y2 = tt.get_int(4)+1;
|
|
if (y1 == l+1) // at ze biginnin
|
|
{
|
|
(*rwd) << 'u' << char(x1);
|
|
(*rwd) << 'r' << char(x1) << char(x2);
|
|
(*rwd) << 'u' << char(x2);
|
|
}
|
|
else if (y2 == l+1) // at ze end
|
|
{
|
|
(*rwd) << 'o' << char(x1);
|
|
(*rwd) << 'r' << char(x1) << char(x2);
|
|
(*rwd) << 'o' << char(x2);
|
|
}
|
|
else if (y1 < l+1 && y2 > l+1) // in ze middol
|
|
{
|
|
(*rwd) << 'v' << char(x1);
|
|
(*rwd) << 'v' << char(x2);
|
|
}
|
|
break;
|
|
case 'l':
|
|
x1 = tt.get_int(1)+1; y1 = tt.get_int(2)+1;
|
|
x2 = tt.get_int(3)+1; y2 = tt.get_int(4)+1;
|
|
if (y1 == y2 && y1 == l+1) // orizzontale
|
|
{
|
|
(*rwd) << 'h' << char(x1) << char(x2);
|
|
}
|
|
else if (y1 <= l+1 && y2 >= l+1) // verticale
|
|
{
|
|
(*rwd) << 'v' << char(x1);
|
|
}
|
|
break;
|
|
case 't':
|
|
x1 = tt.get_int(1)+1; y1 = tt.get_int(2)+1; // al gh'e'
|
|
if (y1 == l+1)
|
|
{}
|
|
break;
|
|
case 'W':
|
|
curwid = *(tt.get(1));
|
|
(*rwd) << 'W' << curwid;
|
|
break;
|
|
case 'P':
|
|
curpen = *(tt.get(1));
|
|
(*rwd) << 'P' << curpen;
|
|
break;
|
|
case 'B':
|
|
curpat = *(tt.get(1));
|
|
(*rwd) << 'B' << curpat;
|
|
break;
|
|
case 'C':
|
|
curcol = *(tt.get(1));
|
|
(*rwd) << 'C' << curcol;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TPrinter::setbackground(const char* b)
|
|
{
|
|
_background.destroy();
|
|
_bg_desc = b;
|
|
if (b != NULL) _parse_background();
|
|
}
|
|
|
|
|
|
bool printers_on_key (TMask_field& f, KEY key);
|
|
|
|
// fv support structs for config
|
|
|
|
bool PrinterDef::read(const char* name, FILE* fd)
|
|
{
|
|
_printername = name;
|
|
_printername.trim();
|
|
|
|
TToken_string tmp(64, '=');
|
|
TString l(48);
|
|
TString r(16);
|
|
|
|
while(TRUE)
|
|
{
|
|
const long p = ftell(fd); // Memorizza inizio paragrafo
|
|
|
|
if (fgets(__tmp_string,256,fd) == NULL)
|
|
return FALSE;
|
|
tmp = __tmp_string; tmp.trim();
|
|
|
|
if (tmp == "[End of File]")
|
|
return FALSE;
|
|
|
|
if (tmp[0] == '[')
|
|
{
|
|
fseek(fd,p,SEEK_SET); // Ritorna ad inizio paragrafo
|
|
break;
|
|
}
|
|
|
|
l = tmp.get(); l.trim();
|
|
r = tmp.get(); r.trim();
|
|
|
|
if (l == "Device name") { _devicename = r; } else
|
|
if (l == "Filter name") { _filtername = r; } else
|
|
if (l == "Printer type"){ _printertype = r; } else
|
|
if (l == "Normal") { strcpy(_atstr[normalstyle], r); } else
|
|
if (l == "Bold") { strcpy(_atstr[boldstyle], r); } else
|
|
if (l == "Italic") { strcpy(_atstr[italicstyle], r); } else
|
|
if (l == "Underlined") { strcpy(_atstr[underlinedstyle], r); } else
|
|
if (l == "Code") { TToken_string code(r); _names.add(TString( code.get()));
|
|
_codes.add(TString(code.get())); } else
|
|
if (l == "Form feed") { _ffcode = r; } else
|
|
if (l == "Newline") { _nlcode = r; } else
|
|
return error_box("Riga di configurazione stampante errata:\n%s", (const char*)l);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool PrinterDef::isdefault()
|
|
{
|
|
return strcmp(_printername,"Default") == 0;
|
|
}
|
|
|
|
////////// TPRINTROW //////////
|
|
|
|
TPrintrow::TPrintrow ()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
TPrintrow::TPrintrow(const TPrintrow& pr)
|
|
{
|
|
_row = pr.row();
|
|
memcpy(_attr, pr._attr,MAXSTR);
|
|
memcpy(_cols, pr._cols,MAXSTR);
|
|
_currentcolor = 'w'; _currentcolor <<= 8; _currentcolor += 'n';
|
|
_currentstyle = pr._currentstyle;
|
|
for (int i = 0; i < MAXSTR; i++) _cols[i] = _currentcolor;
|
|
_lastpos = pr._lastpos;
|
|
}
|
|
|
|
TObject* TPrintrow::dup() const
|
|
{
|
|
return new TPrintrow(*this);
|
|
}
|
|
|
|
const char* TPrintrow::class_name() const
|
|
{
|
|
return "Printrow";
|
|
}
|
|
|
|
word TPrintrow::class_id() const
|
|
{
|
|
return CLASS_PRINTROW;
|
|
}
|
|
|
|
|
|
TPrintrow& TPrintrow::reset()
|
|
{
|
|
_row.spaces(sizeof(_attr));
|
|
_currentcolor = 'w'; _currentcolor <<= 8; _currentcolor += 'n';
|
|
memset(_attr, normalstyle, sizeof(_attr));
|
|
for (int i = 0; i < MAXSTR; i++) _cols[i] = _currentcolor;
|
|
_lastpos = 0;
|
|
_currentstyle = normalstyle;
|
|
return *this;
|
|
}
|
|
|
|
const char* TPrintrow::row_codified()
|
|
{
|
|
// returns the row with @-codes for font style and color
|
|
char last_attr = -1; int last_color = -1;
|
|
int k = 0;
|
|
_row.rtrim();
|
|
for(int i = 0; i < _row.len(); i++)
|
|
{
|
|
if (_attr[i] != last_attr)
|
|
{
|
|
__tmp_string[k++] = '@';
|
|
switch(_attr[i])
|
|
{
|
|
case normalstyle: __tmp_string[k++] = 'r'; break;
|
|
case boldstyle: __tmp_string[k++] = 'b'; break;
|
|
case italicstyle: __tmp_string[k++] = 'i'; break;
|
|
case underlinedstyle: __tmp_string[k++] = 'u'; break;
|
|
}
|
|
last_attr = _attr[i];
|
|
}
|
|
if (_cols[i] != last_color)
|
|
{
|
|
__tmp_string[k++] = '$';
|
|
__tmp_string[k++] = '[';
|
|
__tmp_string[k++] = (char)(_cols[i] & 0x00ff);
|
|
__tmp_string[k++] = ',';
|
|
__tmp_string[k++] = (char)(_cols[i] >> 8);
|
|
__tmp_string[k++] = ']';
|
|
last_color = _cols[i];
|
|
}
|
|
__tmp_string[k++] = _row[i];
|
|
}
|
|
// k = k > 255 ? 255 : k;
|
|
__tmp_string[k] = '\0';
|
|
return __tmp_string;
|
|
}
|
|
|
|
|
|
TPrintrow& TPrintrow::put (const char* str, int position, int len)
|
|
{
|
|
if (len < 1)
|
|
len = strlen(str);
|
|
|
|
if (position < 0)
|
|
position = _lastpos;
|
|
|
|
char bg = 'w', fg = 'n';
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
char c = str[i];
|
|
if (c == '$' && str[i+1] == '[')
|
|
{
|
|
++i;
|
|
fg = str[++i];
|
|
c = str[++i];
|
|
if (c == ']')
|
|
bg = _currentcolor >> 8;
|
|
else if (c == ',')
|
|
{ bg = str[++i]; i++; }
|
|
else { CHECK(0,"Error in color specification"); }
|
|
_currentcolor = (bg << 8) + fg;
|
|
}
|
|
else if (c == '@')
|
|
{
|
|
c = str[++i];
|
|
switch (toupper(c))
|
|
{
|
|
case '#':
|
|
case '<':
|
|
case '>':
|
|
// printer MUST handle them
|
|
{
|
|
const int n = (c == '#') ? 5 : ((c == '>') ? 10 : 8);
|
|
_row[position] = '@'; _attr[position++] = _currentstyle;
|
|
for (int j = 1; j < n; j++)
|
|
{
|
|
_row[position] = c;
|
|
_attr[position++] = _currentstyle;
|
|
}
|
|
}
|
|
break;
|
|
case 'B':
|
|
_currentstyle = boldstyle;
|
|
break;
|
|
case 'I':
|
|
_currentstyle = italicstyle;
|
|
break;
|
|
case 'U':
|
|
_currentstyle = underlinedstyle;
|
|
break;
|
|
case 'R':
|
|
_currentstyle = normalstyle;
|
|
break;
|
|
default:
|
|
// should be number followed by skip or jump
|
|
if (isdigit(c))
|
|
{
|
|
// read number
|
|
char digbuf[8]; int cnt = 0;
|
|
digbuf[cnt++] = c;
|
|
while (isdigit(c = str[++i]))
|
|
digbuf[cnt++] = c;
|
|
digbuf[cnt] = '\0';
|
|
int pp = atoi(digbuf);
|
|
if (toupper(c) == 'G')
|
|
{
|
|
if (pp >= MAXSTR)
|
|
fatal_box("printrow reaches position %d",pp);
|
|
if (pp > position)
|
|
for (int k = position; k < pp; k++)
|
|
{
|
|
_attr[k] = _currentstyle;
|
|
_cols[k] = _currentcolor;
|
|
}
|
|
position = pp;
|
|
}
|
|
else if (toupper(c) == 'J')
|
|
{
|
|
if (pp+position >= MAXSTR)
|
|
fatal_box("printrow reaches position %d", pp+position);
|
|
for (int k = 0; k < pp; k++)
|
|
{
|
|
_attr[k+position] = _currentstyle;
|
|
_cols[k+position] = _currentcolor;
|
|
}
|
|
position += pp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_row[position] = c;
|
|
_attr[position++] = _currentstyle;
|
|
_cols[position++] = _currentcolor;
|
|
}
|
|
} // switch
|
|
}
|
|
else
|
|
{
|
|
_row[position] = c;
|
|
_attr[position] = _currentstyle;
|
|
_cols[position++] = _currentcolor;
|
|
}
|
|
} // for
|
|
|
|
_lastpos = position;
|
|
return *this;
|
|
}
|
|
|
|
////////// TPRINTER //////////
|
|
|
|
bool printers_on_key (TMask_field& f, KEY key)
|
|
{
|
|
if (key==K_SPACE)
|
|
{
|
|
TToken_string pn1(10), pn2(20);
|
|
|
|
const PrinterDef& def = MainApp()->printer().get_description(atoi(f.get()));
|
|
const char* s;
|
|
int j = 0;
|
|
while ((s = def.get_codenames(j)) != NULL)
|
|
{
|
|
pn1.add(format("%02d", j));
|
|
pn2.add(s);
|
|
j++;
|
|
}
|
|
((TList_field&) f.mask().field(MSK_1_CODES)).replace_items(pn1, pn2);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
|
|
bool set_windows_print_device(TMask_field& f, KEY key)
|
|
{
|
|
static char szDevice[80];
|
|
if (key == K_SPACE)
|
|
{
|
|
if (MainApp()->printer().get_printrcd() != NULL)
|
|
free_print_rcd(MainApp()->printer().get_printrcd());
|
|
TToken_string& pn = MainApp()->printer().getprinternames();
|
|
TString pdev(pn.get(atoi(f.get())));
|
|
GetProfileString("devices", pdev, "", szDevice, sizeof(szDevice));
|
|
pdev << "," << szDevice;
|
|
// WriteProfileString("windows","device", pdev);
|
|
// madonna bona
|
|
MainApp()->printer().set_printrcd(get_print_rcd(&(MainApp()->printer().get_printrcdsize())));
|
|
MainApp()->printer().set_win_formlen();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
TPrinter::TPrinter() : _date(TODAY), _multiple_link(FALSE), _frozen(FALSE), _isgraphics(TRUE),
|
|
_lines_per_inch(6), _ch_size(12)
|
|
|
|
{
|
|
_footerhandler = _headerhandler = NULL;
|
|
_linkhandler = NULL;
|
|
_config = "printer.ini";
|
|
_curprn = 0; // first in list if no default is specified
|
|
_curcode = 0; // first in list if no default is specified
|
|
_formlen = 66;
|
|
_frompage = 0;
|
|
_topage = 0xffff;
|
|
_hwformfeed = FALSE;
|
|
_currentpage = 1;
|
|
_currentrow = 1;
|
|
_fp = NULL;
|
|
_headersize = 0;
|
|
_footersize = 0;
|
|
_isopen = FALSE;
|
|
// read configuration file
|
|
read_configuration(_config);
|
|
#if XVT_OS == XVT_OS_WIN
|
|
print_begin();
|
|
_print_rcd = get_print_rcd(&_print_rcd_size);
|
|
set_win_formlen();
|
|
#else
|
|
_isgraphics = FALSE;
|
|
#endif
|
|
}
|
|
|
|
|
|
TToken_string& TPrinter::getprinternames()
|
|
{
|
|
// per ora va solo in windows
|
|
#if XVT_OS == XVT_OS_WIN
|
|
_get_windows_printer_names(_printer_names);
|
|
#endif
|
|
return _printer_names;
|
|
}
|
|
|
|
void TPrinter::read_configuration(const char* conf)
|
|
{
|
|
|
|
FILE* cnfp=fopen(conf, "r");
|
|
if (cnfp == NULL)
|
|
fatal_box("Impossibile aprire il file %s", (const char*) _config);
|
|
|
|
for (int i = 0; !feof(cnfp); i++)
|
|
{
|
|
if (fgets(__tmp_string,256,cnfp) == NULL) return;
|
|
// else
|
|
if (strncmp(__tmp_string, "[Default]",9) != 0)
|
|
// fgets(__tmp_string,256,cnfp);
|
|
// else
|
|
{
|
|
if (*__tmp_string == '[')
|
|
{
|
|
// fatal_box("[ expected in file of printer configuration");
|
|
|
|
char* u = strchr(__tmp_string, ']');
|
|
if (u) *u = '\0';
|
|
u = __tmp_string+1;
|
|
|
|
PrinterDef* pp = new PrinterDef;
|
|
_printers.add(pp);
|
|
if (pp->read(u, cnfp) == FALSE)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
fclose(cnfp);
|
|
|
|
TString s("printer.def");
|
|
#if XVT_OS == XVT_OS_SCOUNIX
|
|
s << format(".%d", getuid());
|
|
#endif
|
|
if (fexist(s))
|
|
{
|
|
TScanner sc(s);
|
|
TToken_string t(sc.line());
|
|
int where_print = t.get_int(1);
|
|
t = sc.line();
|
|
_curprn = t.get_int(1);
|
|
t = sc.line();
|
|
_printerfile = t.get(1);
|
|
t = sc.line();
|
|
_curcode = t.get_int(1);
|
|
#if XVT_OS != XVT_OS_WIN
|
|
PrinterDef& def = (PrinterDef&)get_description(_curprn);
|
|
#endif
|
|
switch (where_print)
|
|
{
|
|
case 0: // stampante
|
|
#if XVT_OS == XVT_OS_WIN
|
|
_printertype = winprinter;
|
|
#else
|
|
switch (atoi(def._printertype))
|
|
{
|
|
case 0:
|
|
_printertype = normprinter;
|
|
break;
|
|
case 1:
|
|
_printertype = localprinter;
|
|
break;
|
|
case 2:
|
|
_printertype = spoolprinter;
|
|
break;
|
|
}
|
|
#endif
|
|
break;
|
|
case 1: // file
|
|
_printertype = fileprinter;
|
|
break;
|
|
case 2: // video
|
|
_printertype = screenvis;
|
|
_curcode = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
TPrinter::~TPrinter()
|
|
{
|
|
#if XVT_OS == XVT_OS_WIN
|
|
print_end();
|
|
#endif
|
|
}
|
|
|
|
const char* TPrinter::class_name() const
|
|
{
|
|
return "Printer";
|
|
}
|
|
|
|
word TPrinter::class_id() const
|
|
{
|
|
return CLASS_PRINTER;
|
|
}
|
|
|
|
TPrintrow* TPrinter::getheaderline (int linetoget)
|
|
{
|
|
return((TPrintrow*)_header.objptr(linetoget));
|
|
}
|
|
|
|
TPrintrow* TPrinter::getfooterline (int linetoget)
|
|
{
|
|
return((TPrintrow*)_footer.objptr(linetoget));
|
|
}
|
|
|
|
void TPrinter::setheaderline (int linetoset, TPrintrow* line)
|
|
{
|
|
_header.add(line, linetoset);
|
|
if (linetoset >= _headersize) _headersize = linetoset+1;
|
|
}
|
|
|
|
void TPrinter::setheaderline (int linetoset, const TPrintrow& line)
|
|
{
|
|
TPrintrow* p = new TPrintrow(line);
|
|
setheaderline(linetoset, p);
|
|
}
|
|
|
|
void TPrinter::setfooterline (int linetoset, TPrintrow* line)
|
|
{
|
|
_footer.add(line,linetoset);
|
|
// if (linetoset >= _footersize) _footersize = linetoset+1;
|
|
}
|
|
|
|
void TPrinter::setfooterline (int linetoset, const TPrintrow& line)
|
|
{
|
|
TPrintrow* p = new TPrintrow(line);
|
|
setfooterline(linetoset, p);
|
|
}
|
|
|
|
void TPrinter::resetheader()
|
|
{
|
|
_header.destroy();
|
|
_headersize = 0;
|
|
}
|
|
|
|
void TPrinter::resetfooter()
|
|
{
|
|
_footer.destroy();
|
|
// _footersize = 0;
|
|
}
|
|
|
|
bool TPrinter::printrow(TPrintrow* rowtoprint)
|
|
{
|
|
if (!isopen()) return FALSE;
|
|
|
|
if (_currentpage < _frompage || _currentpage > _topage)
|
|
return TRUE;
|
|
|
|
|
|
TString rw(rowtoprint == NULL ? "" : (_printertype == screenvis || _printertype == winprinter ?
|
|
rowtoprint->row_codified() :
|
|
rowtoprint->row()));
|
|
rw.rtrim();
|
|
|
|
int lun = rw.len();
|
|
int idx;
|
|
|
|
for (idx = 0; idx < lun; idx++)
|
|
{
|
|
if (rw[idx] == '@') // gestione data e n. di pagina
|
|
{
|
|
switch(rw[idx+1])
|
|
{
|
|
case '#': rw.overwrite(format("%-5u", _currentpage), idx++); break;
|
|
case '>': rw.overwrite(_date.string(4), idx++); break;
|
|
case '<': rw.overwrite(_date.string(2), idx++); break;
|
|
default : break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_printertype == screenvis)
|
|
{
|
|
if (!_vf->frozen()) _vf->add_line(rw);
|
|
else _frozen = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
if (_printertype == winprinter)
|
|
{
|
|
// add line to txt
|
|
if (!_frozen) _txt.append(rw);
|
|
return TRUE;
|
|
}
|
|
|
|
const PrinterDef& pd = get_description(_curprn);
|
|
int prvstl = -1;
|
|
for (idx = 0; idx < lun; idx++)
|
|
{
|
|
int cst=rowtoprint->get_style(idx);
|
|
if (cst!=prvstl)
|
|
{
|
|
fprintf(_fp,"%s", pd._atstr[normalstyle]);
|
|
if (cst != normalstyle)
|
|
fprintf(_fp,"%s", pd._atstr[cst]);
|
|
}
|
|
prvstl=cst;
|
|
putc(rw[idx], _fp);
|
|
}
|
|
if (newline())
|
|
putc(newline(), _fp);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
word TPrinter::rows_left() const
|
|
{
|
|
word left = _formlen-_currentrow-_footersize+1;
|
|
if (_currentrow < 2) left -= _headersize;
|
|
return left;
|
|
}
|
|
|
|
bool TPrinter::print(TPrintrow& rowtoprint)
|
|
{
|
|
bool ok = TRUE;
|
|
|
|
if (_currentrow > _formlen-_footersize)
|
|
ok = printfooter();
|
|
|
|
// if (ok && _currentrow <= _headersize)
|
|
if (ok && _currentrow == 1)
|
|
ok = printheader();
|
|
|
|
if (ok)
|
|
{
|
|
ok = printrow(&rowtoprint);
|
|
_currentrow++;
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
bool TPrinter::printheader ()
|
|
{
|
|
if (_headerhandler) _headerhandler(*this);
|
|
|
|
bool ok = TRUE;
|
|
for(int i = 0; i < _headersize && ok; i++)
|
|
ok = printrow(getheaderline(i));
|
|
|
|
_currentrow = _headersize+1;
|
|
return ok;
|
|
}
|
|
|
|
bool TPrinter::printfooter ()
|
|
{
|
|
if (_footerhandler) _footerhandler(*this);
|
|
|
|
bool ok = TRUE;
|
|
for(int i = 0; i < _footersize && ok; i++)
|
|
ok = printrow(getfooterline(i));
|
|
|
|
#if XVT_OS != XVT_OS_WIN
|
|
if (ok) printformfeed();
|
|
#endif
|
|
|
|
_currentrow = 1;
|
|
_currentpage++;
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool TPrinter::skip (int linestoskip)
|
|
{
|
|
int jumpline;
|
|
|
|
CHECK(linestoskip>=0, "Linestoskip can't be negative");
|
|
jumpline=_currentrow+linestoskip;
|
|
return jump(jumpline);
|
|
}
|
|
|
|
bool TPrinter::jump (int jumpline)
|
|
{
|
|
int i=0;
|
|
bool ok=TRUE;
|
|
|
|
CHECK(jumpline>=0, "Jumpline can't be negative");
|
|
if (jumpline>_formlen-_footersize) ok=formfeed();
|
|
else for(i=_currentrow;i<jumpline;i++) if (!printrow()) ok=FALSE;
|
|
if (jumpline>_formlen-_footersize) ok=FALSE;
|
|
return ok;
|
|
}
|
|
|
|
bool TPrinter::formfeed ()
|
|
{
|
|
const int lastrow = _formlen-_footersize;
|
|
for (;_currentrow <= lastrow; _currentrow++)
|
|
printrow();
|
|
return printfooter();
|
|
}
|
|
|
|
void TPrinter::reset ()
|
|
{
|
|
resetheader();
|
|
resetfooter();
|
|
_currentpage=1;
|
|
_currentrow=1;
|
|
}
|
|
|
|
bool TPrinter::printformfeed ()
|
|
{
|
|
#if XVT_OS != XVT_OS_WIN
|
|
const PrinterDef& pd = get_description(_curprn);
|
|
|
|
if (_printertype != screenvis && _hwformfeed)
|
|
fprintf(_fp,"%s",(const char*)pd._ffcode);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
bool TPrinter::open ()
|
|
{
|
|
// qui
|
|
#if XVT_OS==XVT_OS_SCOUNIX
|
|
if (_printertype==spoolprinter)
|
|
{
|
|
const PrinterDef& def = get_description(_curprn);
|
|
int pfd[2];
|
|
|
|
if (pipe(pfd) == -1)
|
|
return error_box("Impossibile creare processo di stampa ""(pipe)");
|
|
|
|
int ret = fork();
|
|
if (ret == -1)
|
|
return error_box("Impossibile creare processo di stampa ""(fork)");
|
|
|
|
if (ret == 0)
|
|
{
|
|
if ((::close(0) != -1) && (::dup(pfd[0]) == 0) &&
|
|
(::close(pfd[0]) == 0) && (::close(pfd[1]) != -1))
|
|
{
|
|
char s0[80];
|
|
|
|
sprintf(s0, "-d%s", (const char*) def._devicename);
|
|
if ((def._filtername).not_empty())
|
|
{
|
|
char s1[80];
|
|
sprintf(s1, "-o %s", (const char*) def._filtername);
|
|
char *ws[5] = { "lpr", "-s", s0, s1, NULL};
|
|
execvp(ws[0], ws);
|
|
}
|
|
else
|
|
{
|
|
char *ws[4] = { "lpr", "-s", s0, NULL};
|
|
execvp(ws[0], ws);
|
|
}
|
|
exit(-1);
|
|
}
|
|
}
|
|
if ((::close(pfd[0])==-1) || ((_fp=fdopen(pfd[1],"w"))==NULL))
|
|
return error_box("Impossibile creare processo di stampa""(close)");
|
|
}
|
|
else
|
|
#endif
|
|
if (_printertype == screenvis)
|
|
{
|
|
_vf = new TViswin(NULL, "Anteprima di stampa", TRUE, TRUE,
|
|
_linksdescr.items() > 0);
|
|
_vf->open_modal();
|
|
}
|
|
else if (_printertype == winprinter)
|
|
{
|
|
// prepare text object for new text
|
|
_txt.destroy();
|
|
}
|
|
else
|
|
{
|
|
const PrinterDef& def = get_description(_curprn);
|
|
TFilename fname(_printerfile);
|
|
|
|
if (_printertype == normprinter) fname = def._devicename;
|
|
_fp = fopen(fname, "w");
|
|
|
|
if (_fp == NULL)
|
|
return error_box("Errore di apertura file stampa: '%s'",
|
|
(const char*)fname);
|
|
|
|
TString code(def.get_codes(_curcode));
|
|
if (code.not_empty())
|
|
{
|
|
const char* s = code;
|
|
fputs(esc((char*)s), _fp);
|
|
}
|
|
}
|
|
|
|
_currentrow = 1;
|
|
_currentpage = 1;
|
|
|
|
return _isopen = TRUE;
|
|
}
|
|
|
|
void TPrinter::set()
|
|
{
|
|
TMask mask("bagn001a.msk");
|
|
TToken_string pn1(50), pn2(100);
|
|
int i;
|
|
|
|
MainApp()->disable_menu_item(M_FILE_PG_SETUP);
|
|
#if XVT_OS != XVT_OS_WIN
|
|
for (i = 0; i < _printers.items(); i++)
|
|
{
|
|
pn1.add(i);
|
|
pn2.add(((PrinterDef&) _printers[i])._printername);
|
|
}
|
|
((TList_field&)(mask.field(MSK_1_PRINTERS))).replace_items(pn1, pn2);
|
|
mask.hide(MSK_1_SETUP);
|
|
mask.hide(MSK_1_SIZE);
|
|
mask.hide(MSK_1_LINES);
|
|
pn1 = "";
|
|
pn2 = "";
|
|
for (i = 0; i < ((PrinterDef&)_printers[_curprn])._names.items(); i++ )
|
|
{
|
|
pn1.add(format("%d", i));
|
|
pn2.add((TString&)((PrinterDef&) _printers[_curprn])._names[i]);
|
|
}
|
|
((TList_field&)(mask.field(MSK_1_CODES))).replace_items(pn1, pn2);
|
|
mask.set_handler(MSK_1_PRINTERS, printers_on_key);
|
|
if (_printertype == fileprinter)
|
|
mask.set(MSK_1_TYPE, "1");
|
|
else
|
|
if (_printertype == screenvis)
|
|
mask.set(MSK_1_TYPE, "2");
|
|
else
|
|
mask.set(MSK_1_TYPE, "0");
|
|
|
|
mask.set(MSK_1_PRINTERS, format("%d",_curprn));
|
|
mask.set(MSK_1_CODES, format("%d",_curcode));
|
|
mask.set(MSK_1_FILENAME, _printerfile);
|
|
mask.reset(MSK_1_SAVE);
|
|
|
|
if (mask.run() == K_ESC) return;
|
|
|
|
if (mask.get(MSK_1_SAVE).not_empty())
|
|
{
|
|
TString s("printer.def");
|
|
#if XVT_OS == XVT_OS_SCOUNIX
|
|
s << format(".%d", getuid());
|
|
#endif
|
|
mask.set_workfile(s);
|
|
mask.save();
|
|
}
|
|
|
|
|
|
// get user choices
|
|
|
|
_curprn = atoi(mask.get(MSK_1_PRINTERS));
|
|
PrinterDef& def = (PrinterDef&)get_description(_curprn);
|
|
switch (atoi(mask.get(MSK_1_TYPE)))
|
|
{
|
|
case 0: // stampante
|
|
_printertype = normprinter;
|
|
_curcode = atoi(mask.get(MSK_1_CODES));
|
|
switch (atoi(def._printertype))
|
|
{
|
|
case 0:
|
|
_printertype = normprinter;
|
|
break;
|
|
case 1:
|
|
_printertype = localprinter;
|
|
break;
|
|
case 2:
|
|
_printertype = spoolprinter;
|
|
break;
|
|
}
|
|
break;
|
|
case 1: // file
|
|
_printertype = fileprinter;
|
|
_printerfile = mask.get(MSK_1_FILENAME);
|
|
_curcode = atoi(mask.get(MSK_1_CODES));
|
|
break;
|
|
case 2: // video
|
|
_printertype = screenvis;
|
|
_curcode = 0;
|
|
break;
|
|
}
|
|
|
|
#else
|
|
|
|
static char defPrinter[80];
|
|
static char szDevice[50];
|
|
int defIndex;
|
|
|
|
// get default printer driver
|
|
GetProfileString("windows","device",",,,",defPrinter, sizeof(defPrinter));
|
|
TString pdev(defPrinter);
|
|
GetProfileString("devices", pdev, "", szDevice, sizeof(szDevice));
|
|
pdev << "," << szDevice;
|
|
TToken_string dio(pdev, ',');
|
|
|
|
// get printer names
|
|
_get_windows_printer_names(pn2);
|
|
// determine index of current default printer
|
|
for (i = 0; i < pn2.items(); i++)
|
|
{
|
|
if (TString(dio.get(0)) == TString(pn2.get(i)))
|
|
{
|
|
defIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
if (defIndex == pn2.items()) defIndex = 0; // should never happen
|
|
|
|
for (i = 0; i < pn2.items(); i++) pn1.add(i);
|
|
|
|
((TList_field&)(mask.field(MSK_1_PRINTERS))).replace_items(pn1, pn2);
|
|
mask.set(MSK_1_PRINTERS, pn1.get(defIndex));
|
|
mask.hide(MSK_1_CODES);
|
|
mask.set(MSK_1_ISGRAPHICS, _isgraphics ? "X" : "");
|
|
mask.set(MSK_1_SIZE, format("%d",_ch_size));
|
|
mask.set(MSK_1_LINES, format("%d",_lines_per_inch));
|
|
|
|
if (_printertype == fileprinter)
|
|
mask.set(MSK_1_TYPE,"1");
|
|
else
|
|
if (_printertype == screenvis)
|
|
mask.set(MSK_1_TYPE, "2");
|
|
else
|
|
mask.set(MSK_1_TYPE, "0");
|
|
|
|
mask.set_handler(MSK_1_PRINTERS, set_windows_print_device);
|
|
mask.reset(MSK_1_SAVE);
|
|
|
|
KEY k;
|
|
while ((k = mask.run()) != K_ESC && k != K_ENTER)
|
|
{
|
|
if (k == MSK_1_SETUP)
|
|
{
|
|
if (_print_rcd != NULL)
|
|
{
|
|
if (page_setup_dlg(_print_rcd))
|
|
{
|
|
// see if user has changed printer
|
|
int dIndex;
|
|
// determine index of currently selected printer
|
|
// ACTHUNG! Deep hacking of XVT internals! NON PORTABLE!
|
|
for (i = 0; i < pn2.items(); i++)
|
|
if (strcmp((const char*)(_print_rcd+4), pn2.get(i)) == 0)
|
|
{
|
|
dIndex = i;
|
|
break;
|
|
}
|
|
mask.set(MSK_1_PRINTERS, pn1.get(dIndex));
|
|
set_win_formlen();
|
|
}
|
|
mask.set_focus();
|
|
}
|
|
else beep();
|
|
}
|
|
}
|
|
if (k == K_ESC)
|
|
{
|
|
// rimetti come prima
|
|
// WriteProfileString("windows","device", pdev);
|
|
if (_print_rcd != NULL) free_print_rcd(_print_rcd);
|
|
_print_rcd = get_print_rcd(&_print_rcd_size);
|
|
set_win_formlen();
|
|
return;
|
|
}
|
|
|
|
if (mask.get(MSK_1_SAVE).not_empty())
|
|
{
|
|
TString s("printer.def");
|
|
mask.set_workfile(s);
|
|
mask.save();
|
|
}
|
|
|
|
switch (atoi(mask.get(MSK_1_TYPE)))
|
|
{
|
|
case 0: // stampante
|
|
_printertype = winprinter;
|
|
break;
|
|
case 1: // file
|
|
_printertype = fileprinter;
|
|
_printerfile = mask.get(MSK_1_FILENAME);
|
|
_curcode = atoi(mask.get(MSK_1_CODES));
|
|
break;
|
|
case 2: // video
|
|
_printertype = screenvis;
|
|
_curcode = 0;
|
|
break;
|
|
}
|
|
|
|
_isgraphics = mask.get_bool(MSK_1_ISGRAPHICS);
|
|
_ch_size = atoi(mask.get(MSK_1_SIZE));
|
|
_lines_per_inch = atoi(mask.get(MSK_1_LINES));
|
|
set_win_formlen();
|
|
|
|
#endif
|
|
|
|
MainApp()->enable_menu_item(M_FILE_PG_SETUP);
|
|
}
|
|
|
|
|
|
void TPrinter::close ()
|
|
{
|
|
if (isopen() && _currentrow > 1 &&
|
|
(_footersize || (_printertype != screenvis && _printertype != winprinter)))
|
|
formfeed();
|
|
|
|
if (_fp)
|
|
{
|
|
fclose(_fp);
|
|
_fp = NULL;
|
|
}
|
|
|
|
if (_printertype == screenvis)
|
|
{
|
|
CHECK(_vf, "VF!");
|
|
_vf->close_print();
|
|
_vf->run();
|
|
if (_vf->is_open()) _vf->close_modal();
|
|
delete _vf;
|
|
_vf = NULL;
|
|
}
|
|
#if XVT_OS == XVT_OS_WIN
|
|
else if (_printertype == winprinter)
|
|
{
|
|
PrintWhat._prcd = _print_rcd;
|
|
PrintWhat._txt = &_txt;
|
|
PrintWhat._graphics = _isgraphics;
|
|
PrintWhat._charsize = _ch_size;
|
|
start_print_thread(start_winprint, (long)(&PrintWhat));
|
|
}
|
|
#endif
|
|
else
|
|
|
|
if (_printertype == localprinter)
|
|
{
|
|
#if XVT_OS == XVT_OS_SCOUNIX
|
|
TFilename s1 = tmpnam(NULL);
|
|
switch (fork())
|
|
{
|
|
case -1:
|
|
break;
|
|
case 0:
|
|
execlp("localprint", "localprint", (const char*)s1, NULL);
|
|
default:
|
|
wait ((int*)NULL);
|
|
}
|
|
remove(s1);
|
|
#endif
|
|
}
|
|
_isopen = FALSE;
|
|
}
|
|
|
|
//
|
|
// TFile_printer
|
|
//
|
|
|
|
#include <tfilepr.h>
|
|
|
|
#if XVT_OS == XVT_OS_DOS
|
|
#define FORMAT_COMMAND "FORMAT"
|
|
#else
|
|
#define FORMAT_COMMAND "dosformat -fq"
|
|
#endif
|
|
|
|
const long disk_sizes [] = { 360000, 1200000, 720000, 1400000, 2880000 };
|
|
|
|
|
|
TFile_printer::TFile_printer (const char* ffile, const char * label, int len_rec, int num_rec_inizio, int num_rec_fine, int tipo_disco)
|
|
{
|
|
set_printtype (fileprinter);
|
|
|
|
_num_rec_testa_coda = num_rec_inizio + num_rec_fine;
|
|
_file = ffile;
|
|
_label = label;
|
|
_len_rec = len_rec;
|
|
_volume = 1;
|
|
_size = disk_sizes [tipo_disco];
|
|
_num_rec_volume = int((_size / len_rec) - _num_rec_testa_coda);
|
|
_nome_file_fissato = TRUE;
|
|
_formatta = FALSE;
|
|
_label_fissata = TRUE;
|
|
|
|
}
|
|
|
|
void TFile_printer::open()
|
|
{
|
|
}
|
|
|
|
void TFile_printer::close()
|
|
{
|
|
}
|
|
|
|
bool TFile_printer::genera_dischetti()
|
|
{
|
|
int r;
|
|
|
|
warning_box ("Questa procedura richiede %2d dischetti",
|
|
_volume);
|
|
|
|
for (int i = 0; i < _tmp_files.items(); i++)
|
|
{
|
|
// Avvisa l'utente di inserire un dischetto
|
|
r = yesno_box ("Inserire il dischetto n. %2d di %2d nel drive %2s",
|
|
i+1, _volume, _drive );
|
|
if (!r)
|
|
return error_box ("Procedura interrotta!");
|
|
|
|
// e eventualmente lo formatta
|
|
if (_formatta)
|
|
{
|
|
TString dep (30);
|
|
if (_label != NULL)
|
|
dep << FORMAT_COMMAND << " " << "/v:" << _label << " " << _drive;
|
|
else
|
|
dep << FORMAT_COMMAND << " " << _drive;
|
|
|
|
TExternal_app sys(dep);
|
|
sys.run();
|
|
}
|
|
|
|
// copia il file sul dischetto
|
|
fcopy ((const char *)&_tmp_files[i], (const char *)_drive);
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
TFile_printer::~TFile_printer ()
|
|
{
|
|
}
|
|
|
|
void TFile_printer::set()
|
|
{
|
|
TMask m ("tfilepr");
|
|
KEY tasto;
|
|
int f;
|
|
|
|
//
|
|
//
|
|
// --------------------------------------------------------------------
|
|
// Qui bisogna inserire la lista dei drive disponibili nella maschera
|
|
// Per ora tale lista e' fissa e contiene solo A: e B:
|
|
// --------------------------------------------------------------------
|
|
//
|
|
//
|
|
|
|
m.set (F_FILE_DESTINAZIONE, _file);
|
|
m.set (F_LABEL, _label);
|
|
|
|
if (_nome_file_fissato)
|
|
m.disable (F_FILE_DESTINAZIONE);
|
|
|
|
if (_label_fissata)
|
|
m.disable (F_LABEL);
|
|
|
|
tasto = m.run();
|
|
|
|
if (tasto == K_ENTER)
|
|
{
|
|
f = atoi (m.get (F_FORMATO_DISCO));
|
|
_drive = m.get (F_DRIVE);
|
|
_file = m.get (F_FILE_DESTINAZIONE);
|
|
_label = m.get (F_LABEL);
|
|
_formatta = (bool) (m.get (F_FORMATTA) == "X");
|
|
_size = disk_sizes [f];
|
|
_num_rec_volume = int((_size / _len_rec) - _num_rec_testa_coda);
|
|
}
|
|
}
|
|
|
|
//
|
|
// TFile printer fine
|
|
//
|