campo-sirio/include/printer.cpp
guy 4cbc74e8f5 Patch level : 2.1 nopatch
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :

Correzioni per stampa tabelle


git-svn-id: svn://10.65.10.50/trunk@12171 c028cbd2-c16b-5b4b-a496-9718f37d4682
2004-06-09 09:54:56 +00:00

2100 lines
52 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <config.h>
#include <golem.h>
#include <printer.h>
#include <printwin.h>
#include <urldefid.h>
#include <utility.h>
#include <viswin.h>
#include <agasys.h>
#include <bagn001a.h>
#include <bagn003.h>
HIDDEN TPrinter* _printer = NULL;
///////////////////////////////////////////////////////////
// Maschera impostazione stampante (fatta come si deve dopo 10 anni!)
///////////////////////////////////////////////////////////
class TPrinter_setup_mask : public TAutomask
{
private:
bool _skip_events;
TString _pdev, _font;
PRINT_RCD* _pcd;
int _pcd_size;
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
void fill_font_list();
void fill_size_list();
public:
void set_print_rcd(PRINT_RCD* pcd, int size);
PRINT_RCD* get_print_rcd(int& size) const;
TPrinter_setup_mask();
virtual ~TPrinter_setup_mask();
};
void TPrinter_setup_mask::set_print_rcd(PRINT_RCD* pcd, int size)
{
_pcd = pcd;
_pcd_size = size;
xvt_print_get_name(pcd, _pdev.get_buffer(), _pdev.size());
}
PRINT_RCD* TPrinter_setup_mask::get_print_rcd(int& size) const
{
size = _pcd_size;
return _pcd;
}
void TPrinter_setup_mask::fill_font_list()
{
const int MAX_FAMILIES = 256;
char* family[MAX_FAMILIES];
const int num_families = (int)xvt_fmap_get_families(_pcd, family, MAX_FAMILIES);
TToken_string fn(256);
for (int i = 0; i < num_families; i++)
{
fn.add(family[i]);
xvt_mem_free(family[i]);
}
TList_field& lst = (TList_field&)field(MSK_FONT);
lst.replace_items(fn, fn);
// Controlla se il font c'e' ancora
if (fn.get_pos(_font) < 0)
_font = fn.get(0);
set(MSK_FONT, _font, 0x1);
}
void TPrinter_setup_mask::fill_size_list()
{
const int MAXSIZES = 128;
long sizes[MAXSIZES];
BOOLEAN scalable;
const int num_sizes = (int)xvt_fmap_get_family_sizes(_pcd, _font.get_buffer(), sizes, &scalable, MAXSIZES);
TToken_string pn1;
if (scalable)
{
for (int i = 4; i <= 32; i++)
pn1.add(i);
}
else
{
if (num_sizes > 0)
{
for (int i = 0; i < num_sizes; i++)
pn1.add(sizes[i]);
}
else
pn1.add(printer().get_char_size()); // semper better than nothing
}
TList_field& lst = (TList_field&)field(MSK_SIZE);
const TString8 old_size = lst.get();
lst.replace_items(pn1, pn1);
lst.set(old_size);
lst.enable(pn1.items() > 1);
}
bool TPrinter_setup_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
if (_skip_events)
return TRUE;
switch (o.dlg())
{
case MSK_PRINTERS:
if (fe_modify)
{
const TString& pdev = o.get(); // Nome stampante corrente
if (pdev != _pdev)
{
TWait_cursor hourglass;
if (_pcd != NULL)
xvt_print_destroy(_pcd);
_pcd = xvt_print_create_by_name(&_pcd_size, pdev);
_pdev = pdev;
fill_font_list();
}
}
break;
case MSK_FONT:
if (e == fe_modify)
{
TWait_cursor hourglass;
const TString& family = o.get();
if (_font != family)
{
_font = family;
fill_size_list();
}
}
break;
case DLG_SETPRINT:
if (e == fe_button)
{
if (xvt_dm_post_page_setup(_pcd))
{
// see if user has changed printer
// determine name of currently selected printer
TString name;
xvt_print_get_name(_pcd, name.get_buffer(), name.size());
set(MSK_PRINTERS, name, 0x1);
}
}
break;
default:
break;
}
return TRUE;
}
TPrinter_setup_mask::TPrinter_setup_mask()
: TAutomask("bagn001a")
{
TPrinter& pr = printer();
set(MSK_FILENAME, pr.get_printerfile());
const bool can_save = pr._config == "Printer";
enable(DLG_OK, can_save);
set_print_rcd(pr._print_rcd, pr._print_rcd_size);
// Crea la lista delle stampanti
TToken_string pn2;
SLIST plist = xvt_print_list_devices();
for (SLIST_ELT pitem = xvt_slist_get_first(plist);
pitem != NULL; pitem = xvt_slist_get_next(plist, pitem))
{
const char* pname = xvt_slist_get(plist, pitem, NULL);
pn2.add(pname);
}
xvt_slist_destroy(plist);
_skip_events = TRUE;
if (pr._printertype == fileprinter)
set (MSK_TYPE, "1");
else if (pr._printertype == screenvis)
set(MSK_TYPE, "2");
else
set(MSK_TYPE, "0");
TList_field& plst = (TList_field&)field (MSK_PRINTERS);
plst.replace_items(pn2, pn2); // Genera printer list
set(MSK_PRINTERS, pr._prname);
_font = pr._fontname;
fill_font_list();
fill_size_list();
set(MSK_FONT, _font); // Fare solo quando la lista e' piena
set(MSK_SIZE, pr._ch_size); // Fare solo quando la lista e' piena
set(MSK_LINES, pr._lines_per_inch);
set(MSK_ISGRAPHICS, pr.isgraphics() ? "X" : "");
_skip_events = FALSE;
}
TPrinter_setup_mask::~TPrinter_setup_mask()
{
}
///////////////////////////////////////////////////////////
// TPrinter
///////////////////////////////////////////////////////////
TPrinter& printer()
{
if (_printer == NULL)
_printer = new TPrinter;
return *_printer;
}
void printer_destroy()
{
if (_printer != NULL)
{
delete _printer;
_printer = NULL;
}
}
// ----------------------------------------------------------------------
// TPrint_intersector
// ----------------------------------------------------------------------
// TPrint_intersector: calcola intersezioni tra elementi grafici e
// restituisce, riga per riga, i necessari caratteri di fincatura per
// finculare in modo carattere
// usata da viswin e printwin
class TPrint_intersector : public TString_array
{
const char* _fink;
char check_intersection(int x, int y, char ch);
void h_line(int x1, int y1, int len);
void v_line(int x1, int y1, int len);
// caratteri fincazione: l'ho fatto perche' e' inline
char f_topleft() const { return _fink[0]; }
char f_topmiddle() const { return _fink[1]; }
char f_topright() const { return _fink[2]; }
char f_botleft() const { return _fink[3]; }
char f_botmiddle() const { return _fink[4]; }
char f_botright() const { return _fink[5]; }
char f_centerleft() const { return _fink[6]; }
char f_centermiddle() const { return _fink[7]; }
char f_centerright() const { return _fink[8]; }
char f_horizontal() const { return _fink[9]; }
char f_vertical() const { return _fink[10]; }
public:
// aggiunge un elemento grafico
void add(TGraphic_shape s, int x1, int y1, int x2, int y2);
// aggiunge alla stringa passata i necessari caratteri, leggendo
// dalla pagina interna
const char* get_chars(int line) const;
// sbianca tutto
void clear();
TPrint_intersector(const char* fink, int pagesize) : TString_array(pagesize) , _fink(fink)
{}
virtual ~TPrint_intersector() {}
};
char TPrint_intersector::check_intersection(int x, int y, char ch)
{
char a = ' ', b = ' ', c = ' ', d = ' ';
if (y > 0 && objptr(y-1) != NULL)
b = row(y-1)[x];
if (objptr(y+1) != NULL)
d = row(y+1)[x];
if (x > 0) a = row(y)[x-1];
if (x < row(y).len()-1) c = row(y)[x+1];
if (a == ' ' && b == ' ' && c != ' ' && d != ' ')
ch = f_topleft();
else if (a == ' ' && b != ' ' && c != ' ' && d == ' ')
ch = f_botleft();
else if (a != ' ' && b != ' ' && c == ' ' && d == ' ')
ch = f_botright();
else if (a != ' ' && b == ' ' && c == ' ' && d != ' ')
ch = f_topright();
else if (a != ' ' && b != ' ' && c == ' ' && d != ' ')
ch = f_centerright();
else if (a == ' ' && b != ' ' && c != ' ' && d != ' ')
ch = f_centerleft();
else if (a != ' ' && b != ' ' && c != ' ' && d == ' ')
ch = f_botmiddle();
else if (a != ' ' && b == ' ' && c != ' ' && d != ' ')
ch = f_topmiddle();
else if ((a != ' ' && b != ' ' && c != ' ' && d != ' ') ||
((a != ' ' && b == ' ' && c != ' ' && d == ' ') && ch == f_vertical()) ||
((a == ' ' && b != ' ' && c == ' ' && d != ' ') && ch == f_horizontal()))
ch = f_centermiddle();
return ch;
}
void TPrint_intersector::h_line(int x1, int y1, int len)
{
if (objptr(y1) == NULL)
{
TString* ss = new TString(256);
ss->spaces();
TArray::add(ss, y1);
}
TString& s = row(y1);
int i;
for (i = x1; i < x1+len; i++)
s[i] = f_horizontal();
for (i = x1; i < x1+len; i++)
s[i] = check_intersection(i, y1, f_horizontal());
}
void TPrint_intersector::v_line(int x1, int y1, int len)
{
int i;
for (i = y1; i < y1+len; i++)
{
if (objptr(i) == NULL)
{
TString* ss = new TString(256);
ss->spaces();
TArray::add(ss, i);
}
row(i)[x1] = f_vertical();
}
for (i = y1; i < y1+len; i++)
row(i)[x1] = check_intersection(x1, i, f_vertical());
}
void TPrint_intersector::add(TGraphic_shape s, int x1, int y1, int x2, int y2)
{
// rows start at 0
y1 --; y2 --;
// columns pure, ma e' possibile che siano gia' 0 se la generazione
// e' stata automatica (colonna 1. campo - 1)
if (x1 > 0) x1 --;
if (x2 > 0) x2 --;
switch (s)
{
case line:
if (x1 == x2) // vertical
v_line(x1, y1, y2-y1+1);
else if (y1 == y2) // horizontal
h_line(x1,y1, x2-x1+1);
else error_box("Linee oblique non supportate in modalita' testo");
break;
case box:
h_line(x1, y1, x2-x1+1);
h_line(x1, y2, x2-x1+1);
v_line(x1, y1, y2-y1+1);
v_line(x2, y1, y2-y1+1);
break;
default:
break;
}
}
const char* TPrint_intersector::get_chars(int line) const
{
if (objptr(line) == NULL)
return "";
else
return row(line);
}
void TPrint_intersector::clear()
{
for (int i = 0; i < items(); i++)
{
TString* s = (TString*)objptr(i);
if (s != NULL)
s->spaces();
}
}
///////////////////////////////////////////////////////////
// TPrint_txt_info
///////////////////////////////////////////////////////////
struct TPrint_txt_info
{
TTextfile* _txt;
word _copies;
word _pagefrom;
word _pageto;
word _lastpage;
bool edit();
TPrint_txt_info(TTextfile& txt);
};
bool TPrint_txt_info::edit()
{
TPrinter& p = printer();
TMask msk("bagn003");
msk.set(F_PRINTER, p.printername());
msk.set(F_FORM, p.get_form_name());
msk.set(F_FONT, p.fontname());
msk.set(F_SIZE, p.get_char_size());
msk.set(F_ISGRAPHICS, p.isgraphics() ? "X" : "");
msk.set(F_FROMPAGE, _pagefrom);
msk.set(F_TOPAGE, _lastpage);
msk.set(F_COPIES, _copies);
const bool ok = msk.run() == K_ENTER;
if (ok)
{
_copies = msk.get_int(F_COPIES);
_pagefrom = msk.get_int(F_FROMPAGE);
_pageto = msk.get_int(F_TOPAGE);
if (_pageto < _pagefrom || _pageto >= _lastpage)
_pageto = 0;
}
return ok;
}
TPrint_txt_info::TPrint_txt_info(TTextfile& txt)
: _txt(&txt), _copies(1), _pagefrom(1), _pageto(0)
{
const word ps = printer().formlen();
const long li = txt.lines();
_lastpage = (li+ps-1) / ps;
}
// @cmember Ritorna vero se la stampante e' generica/solo testo
bool TPrinter::is_generic() const
{
bool yes = _dots_per_line == 1;
if (!yes)
yes = _prname.find("Generic") >= 0;
return yes;
}
// @cmember Ritorna vero se sono attivati gli elementi grafici
bool TPrinter::isgraphics() const
{
return _isgraphics;
}
// @cmember Attivati gli elementi grafici se possibile
bool TPrinter::set_graphics(bool g)
{
_isgraphics = g && !is_generic();
return _isgraphics;
}
BOOLEAN TPrinter::start_print(long data)
{
const TPrint_txt_info *pd = (TPrint_txt_info *) data;
TTextfile& txt = *(pd->_txt);
TPrinter& stampante = printer();
const int vofs = stampante.get_line_offset();
const int hofs = stampante.get_column_offset();
if (stampante.is_generic() && (vofs != 0 || hofs != 0))
{
TTextfile new_txt;
TString s(256);
const long last_row = txt.lines();
long out_row = 0;
for (long row = (vofs < 0 ? -vofs : 0); row < last_row; row++)
{
const int pagelen = stampante.formlen();
const int page_row = (int) (out_row % pagelen);
if (vofs > 0 && page_row == 0)
{
const int page = (int) (out_row / pagelen);
for (int i = vofs; i > 0; i--)
{
out_row++;
if (page > 0)
row++;
new_txt.append("");
}
}
if (vofs < 0 && page_row == pagelen + vofs)
{
for (int i = -vofs; i > 0; i--)
{
out_row++;
row++;
new_txt.append("");
}
}
s = txt.line(row);
if (hofs < 0)
s.ltrim(-hofs);
else
if(hofs > 0)
s.lpad(s.len() + hofs);
new_txt.append(s);
out_row++;
}
TPrintwin pw(new_txt);
pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies);
return pw.aborted();
}
else
{
TPrintwin pw(txt);
if (pw.win() != NULL_WIN)
pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies);
return pw.aborted();
}
}
// utils del caz
HIDDEN int read_int (const char *s, int &n, int &cnt)
{
char nbuf[16];
while (!isdigit (s[cnt]))
cnt++;
int j;
for (j = 0; isdigit (s[cnt]); j++)
nbuf[j] = s[cnt++];
nbuf[j] = '\0';
return n = atoi (nbuf);
}
void TPrinter::parse_background(const char* bg_desc, TString_array& background)
{
TString_array pix;
char op, ch;
int x1, x2, y1, y2;
int id, cnt = 0;
TToken_string tt;
TFilename bmp;
if (!_fink_mode && _finker == NULL)
_finker = new TPrint_intersector(_fink, _formlen);
else if (_finker)
_finker->clear();
while ((ch = bg_desc[cnt++]) != '\0')
{
op = ch;
tt = "";
char bf[2];
bf[1] = '\0';
switch (op)
{
case ' ':
case '\t':
case '\n':
continue; // ignore whitespace
break;
case 'i':
cnt++;
for (x1 = 0; bg_desc[cnt] != ','; x1++)
bmp[x1] = bg_desc[cnt++];
bmp[x1] = '\0';
id = _image_names.find(bmp);
if (id < 0) id = _image_names.add(bmp);
read_int(bg_desc, x1, cnt); if (x1 <= 0) x1 = 1;
read_int(bg_desc, y1, cnt); if (y1 <= 0) y1 = 1;
read_int(bg_desc, x2, cnt); if (x2 <= 0) x2 = formwidth();
read_int(bg_desc, y2, cnt); if (y2 <= 0) y2 = formlen();
cnt++;
if (_isgraphics)
{
tt << op;
tt.add(id);
tt.add(x1);
tt.add(y1);
tt.add(x2);
tt.add(y2);
}
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++; // skip separator
if (_isgraphics && _fink_mode)
{
tt << op;
tt.add (x1 - 1);
tt.add (y1 - 1);
tt.add (x2 - 1);
tt.add (y2 - 1);
}
else
{
TGraphic_shape s = op == 'b' ? box : line;
_finker->add(s, x1, y1, x2, y2);
}
break;
case 't': // text
cnt++;
read_int (bg_desc, x1, cnt);
read_int (bg_desc, y1, cnt);
cnt++;
tt << op;
tt.add (x1-1);
tt.add (y1-1);
tt << '|';
while ((ch = bg_desc[cnt++]) != '}')
tt << ch;
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++)
{
if (background.objptr(l) == NULL) // Se la riga non esiste creala
{
TToken_string* r = new TToken_string(15);
if (curcol != 'n') *r << 'C' << curcol; // Setta valori se diversi da default
if (curpat != 'n') *r << 'B' << curpat;
if (curwid != '1') *r << 'W' << curwid;
if (curpen != 'n') *r << 'P' << curcol;
background.add(r, l);
}
TString& rwd = background.row(l);
for (int j = 0; j < pix.items(); j++)
{
TToken_string& tt = pix.row(j);
// la stringa contiene l'opcode piu' i parametri in binario,
// incrementati di 1 per evitare lo 0
switch (tt.get_char(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 'r':
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) // orizzontale
{
if (y1 == l+1)
rwd << 'r' << char (x1) << char (x2);
}
else
{
const int l1 = l+1;
if (l1 >= y1 && l1 <= y2) // verticale
{
char code = 'v';
if (y1 == l1) code = 'u'; else
if (y2 == l1) code = 'o';
rwd << code << 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 'i':
id = tt.get_int();
x1 = tt.get_int();
y1 = tt.get_int();
x2 = tt.get_int();
y2 = tt.get_int();
if (l+1 >= y1 && l+1 <= y2)
rwd << 'i' << char(id+1) << char(l-y1+2) << char(x1)
<< char(x2-x1+1) << char(y2-y1+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;
default:
break;
}
}
}
}
void TPrinter::setbackground(const char* b, int index)
{
CHECK(index >= 0 && index <= 3, "Bad background index");
_backgrounds.destroy(index);
if (b && *b)
{
TString_array* bg = new TString_array(formlen());
_backgrounds.add(bg, index);
parse_background(b, *bg);
}
}
TString_array& TPrinter::getbgdesc(word page) const
{
int index = 0;
if (page == 0 && _backgrounds.objptr(3))
index = 3;
if (page == 1 && _backgrounds.objptr(2))
index = 2;
if (index == 0 && (page & 0x1) == 0 && _backgrounds.objptr(1))
index = 1;
TString_array* bg = (TString_array*)_backgrounds.objptr(index);
if (bg == NULL)
{
bg = new TString_array(formlen());
((TPrinter*)this)->_backgrounds.add(bg, index); // keep const
}
return *bg;
}
//bool printers_on_key(TMask_field & f, KEY key);
////////// TPRINTROW //////////
TPrintrow::TPrintrow()
{
reset();
}
TPrintrow::TPrintrow(const TPrintrow& pr)
{
reset();
_row = pr.row ();
memcpy (_attr, pr._attr, MAX_PR_WIDTH);
memcpy (_cols, pr._cols, MAX_PR_WIDTH);
_tab = pr._tab;
if (pr._images)
_images = new TToken_string(*pr._images);
_currentstyle = pr._currentstyle;
_currentcolor = pr._currentcolor;
_lastpos = pr._lastpos;
}
TPrintrow::~TPrintrow()
{
if (_images)
delete _images;
}
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)); // Azzera testo
memset(_attr, normalstyle, sizeof (_attr)); // Azzera stile
_tab.reset(); // Azzera tabulazioni
_images = NULL;
_currentcolor = 'w';
_currentcolor <<= 8;
_currentcolor += 'n';
for (int i = 0; i < MAX_PR_WIDTH; i++)
_cols[i] = _currentcolor; // Azzera colori
_lastpos = 0;
_currentstyle = normalstyle;
return *this;
}
const char* TPrintrow::row_codified() const
{
char last_attr = -1;
int last_color = -1;
int k = 0, i = 0, len = 0;
char* tmp = get_tmp_string(256).get_buffer();
// Calcolo lunghezza stringa
for (i = _row.size()-1; i >= 0; i--)
{
if (_row[i] != ' ')
{
len = i+1;
break;
}
}
for (i = 0; i < len; i++)
{
if (_tab[i])
{
tmp[k++] = '@';
tmp[k++] = 't';
}
if (_attr[i] != last_attr)
{
tmp[k++] = '@';
switch (_attr[i])
{
case normalstyle:
tmp[k++] = 'r';
break;
case boldstyle:
tmp[k++] = 'b';
break;
case italicstyle:
tmp[k++] = 'i';
break;
case underlinedstyle:
tmp[k++] = 'u';
break;
}
last_attr = _attr[i];
}
if (_cols[i] != last_color)
{
tmp[k++] = '$';
tmp[k++] = '[';
tmp[k++] = (char) (_cols[i] & 0x00ff);
tmp[k++] = ',';
tmp[k++] = (char) (_cols[i] >> 8);
tmp[k++] = ']';
last_color = _cols[i];
}
if (_row[i] == '@' && strchr("<#>", _row[i+1]) == NULL)
tmp[k++] = '@'; // Escape for @
tmp[k++] = _row[i];
}
tmp[k] = '\0';
if (_images)
{
strcat(tmp, "$[w,w]"); // Bianco su bianco!
FOR_EACH_TOKEN((*_images), tok)
strcat(tmp, tok);
}
return tmp;
}
TPrintrow& TPrintrow::put(const char *str, int position, int len)
{
if (len <= 0)
len = strlen (str);
if (position < 0)
position = _lastpos;
else
_tab.set(position);
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 '@': // Escape for @
_row[position] = '@';
_attr[position] = _currentstyle;
_cols[position++] = _currentcolor;
break;
case '#':
case '<':
case '>':
// printer MUST handle them
{
const int n = (c == '#') ? 5 : ((c == '>') ? 10 : 8);
_row[position] = '@';
_attr[position] = _currentstyle;
_cols[position++] = _currentcolor;
for (int j = 1; j < n; j++)
{
_row[position] = c;
_attr[position] = _currentstyle;
_cols[position++] = _currentcolor;
}
}
break;
case 'T':
_tab.set(position);
break;
case 'B':
_currentstyle = boldstyle;
break;
case 'I':
_currentstyle = italicstyle;
break;
case 'U':
_currentstyle = underlinedstyle;
break;
case 'R':
_currentstyle = normalstyle;
break;
case 'F':
{
const int f = i;
for ( ; str[i] && str[i] != ']'; i++);
TString name = &str[f+2];
name.cut(i-f-2);
name.insert("i{"); name << '}';
if (_images == NULL) _images = new TToken_string;
_images->add(name);
}
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 >= MAX_PR_WIDTH)
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;
_tab.set(position);
}
else if (toupper (c) == 'J')
{
if (pp + position >= MAX_PR_WIDTH)
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;
_tab.set(position);
}
}
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 //////////
void TPrinter::set_printrcd()
{
if (_print_rcd != NULL)
{
xvt_print_destroy(_print_rcd);
_print_rcd = NULL;
_print_rcd_size = 0;
}
bool ok = false;
if (_prname.not_empty())
{
_print_rcd = xvt_print_create_by_name(&_print_rcd_size, _prname);
ok = xvt_print_is_valid(_print_rcd) != 0;
}
if (!ok)
{
_print_rcd = xvt_print_create(&_print_rcd_size);
xvt_print_get_name(_print_rcd, _prname.get_buffer(), _prname.size());
ok = xvt_print_is_valid(_print_rcd) != 0;
}
if (!ok)
error_box(FR("Errore di inizializzazione della stampante %s"), (const char*)_prname);
}
PRINT_RCD* TPrinter::get_printrcd(int *size)
{
if (_print_rcd == NULL)
set_printrcd();
if (size != NULL)
*size = _print_rcd_size;
return _print_rcd;
}
// @doc EXTERNAL
// @mfunc Setta le caratteristiche della stampante leggendole da <p _print_rcd>
void TPrinter::init_formlen(
WINDOW prwin) // @parm Finestra effettiva di stampa (default NULL_WIN)
// @comm Nel caso <p prwin> sia NULL_WIN vengono solamente aggiornati i valori
{
long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution
xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, get_printrcd(), &ph, &pw, &pvr, &phr);
if (pvr > 0)
{
_formlen = int(ph * _lines_per_inch / pvr); // Total number of lines per page
_dots_per_line = int(pvr / _lines_per_inch); // Number of point per line
_vert_offset = (int)(ph - ((long)_formlen * _dots_per_line)) >> 1;
if (prwin != NULL_WIN)
{
// Compute maximum number of chars per line
int mincol = 0,maxcol=MAX_PR_WIDTH;
TString256 spc; spc.fill('m', maxcol);
_formwidth = maxcol;
int w = 0;
while (mincol < maxcol )
{
w = xvt_dwin_get_text_width(prwin, (char*)(const char*)spc, _formwidth);
if (w < pw)
mincol = _formwidth+1;
else
maxcol=_formwidth-1;
_formwidth=(mincol+maxcol)/2;
}
_horz_offset = (_formwidth > 80) ? (int)(pw - w)/2 : 0;
if (_horz_offset < 0)
_horz_offset = 0;
}
else
{
_formwidth = int (pw * (_ch_size * 10 / 12) / phr);
_horz_offset = 0;
}
}
}
TPrinter::TPrinter()
: _vf(NULL), _ch_size (12), _date (TODAY), _multiple_link (FALSE),
_isgraphics (TRUE), _frozen (FALSE), _print_rcd(NULL), _lines_per_inch (6),
_l_offset(0), _c_offset(0), _export_header(FALSE), _export_header_len(0),
_appendfile(FALSE)
{
_footerhandler = _headerhandler = NULL;
_linkhandler = NULL;
_formlen = 66;
_formwidth = 0;
_frompage = 0;
_topage = 0xffff;
_hwformfeed = FALSE;
_currentpage = 1;
_currentrow = 1;
_fp = NULL;
_headersize = 0;
_footersize = 0;
_isopen = FALSE;
// xvt_print_get_default_device(_defPrinter.get_buffer(), _defPrinter.size());
// read configuration file
read_configuration ();
init_formlen ();
set_fincatura("+++++++++-|");
set_fink_mode(TRUE);
_finker = _isgraphics && _fink_mode ? NULL : new TPrint_intersector(_fink, _formlen);
}
// @doc EXTERNAL
// @mfunc Legge la configurazione della stampante
void TPrinter::read_configuration(
const char* parag) // parm Nome del file di configurazione della stampante (default NULL)
// @comm Se <p parag> e' NULL viene letta la configurazione della stamapnte di default.
{
TWait_cursor hourglass;
_config = parag; // Inizializza nome configurazione
if (_config.empty()) // Se non specificata ...
_config = "Printer"; // ... usa configurazione standard
TConfig* iniptr = NULL;
if (_config != "Printer") // Cerca configurazione speciale
{
iniptr = new TConfig(CONFIG_STAMPE, _config);
const int what = iniptr->get_int("Type", NULL, -1, -1);
if (what < 0) // Se configurazione annullata ...
{
delete iniptr; iniptr = NULL;
}
}
if (iniptr == NULL)
iniptr = new TConfig(CONFIG_GUI, "Printer");
const int what = iniptr->get_int("Type", NULL, -1, 4); // Tipo stampante
_prname = iniptr->get("Name", NULL, -1, _defPrinter); // Nome stampante corrente
_printerfile = iniptr->get("File", NULL, -1, ""); // File di stampa
set_fontname(iniptr->get("Font", NULL, -1, XVT_FFN_FIXED)); // Nome del font
_ch_size = iniptr->get_int("Size", NULL, -1, 10); // Dimensione del font
_lines_per_inch = iniptr->get_int("Lines", NULL, -1, 6); // Linee per pollice
set_graphics(iniptr->get_bool("Graphic", NULL, -1, TRUE)); // Grafica attiva
bool read_rcd = FALSE;
const TString& host = iniptr->get("Host");
if (host.not_empty())
{
char hostname[256];
xvt_sys_get_host_name(hostname, sizeof(hostname));
read_rcd = (host == hostname); // Safe to read
if (!read_rcd)
{
read_rcd = yesno_box(FR("Attenzione: le impostazioni della stampante sono relative alla stazione di lavoro %s.\n"
"Si desidera utilizzarle ugualmente sulla stazione %s?"), (const char*)host, hostname);
if (!read_rcd)
{
// Forza la lettura parametri della stampante di default
_prname.cut(0);
set_printrcd();
}
}
}
if (read_rcd)
{
if (_print_rcd != NULL)
xvt_print_destroy(_print_rcd);
_print_rcd = xvt_print_create_by_name(&_print_rcd_size, _prname);
if (xvt_print_is_valid(_print_rcd) && iniptr->exist("rcd", 0))
{
TToken_string s(256);
int i = 0;
for (int index = 0; ; index++)
{
s = iniptr->get("rcd", NULL, index);
if (s.not_empty())
{
byte* rcd = (byte*)_print_rcd;
for (const char* n = s.get(0); n != NULL && i < _print_rcd_size; n = s.get())
rcd[i++] = (byte)atoi(n);
}
else
break;
}
}
if (xvt_print_is_valid(_print_rcd))
{
init_formlen();
xvt_print_get_name(_print_rcd, _prname.get_buffer(), _prname.size());
}
else
{
error_box("Attenzione: la stampante corrente non e' valida.\n"
"Si prega di selezionare e registrare una nuova stampante.");
set_printrcd();
}
}
delete iniptr; iniptr = NULL;
if (_printerfile.empty())
{
_printerfile.tempdir();
_printerfile << SLASH;
}
if (_config == "Printer" || _printertype == winprinter)
{
switch (what)
{
case 1: _printertype = fileprinter; break;
case 2: _printertype = screenvis; break;
case 3: _printertype = exportprinter; break;
default: _printertype = winprinter; break;
}
}
}
void TPrinter::save_configuration()
{
TWait_cursor hourglass;
CHECK(_config.not_empty(), "Invalid printer config");
TConfig prini(_config == "Printer" ? CONFIG_GUI : CONFIG_STAMPE, _config);
prini.set("Type", _printertype); // Tipo stampante
prini.set("Name", _prname); // Nome stampante corrente
prini.set("File", _printerfile); // File di stampa
prini.set("Font", _fontname); // Nome del font
prini.set("Size", _ch_size); // Dimensione del font
prini.set("Lines", _lines_per_inch); // Linee per pollice
prini.set("Graphic", _isgraphics ? "X" : ""); // Grafica attiva
char hostname[256];
xvt_sys_get_host_name(hostname, sizeof(hostname));
prini.set("Host", hostname);
prini.set("User", user());
int n = 0, index = 0;
TToken_string val(256);
int rcdsize;
byte* rcd = (byte*)get_printrcd(&rcdsize);
for (int i = 0; i < rcdsize; i++)
{
val.add((int)rcd[i]);
n++;
if (n == 24)
{
prini.set("rcd", val, NULL, TRUE, index++);
val.cut(n = 0);
}
}
if (n > 0)
prini.set("rcd", val, NULL, TRUE, index);
for (index++; prini.remove("rcd", index); index++);
}
TPrinter::~TPrinter ()
{
if (_print_rcd != NULL)
{
xvt_print_destroy(_print_rcd);
_print_rcd = NULL;
}
// xvt_print_set_default_device(_defPrinter);
}
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));
}
// @doc EXTERNAL
// @mfunc Setta il contenuto di una line dell'header
void TPrinter::setheaderline (
int linetoset, // @parm Numero della linea da settare
TPrintrow * line) // @parm Contenuto della linea dell'header
// @parm const TPrintrow& | line | Indirizzo con il contenuto della
// linea dell'header
// @syntax void setheaderline (int linetoset, TPrintrow* line);
// @syntax void setheaderline (int linetoset, const 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);
}
// @doc EXTERNAL
// @mfunc Setta il contenuto di una line dell'header
void TPrinter::setfooterline (
int linetoset, // @parm Numero della linea da settare
TPrintrow * line) // @parm Contenuto della linea del footer
// @parm const TPrintrow& | line | Indirizzo con il contenuto della
// linea del footer
// @syntax void setfooterline (int linetoset, TPrintrow* line);
// @syntax void setfooterline (int linetoset, const TPrintrow& line);
{
_footer.add (line, linetoset);
}
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;
}
// @doc EXTERNAL
// @mfunc Metodo base per la stampa
//
// @rdesc Ritorna il risulato della stampa:
//
// @flag TRUE | Se la stampa ha avuto successo
// @flag FALSE | Se la stampante non e' attiva
bool TPrinter::printrow(
TPrintrow* rowtoprint) // @parm Riga da stampare
// @comm Se la pagina logica corrente e' precedente alla prima pagina logica o successiva
// all'ultima pagina logica viene ritornato TRUE.
{
if (!isopen ())
return FALSE;
if (_currentpage < _frompage || _currentpage > _topage)
return TRUE;
TString rw (rowtoprint == NULL ? "" : ((_printertype == screenvis || _printertype == winprinter ||
_printertype == exportprinter) ?
rowtoprint->row_codified () :
rowtoprint->row ()));
rw.rtrim ();
int lun = rw.len ();
int idx;
if (_printertype != exportprinter)
{
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(full), idx++);
break;
case '<':
rw.overwrite (_date.string(brief), idx++);
break;
default:
break;
}
}
}
}
if (_printertype == screenvis)
{
if (!_vf->frozen ())
_vf->add_line(rw);
else
_frozen = TRUE;
}
else
{
// add line to txt
if (!_frozen)
_txt.append(rw);
}
return true;
}
word TPrinter::rows_left() const
{
word left = _formlen - _currentrow - _footersize + 1;
if (_currentrow < 2)
left -= _headersize;
return left;
}
// @doc EXTERNAL
// @mfunc Permette di stampare una riga
//
// @rdesc Ritorna il risultato della stampa:
//
// @flag TRUE | Se la stampa ha avuto successo
// @flag FALSE | Se non e' riuscito ad effettuare la stampa
bool TPrinter::print(
TPrintrow& rowtoprint) // @parm Riga da stampare
// @comm Nel caso la riga non ci stia nella pagina logica corrente vengono stampanti il footer
// della pagina corrente e l'header della successiva prima prima della stampa della riga
// vera e propria.
{
bool ok = TRUE;
if (!(_printertype == exportprinter && !_export_header))
{
if (_currentrow > _formlen - _footersize)
ok = printfooter ();
if (ok && _currentrow == 1)
ok = printheader();
}
if (ok)
{
ok = printrow(&rowtoprint);
_currentrow++;
}
return ok;
}
bool TPrinter::printheader()
{
if (_headerhandler)
_headerhandler(*this);
bool ok = TRUE;
int i;
for (i = 0; i < _headersize && ok; i++)
ok = printrow(getheaderline(i));
// _currentrow = _headersize + 1;
_currentrow = i+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));
_currentrow = 1;
_currentpage++;
return ok;
}
// @doc EXTERNAL
// @mfunc Permette di settare il tipo di fincatura
void TPrinter::set_fink_mode(
bool f) // @parm Indica il tipo di fincatura:
//
// @flag TRUE | Fincatura di tipo grafico
// @flag FALSE | Fincatura di tipo testo
// @comm Viene prima controllato che la stampante supporti la modalita' grafica,
// in tal caso, se viene impostato il flag a TRUE e la stampante e' generica
// oppure non ha il flag di stampa elementi grafici attivato, la fincatura sara'
// in modo testo.
{
_fink_mode = f && isgraphics();
}
// @doc EXTERNAL
// @mfunc Permette di saltare alcune righe dalla posizione corrente
//
// @rdesc Ritorna il risulato dell'operazione:
//
// @flag TRUE | Se e' riuscito a saltare le righe
// @flag FALSE | Se non e' riuscito a saltare le righe
bool TPrinter::skip(
int linestoskip) // @parm Vengono accettati solo valori positivi
// @xref <mf TPrinter::jump>
{
CHECK (linestoskip >= 0, "Linestoskip can't be negative");
int jumpline = _currentrow + linestoskip;
return jump(jumpline);
}
// @doc EXTERNAL
// @mfunc Permette di saltare alla riga indicata
//
// @rdesc Ritorna il risultato dell'operazione
//
// @flag TRUE | Se e' riuscito a saltare alla riga
// @flag FALSE | Se non e' riuscito a saltare alla riga o se viene inserito un formfeed
bool TPrinter::jump(
int jumpline) // @parm Numero della riga a cui saltare nella stampa. Vengono accettai
// solo valori positivi
// @comm Nel caso si cerchi di saltare ad una riga superiore alla lunghezza della pagina attiva
// viene inserito un formfeed.
// @xref <mf TPrinter::skip>
{
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 + _export_header_len <= lastrow; _currentrow++)
printrow();
return printfooter();
}
void TPrinter::reset()
{
resetheader();
resetfooter();
_currentpage = 1;
_currentrow = 1;
}
bool TPrinter::open()
{
// xvt_print_set_default_device(_prname);
if (_printertype == screenvis)
{
CHECK(_vf == NULL, "Print preview already open");
_vf = new TViswin (NULL, "Anteprima di stampa", TRUE, TRUE,
_linksdescr.items () > 0);
_vf->open_modal ();
}
else
{
// prepare text object for new text
_txt.destroy();
_txt.interactive(FALSE);
}
_currentrow = 1;
_currentpage = 1;
return _isopen = TRUE;
}
bool TPrinter::set()
{
main_app().disable_menu_item(M_FILE_PG_SETUP);
const TString oldprn = _prname;
int old_rcd_size;
PRINT_RCD* rcd = get_printrcd(&old_rcd_size);
TString oldrcd(old_rcd_size);
memcpy(oldrcd.get_buffer(), rcd, old_rcd_size);
TPrinter_setup_mask mask;
const KEY k = mask.run();
_print_rcd = mask.get_print_rcd(_print_rcd_size);
if (k == K_ESC)
{
xvt_print_destroy(_print_rcd);
_print_rcd = xvt_print_create_by_name(&_print_rcd_size, oldprn);
memcpy(_print_rcd, oldrcd, _print_rcd_size);
}
else
{
_prname = mask.get(MSK_PRINTERS);
switch (atoi (mask.get (MSK_TYPE)))
{
case 1: // file
_printertype = fileprinter;
_printerfile = mask.get (MSK_FILENAME);
break;
case 2: // video
_printertype = screenvis; break;
default: // stampante
_printertype = winprinter; break;
}
set_fontname(mask.get(MSK_FONT));
const int cs = mask.get_int(MSK_SIZE);
if (cs > 4) _ch_size = cs;
_lines_per_inch = mask.get_int (MSK_LINES);
_isgraphics = mask.get_bool (MSK_ISGRAPHICS);
init_formlen ();
if (k == K_INS)
save_configuration();
}
main_app().enable_menu_item (M_FILE_PG_SETUP);
return TRUE;
}
// @doc EXTERNAL
// @mfunc Inserisce un file di export fatto da un'altra printer
void TPrinter::merge_export_file(
const char* file,
bool header) // @parm Indica se gli header sono presenti nel file:
//
// @flag TRUE | Gli header sono nel file e quindi non vengono stampanti (default)
// @flag FALSE | Gli header non sono nel file e quindi vengono stampanti
// @comm Vengono inseriti nel file di export i formati e tutto il resto. Vengono ignorati gli
// header supponendo che siano gia' presenti nel file
{
TTextfile txt(file);
for (long i = 0; i < txt.lines(); i++)
{
TPrintrow* p = new TPrintrow();
p->put(txt.line_formatted(i));
if (header) printrow(p);
else print(*p);
}
}
// @doc EXTERNAL
// @mfunc Crea un segnalibro
//
// @rdesc Ritorna l'identificatore del segnalibro creato
int TPrinter::set_bookmark(
const char* txt, // @parm Nome del segnalibro da creare
int father) // @parm Identificatore del segnalibro padre a cui collegare quello
// da creare
{
if (_printertype == screenvis)
{
BkDef* bkd = new BkDef;
bkd->_row = (_currentrow + ((_currentpage - 1)*_formlen)) - 1;
bkd->_father_id = father;
bkd->_id = _bookmarks.items() + 1;
bkd->_txt = txt;
_bookmarks.add(bkd);
return _bookmarks.items();
}
return 0;
}
void TPrinter::print_txt(TTextfile& txt)
{
if (txt.lines() > 0)
{
TPrint_txt_info what(txt);
if (what.edit())
{
xvt_print_open();
xvt_print_start_thread(start_print, long(&what));
xvt_print_close();
}
}
}
void TPrinter::close ()
{
if (isopen() && // la stampante era aperta e
_currentrow >1 && // .. ho stampato qualcosa ...
_footersize>0 ) // ... c'<27> footer da stampare
formfeed();
if (_fp)
{
fclose (_fp);
_fp = NULL;
}
if (_printertype == screenvis)
{
_vf->close_print();
const KEY key = _vf->run ();
if (_vf->is_open ()) _vf->close_modal ();
_bookmarks.destroy();
if (key == K_CTRL+'S')
{
_isopen = FALSE;
_currentrow = _currentpage = 1;
print_txt(_vf->text());
}
delete _vf; _vf = NULL;
}
else if (_printertype == exportprinter)
{
if (_exportfile.not_empty() && _txt.lines() > 0L)
{
ofstream txt(_exportfile);
for (long i = 0; i < _txt.lines(); i++)
txt << _txt.line_formatted(i) << '\n';
txt.close();
}
}
else if (_printertype == winprinter && _txt.lines() > 0L)
{
print_txt(_txt);
}
else if (_printertype == fileprinter)
{
FILE* fp = fopen(_printerfile, _appendfile ? "a" : "w");
if (fp == NULL)
{
error_box(FR("Impossibile aprire il file %s"), (const char*)_printerfile);
return;
}
for (long i = 0; i < _txt.lines(); i++)
fprintf(fp,"%s\n", _txt.line(i));
fclose(fp);
message_box(FR("Stampa su file terminata. Nome archivio: %s"),(const char *)_printerfile);
}
if (_finker)
{
delete _finker;
_finker = NULL;
}
// Dealloca sfondi ormai inutili
_backgrounds.destroy();
freeze (FALSE);
_isopen = FALSE;
}
//
// TFile_printer
//
#include <bagn004.h>
const long disk_sizes[] = { 360000L, 1200000L, 720000L, 1400000L, 2880000L };
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;
_label_fissata = TRUE;
}
void TFile_printer::open()
{
}
void TFile_printer::close ()
{
}
bool TFile_printer::genera_dischetti ()
{
int r;
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!");
// copia il file sul dischetto
fcopy ((const char *) &_tmp_files[i], (const char *) _drive);
}
return TRUE;
}
TFile_printer::~TFile_printer ()
{
}
bool TFile_printer::set ()
{
TMask m ("bagn004");
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);
const bool ok = m.run () == K_ENTER;
if (ok)
{
f = atoi(m.get(F_FORMATO_DISCO));
_drive = m.get(F_DRIVE);
_file = m.get(F_FILE_DESTINAZIONE);
_label = m.get(F_LABEL);
_size = disk_sizes[f];
_num_rec_volume = int ((_size / _len_rec) - _num_rec_testa_coda);
}
return ok;
}
const char* TPrinter::background_chars(int l) const
{
return _finker == NULL ? "" : _finker->get_chars(l);
}
///////////////////////////////////////////////////////////
// Calcolo dimensione font
///////////////////////////////////////////////////////////
struct font_data
{
TString _name;
int _size;
int _columns;
};
HIDDEN BOOLEAN calc_font_callback(long data)
{
font_data& fd = *(font_data*)data;
// Create print window
WINDOW win = xvt_print_create_win(printer().get_printrcd(), "Calcolo font");
if (win != NULL_WIN)
{
long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution
xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, printer().get_printrcd(), &ph, &pw, &pvr, &phr);
TString test(fd._columns);
test.fill('M', fd._columns);
int size;
for (size = fd._size; size > 0; size--)
{
// Set print font
xvt_set_font(win, fd._name, XVT_FS_NONE, size);
const int w = xvt_dwin_get_text_width(win, (char*)(const char*)test, fd._columns);
if (w <= pw)
break;
}
if (size > 0)
fd._size = size;
xvt_vobj_destroy(win);
}
return win != NULL_WIN;
}
int TPrinter::calc_font_size(int columns) const
{
font_data fd;
fd._name = fontname();
fd._size = get_char_size();
fd._columns = columns;
xvt_print_open();
xvt_print_start_thread(calc_font_callback, (long)&fd);
xvt_print_close();
return fd._size;
}
HIDDEN BOOLEAN calc_cols_callback(long data)
{
int &numcols=*(int *)data;
// Create print window
WINDOW win = xvt_print_create_win(printer().get_printrcd(), "Calcolo numero colonne");
if (win != NULL_WIN)
{
long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution
xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, printer().get_printrcd(), &ph, &pw, &pvr, &phr);
xvt_set_font(win, printer().fontname(), XVT_FS_NONE, printer().get_char_size());
// Compute maximum number of chars per line
int mincol = 0,maxcol=MAX_PR_WIDTH;
TString spc(maxcol,'M' );
numcols = maxcol;
int w;
while (mincol < maxcol )
{
w = xvt_dwin_get_text_width(win, (char*)(const char*)spc, numcols);
if (w < pw)
mincol = numcols+1;
else
maxcol=numcols-1;
numcols=(mincol+maxcol)/2;
}
xvt_vobj_destroy(win);
}
return win != NULL_WIN;
}
// Funzione chiamata solo da sv1200, ma non si capisce perche' non usi la formwidth()
int TPrinter::calc_num_cols() const
{
int numcols;
xvt_print_open();
xvt_print_start_thread(calc_cols_callback, (long)&numcols);
xvt_print_close();
return numcols;
}