campo-sirio/include/printer.cpp
guy 76d2e43293 default.url Aggiunto supporto per l'italiano
printer.cpp    Vietao il registra di configurazioni utente
text.cpp       Modificati include inutili
text.h         Cambiati valori di un enum per compatibilita con release 4.5
viswin.cpp     Tolto bottone di chiusura
window.cpp     Aggiunti controlli sulla chiusura/distruzione delle finestre.


git-svn-id: svn://10.65.10.50/trunk@3804 c028cbd2-c16b-5b4b-a496-9718f37d4682
1996-10-21 10:42:45 +00:00

2197 lines
54 KiB
C++
Executable File

#include <stdlib.h>
#define STRICT
#define XVT_INCL_NATIVE
#include <xvt.h>
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
#include <strstrea.h>
#else
#include <strstream.h>
#endif
#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 <applicat.h>
#include <config.h>
#include <execp.h>
#include <golem.h>
#include <mask.h>
#include <printer.h>
#include <printwin.h>
#include <urldefid.h>
#include <utility.h>
#include <viswin.h>
#include <bagn001a.h>
HIDDEN TPrinter* _printer = NULL;
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);
for (int 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)
{
for (int 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();
}
}
///////////////////////////////////////////////////////////
// PrDesc
///////////////////////////////////////////////////////////
struct PrDesc
{
TTextfile *_txt;
PRINT_RCD *_prcd;
bool _graphics;
int _formlen;
int _charsize;
int _lines_per_inch;
}
PrintWhat;
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
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')
{
if (buf[i+1] != '\0') buf[i] = '|';
else break;
}
}
t = buf;
delete buf;
}
BOOLEAN XVT_CALLCONV1 TPrinter::start_winprint (long data)
{
PrDesc *pd = (PrDesc *) data;
TTextfile& txt = *(pd->_txt);
TPrintwin pw(txt);
pw.do_print();
return pw.aborted();
}
#endif
// utils del caz
HIDDEN int read_int (const char *s, int &n, int &cnt)
{
char nbuf[16];
while (!isdigit (s[cnt]))
cnt++;
for (int 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, TArray& background)
{
TString_array pix;
char op, ch;
int x1, x2, y1, y2;
int id, cnt = 0;
TToken_string tt;
TFilename bmp;
if (!_isgraphics && _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)
{
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
{
TString* r = new TString(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 = (TString&)background[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)
{
_background.destroy();
_bg_desc = b;
if (b != NULL)
parse_background(_bg_desc, _background);
}
bool printers_on_key(TMask_field & f, KEY key);
// fv support structs for config
// @doc INTERNAL
// @mfunc Legge la descrizione della stampante dal file
//
// @rdesc Ritorna il risultato dell'operazione:
//
// @flag TRUE | Se e' riuscito a leggere la descrizione della stampante
// @flag FALSE | Se non e' riuscito a leggere la descrizione della stampante
bool PrinterDef::read(
const char *name, // @parm Nome della stampante di cui cercarne la descrizione
FILE * fd) // @parm Puntatore al file contenente la descrizione
{
_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 ( code.get() );
_codes.add ( 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)); // Azzera testo
memset(_attr, normalstyle, sizeof (_attr)); // Azzera stile
_tab.reset(); // Azzera tabulazioni
_currentcolor = 'w';
_currentcolor <<= 8;
_currentcolor += 'n';
for (int i = 0; i < MAXSTR; 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 last = 0, k = 0, len = -1;
for (int i = 0; i < _row.size(); i++)
if (_row[i] > ' ') len = i;
for (i = 0; i < _row.size(); i++)
{
if (_tab[i])
{
__tmp_string[k++] = '@';
__tmp_string[k++] = 't';
}
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 && i <= len)
{
__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];
if (_row[i] > ' ') last = k;
}
__tmp_string[last] = '\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;
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 '#':
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 '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;
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;
_tab.set(position);
}
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;
_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 //////////
HIDDEN bool printer_handler (TMask_field & f, KEY key)
{
if (key == K_SPACE)
{
TToken_string pn1(10), pn2(80);
const PrinterDef & def = 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_CODES)).replace_items (pn1, pn2);
}
return TRUE;
}
void TPrinter::set_printrcd()
{
if (_print_rcd != NULL)
xvt_print_destroy(_print_rcd);
_print_rcd = xvt_print_create(&_print_rcd_size);
}
PRINT_RCD* TPrinter::get_printrcd(int *size)
{
if (_print_rcd == NULL || !xvt_print_is_valid(_print_rcd))
set_printrcd();
if (size != NULL) *size = _print_rcd_size;
return _print_rcd;
}
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
// @doc EXTERNAL
// @mfunc Setta le caratteristiche della stampante leggendole da <p _print_rcd>
void TPrinter::set_win_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)
{
TString256 spc; spc.spaces(256); // Compute maximun number of chars per line
int w = 0;
for (_formwidth = 256; _formwidth >= 80; _formwidth--)
{
w = xvt_dwin_get_text_width(prwin, (char*)(const char*)spc, _formwidth);
if (w < pw) break;
}
_horz_offset = (_formwidth > 80) ? (int)(pw - w)/2 : 0;
}
else
{
_formwidth = 256;
_horz_offset = 0;
}
}
else
warning_box ("Il driver della stampante non e' valido.\n"
"Non stampare prima di averlo reinstallato");
}
// Handler della maschera di setup
HIDDEN bool set_windows_print_device (TMask_field& f, KEY key)
{
TMask& m = f.mask();
if (key == K_TAB && (f.focusdirty() || !m.is_running()))
{
main_app().begin_wait();
TPrinter& pr = printer();
TToken_string& pn = pr.getprinternames ();
TString80 pdev (pn.get(atoi (f.get()))); // Nome stampante corrente
char szDevice[80];
GetProfileString ("devices", pdev, "", szDevice, sizeof (szDevice));
pdev << "," << szDevice;
// scrivi (e semmai lo si risistema poi)
WriteProfileString("windows", "device", pdev);
if (m.is_running())
{
pr.set_printrcd();
pr.set_win_formlen();
}
const int MAX_FAMILIES = 128;
char* family[MAX_FAMILIES];
const int num_families = (int)xvt_fmap_get_families(pr.get_printrcd(), family, MAX_FAMILIES);
TToken_string pn1(256), pn2(256);
// const int MAXSIZES = 16;
// long sizes[MAXSIZES];
// BOOLEAN scalable;
for (int i = 0; i < num_families; i++)
{
pn1.add(family[i]);
pn2.add(family[i]);
xvt_mem_free(family[i]);
}
TList_field& lst = (TList_field&)m.field(MSK_FONT);
lst.replace_items(pn1, pn2);
m.set(MSK_FONT, printer().fontname(), TRUE);
main_app().end_wait();
}
return TRUE;
}
HIDDEN bool font_handler(TMask_field& f, KEY key)
{
TMask& m = f.mask();
if (key == K_TAB && (f.focusdirty() || !m.is_running()))
{
main_app().begin_wait();
const char* family = f.get();
const int MAXSIZES = 16;
long sizes[MAXSIZES];
BOOLEAN scalable;
const int num_sizes = (int)xvt_fmap_get_family_sizes(printer().get_printrcd(),
(char*)family, sizes, &scalable, MAXSIZES);
TToken_string pn1(80), pn2(80);
if (scalable)
{
for (int i = 4; i <= 32; i++)
{
pn1.add(i);
pn2.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());
pn2 = pn1;
}
TList_field& lst = (TList_field&)f.mask().field(MSK_SIZE);
lst.replace_items(pn1, pn2);
lst.set(format("%d", printer().get_char_size()));
main_app().end_wait();
}
return TRUE;
}
#endif
HIDDEN char defPrinter[80];
TPrinter::TPrinter()
: _date (TODAY), _multiple_link (FALSE), _frozen (FALSE), _isgraphics (TRUE),
_lines_per_inch (6), _ch_size (12), _ncopies(1), _export_header(FALSE),
_export_header_len(0), _vf(NULL), _l_offset(0), _c_offset(0)
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
, _print_rcd(NULL)
#endif
{
_footerhandler = _headerhandler = NULL;
_linkhandler = NULL;
_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;
_multiple_copies = main_app().class_id() == CLASS_PRINT_APPLICATION;
// read configuration file
read_configuration ();
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
// xvt_print_open ();
set_win_formlen ();
// char szDevice[50];
// get default printer driver
GetProfileString ("windows", "device", ",,,", defPrinter, sizeof(defPrinter));
TToken_string& pn2 = getprinternames(); // get printer names
CHECK(_curprn >= 0, "Can't find printer ");
if (_curprn >= pn2.items())
{
TToken_string pdev (defPrinter, ',');
// GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice));
// pdev.add(szDevice);
const TString80 p1(pdev.get(0)); // current printer
_curprn = pn2.get_pos(p1);
}
else
{
TString80 pdev(pn2.get(_curprn)); // Nome stampante corrente
char szDevice[80];
GetProfileString ("devices", pdev, "", szDevice, sizeof (szDevice));
pdev << "," << szDevice;
// scrivi (e semmai lo si risistema poi)
WriteProfileString("windows", "device", pdev);
}
set_fincatura("+++++++++-|");
#else
_isgraphics = FALSE;
#endif
_finker = _isgraphics ? NULL : new TPrint_intersector(_fink, _formlen);
}
bool TPrinter::isfax() const
{
bool fax = _printertype == winprinter || _printertype == screenvis;
if (fax)
{
const char* name = (const char*)((TPrinter*)this)->get_printrcd() + 4;
TToken_string p(256, ',');
GetProfileString ("devices", name, "", (char*)(const char*)p, p.size());
const char * driver = p.get(1);
fax = driver != NULL && stricmp(driver, "EASYFAX") == 0;
}
return fax;
}
TToken_string& TPrinter::getprinternames ()
{
// per ora va solo in windows
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
if (_printer_names.empty())
_get_windows_printer_names(_printer_names);
#endif
return _printer_names;
}
// @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.
{
main_app().begin_wait();
#if XVT_OS == XVT_OS_SCOUNIX
const char* const config = "printer.ini";
FILE *cnfp = fopen (config, "r");
if (cnfp == NULL)
fatal_box ("Impossibile aprire il file %s", 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);
#endif
_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_USER, "Printer");
const int what = iniptr->get_int("Type", NULL, -1, 0); // Tipo stampante
_curprn = iniptr->get_int("Number", NULL, -1, 0); // Numero stampante corrente
_printerfile = iniptr->get("File", NULL, -1, ""); // File di stampa
_curcode = iniptr->get_int("Codes", NULL, -1, 0); // Codici di stampa
_fontname = iniptr->get("Font", NULL, -1, XVT_FFN_FIXED); // Nome del font
_ch_size = iniptr->get_int("Size", NULL, -1, 12); // Dimensione del font
_lines_per_inch = iniptr->get_int("Lines", NULL, -1, 6); // Linee per pollice
_isgraphics = iniptr->get_bool("Graphic", NULL, -1, FALSE); // Grafica attiva
if (iniptr->exist("rcd", 0))
{
int size, i = 0;
byte* rcd = (byte*)get_printrcd(&size);
TToken_string s(256);
for (int index = 0; i < size; index++)
{
s = iniptr->get("rcd", NULL, index);
for (const char* n = s.get(0); n; n = s.get())
rcd[i++] = (byte)atoi(n);
}
}
delete iniptr; iniptr = NULL;
if (_printerfile.empty())
{
_printerfile.tempdir();
#if XVT_OS == XVT_OS_SCOUNIX
_printerfile << '/';
#else
_printerfile << '\\';
#endif
}
if (_config == "Printer" || _printertype == winprinter)
switch (what)
{
case 0:
case 5:
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
_printertype = winprinter;
#else
PrinterDef & def = (PrinterDef &) get_description (_curprn);
switch (atoi (def._printertype))
{
case 1:
_printertype = localprinter;
break;
case 2:
_printertype = spoolprinter;
break;
default:
_printertype = normprinter;
break;
}
#endif
break;
case 1: // file
_printertype = fileprinter;
break;
case 4: // video
_printertype = screenvis;
_curcode = 0;
break;
case 6: // export
_printertype = export;
_curcode = 0;
break;
default:
break;
}
main_app().end_wait();
}
void TPrinter::save_configuration()
{
main_app().begin_wait();
CHECK(_config.not_empty(), "Invalid printer config");
TConfig prini(_config == "Printer" ? CONFIG_USER : CONFIG_STAMPE, _config);
prini.set("Type", _printertype); // Tipo stampante
prini.set("Number", _curprn); // Numero stampante corrente
prini.set("File", _printerfile); // File di stampa
prini.set("Codes", _curcode); // Codici 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
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);
main_app().end_wait();
}
TPrinter::~TPrinter ()
{
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
if (_print_rcd != NULL)
{
xvt_print_destroy(_print_rcd);
_print_rcd = NULL;
}
WriteProfileString("windows", "device", defPrinter);
// xvt_print_close();
#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));
}
// @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 == export ?
rowtoprint->row_codified () :
rowtoprint->row ()));
rw.rtrim ();
int lun = rw.len ();
int idx;
if (_printertype != export)
{
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 (format("%10s",_date.string (full)), idx++);
break;
case '<':
rw.overwrite (format("%8s",_date.string (brief)), idx++);
break;
default:
break;
}
}
}
}
if (_printertype == screenvis)
{
if (!_vf->frozen ())
_vf->add_line(rw);
else
_frozen = TRUE;
return TRUE;
}
if (_printertype == winprinter || _printertype == export)
{
// add line to txt
if (!_frozen)
_txt.append(rw);
return TRUE;
}
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
if (_printertype == fileprinter)
{
// add line to txt
if (!_frozen)
_txt.append (rw);
return TRUE;
}
#else
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);
#endif
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 == export && !_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;
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_SCOUNIX
if (ok)
printformfeed();
#endif
_currentrow = 1;
_currentpage++;
return ok;
}
// @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 accettai solo valori positivi
// @xref <mf TPrinter::jump>
{
int jumpline;
CHECK (linestoskip >= 0, "Linestoskip can't be negative");
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::printformfeed()
{
#if XVT_OS == XVT_OS_SCOUNIX
const PrinterDef & pd = get_description(_curprn);
if (_printertype != screenvis && _hwformfeed)
fprintf(_fp, "%s",(const char *)pd._ffcode);
#endif
return TRUE;
}
bool TPrinter::open()
{
#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)
{
CHECK(_vf == NULL, "Print preview already open");
_vf = new TViswin (NULL, "Anteprima di stampa", TRUE, TRUE,
_linksdescr.items () > 0);
_vf->open_modal ();
}
else if (_printertype == winprinter || _printertype == export
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|| _printertype == fileprinter
#endif
)
{
// prepare text object for new text
_txt.destroy();
_txt.interactive(FALSE);
if (isfax())
start_fax_server();
}
#if XVT_OS==XVT_OS_SCOUNIX
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);
}
}
#endif
_currentrow = 1;
_currentpage = 1;
return _isopen = TRUE;
}
bool TPrinter::set()
{
main_app().disable_menu_item (M_FILE_PG_SETUP);
TMask mask("bagn001a");
TToken_string pn1(50), pn2(100);
int i;
mask.set(MSK_FILENAME, _printerfile);
mask.set(MSK_NPAGES, _ncopies);
const bool can_save = _config == "Printer";
mask.enable(DLG_OK, can_save);
mask.enable(DLG_SAVEREC, can_save);
#if XVT_OS == XVT_OS_WIN
pn2 = getprinternames();
char old_default[80];
GetProfileString ("windows", "device", ",,,", old_default, sizeof(old_default));
const int np = pn2.items();
for (i = 0; i < np; i++)
pn1.add(i);
TList_field& plst = (TList_field&)mask.field (MSK_PRINTERS);
plst.replace_items(pn1, pn2); // Genera printer list
mask.set(MSK_PRINTERS, _curprn); // Genera font list
set_windows_print_device(mask.field(MSK_PRINTERS), K_TAB);
font_handler(mask.field(MSK_FONT),K_TAB);
mask.set(MSK_FONT, _fontname); // Genera size list
mask.set(MSK_SIZE, _ch_size);
mask.set_handler (MSK_PRINTERS, set_windows_print_device);
mask.set_handler (MSK_FONT, font_handler);
mask.set(MSK_LINES, _lines_per_inch);
mask.set(MSK_ISGRAPHICS, _isgraphics ? "X" : "");
if (!_multiple_copies)
mask.hide(MSK_NPAGES);
if (_printertype == fileprinter)
mask.set (MSK_TYPE, "1");
else if (_printertype == screenvis)
mask.set (MSK_TYPE, "2");
else
mask.set (MSK_TYPE, "0");
KEY k;
int oldprn = _curprn;
s_printrcd * rcd = get_printrcd();
TString oldrcd(_print_rcd_size);
memcpy((char *) (const char *) oldrcd, rcd, _print_rcd_size);
while ((k = mask.run ()) != K_ESC && k != K_ENTER && k != K_INS)
{
if (k == DLG_SETPRINT)
{
// l'handler setta default di windows a quella nel listbox e ribecca l'rcd
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
if (xvt_dm_post_page_setup(get_printrcd()))
{
// see if user has changed printer
// determine index of currently selected printer
// ACTHUNG! Deep hacking of XVT internals! NON PORTABLE!
const char* name = (const char *)(_print_rcd + 4);
_curprn = pn2.get_pos(name);
CHECKS(_curprn >= 0, "Can't find printer ", name);
mask.set(MSK_PRINTERS, pn1.get(_curprn));
// set_win_formlen(); // Update dimensions
}
else
beep ();
#endif
}
}
if (k == K_ESC)
{
// riaggiusta stampante default windows come prima
// curprn e rcd sono quelle di prima
main_app().enable_menu_item(M_FILE_PG_SETUP);
WriteProfileString("windows", "device", old_default);
_curprn = oldprn;
s_printrcd * rcd = get_printrcd();
memcpy(rcd, (const char *) oldrcd, _print_rcd_size);
set_win_formlen();
return FALSE;
}
_curprn = atoi(mask.get(MSK_PRINTERS));
_ncopies = atoi (mask.get (MSK_NPAGES));
switch (atoi (mask.get (MSK_TYPE)))
{
case 0: // stampante
_printertype = winprinter;
break;
case 1: // file
_printertype = fileprinter;
_printerfile = mask.get (MSK_FILENAME);
_curcode = atoi (mask.get (MSK_CODES));
break;
case 2: // video
_printertype = screenvis;
_curcode = 0;
break;
}
_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);
set_win_formlen ();
#endif
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 XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
if (txt.lines() > 0)
{
PrintWhat._prcd = _print_rcd;
PrintWhat._txt = &txt;
PrintWhat._graphics = _isgraphics;
PrintWhat._charsize = _ch_size;
xvt_print_open();
xvt_print_start_thread (start_winprint, (long) (&PrintWhat));
xvt_print_close();
}
#endif
}
void TPrinter::close ()
{
const bool isfirstpage = (_currentpage == 1 && _frompage == 0) ||
(_currentpage <= _frompage);
if (isopen() && (!isfirstpage || _currentrow > _headersize) &&
(_printertype != screenvis && _printertype != winprinter
&& _printertype != export))
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();
freeze (FALSE);
if (key == K_CTRL+'S')
{
_isopen = FALSE;
_currentrow = _currentpage = 1;
print_txt(_vf->text());
}
delete _vf; _vf = NULL;
}
else if (_printertype == export)
{
if (_exportfile.not_empty() && _txt.lines() > 0L)
{
ofstream txt((const char*)_exportfile);
for (long i = 0; i < _txt.lines(); i++)
txt << _txt.line_formatted(i) << '\n';
txt.close();
}
}
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
else if (_printertype == winprinter && _txt.lines() > 0L)
{
print_txt(_txt);
}
else if (_printertype == fileprinter)
{
FILE* fp = fopen(_printerfile, "w");
if (fp == NULL)
{
error_box("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("Stampa su file terminata. Nome archivio: %s",(const char *)_printerfile);
}
#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
}
if (_finker)
{
delete _finker;
_finker = NULL;
}
_isopen = FALSE;
}
//
// TFile_printer
//
#include <bagn004.h>
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
const char* const FORMAT_COMMAND = "FORMAT";
#else
const char* const FORMAT_COMMAND = "dosformat -fq";
#endif
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;
_formatta = FALSE;
_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!");
// e eventualmente lo formatta
if (_formatta)
{
TString80 dep;
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 ()
{
}
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);
_formatta = (bool)(m.get(F_FORMATTA) == "X");
_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);
}
///////////////////////////////////////////////////////////
// Gestione fax
///////////////////////////////////////////////////////////
bool TPrinter::start_fax_server() const
{
TDDE dde;
return dde.execute("EASYFAX", "FAX", "", "bafax");
}
void TPrinter::close_fax_server() const
{
TDDE dde;
const bool running = dde.initiate("EASYFAX", "FAX");
if (running)
dde.execute("[FileClose]");
}
bool TPrinter::send_fax(const char* tipo, const char* codice)
{
bool ok = isopen() && isfax();
if (ok)
{
if (tipo && codice)
{
TString cmd(80);
cmd << "[SetRecipient(" << tipo << ',' << codice << ")]";
TDDE dde;
dde.execute("EASYFAX", "FAX", cmd, "bafax");
}
close(); // termina la stampa corrente e la spedisce
open(); // riapre la stampante
}
return ok;
}