bool raiseToNextBR(Class2Params&);
bool sendTraining(Class2Params&, int, Status& eresult);
bool sendTCF(const Class2Params&, u_int ms);
- bool sendPage(TIFF* tif, Class2Params&, u_int, u_int, Status& eresult);
+ bool sendPage(TIFF* tif, Class2Params&, u_int, u_int, Status& eresult, bool cover);
bool sendPageData(u_char* data, u_int cc, const u_char* bitrev, bool ecm, Status& eresult);
bool sendRTC(Class2Params params, u_int ppmcmd, uint32 rowsperstrip, Status& eresult);
bool sendPPM(u_int ppm, HDLCFrame& mcf, Status& eresult);
void sendBegin();
void sendSetupPhaseB(const fxStr& pwd, const fxStr& sub);
FaxSendStatus sendPhaseB(TIFF* tif, Class2Params&, FaxMachineInfo&,
- fxStr& pph, Status& eresult, u_int& batched);
+ fxStr& pph, Status& eresult, u_int& batched, PageType pt);
void sendEnd();
void sendAbort();
* Send protocol.
*/
#include "Sys.h"
+#include "SystemLog.h"
#include "Class1.h"
#include "ModemConfig.h"
#include "HDLCFrame.h"
*/
FaxSendStatus
Class1Modem::sendPhaseB(TIFF* tif, Class2Params& next, FaxMachineInfo& info,
- fxStr& pph, Status& eresult, u_int& batched)
+ fxStr& pph, Status& eresult, u_int& batched, PageType pt)
{
int ntrys = 0; // # retraining/command repeats
bool morePages = true; // more pages still to send
/*
* Transmit the facsimile message/Phase C.
*/
- if (!sendPage(tif, params, decodePageChop(pph, params), cmd, eresult)) {
+ if (!sendPage(tif, params, decodePageChop(pph, params), cmd, eresult, pt == PAGE_COVER)) {
if (hadV34Trouble) {
protoTrace("The destination appears to have trouble with V.34-Fax.");
return (send_v34fail);
protoTrace("Skipping page %d", FaxModem::getPageNumberOfCall());
signalRcvd = FCF_MCF;
}
-
+logDebug(" * * * PAGE SENT: %s", pt == PAGE_NORMAL ? "PAGE_NORMAL" :
+ (pt == PAGE_COVER ? "PAGE_COVER" : "PAGE_SKIP"));
int ncrp = 0;
u_int ppr;
do {
/* fall thru... */
case FCF_MCF: // ack confirmation
case FCF_PIP: // ack, w/ operator intervention
- countPage(cmd == PPH_SKIP); // bump page count
- if (cmd != PPH_SKIP || conf.countSkippedPages)
- notifyPageSent(tif); // update server
+ countPage(cmd == PPH_SKIP ? PAGE_SKIP : pt);// bump page count
+ notifyPageSent(tif, cmd == PPH_SKIP ? PAGE_SKIP : pt); // update server
if (pph[2] == 'Z')
pph.remove(0,2+5+1);// discard page-chop+handling info
else
// ignore error and try to send next page
// after retraining
params.br = (u_int) -1; // force retraining above
- countPage(); // bump page count
- notifyPageSent(tif); // update server
+ countPage(pt); // bump page count
+ notifyPageSent(tif, pt); // update server
if (pph[2] == 'Z')
pph.remove(0,2+5+1);// discard page-chop+handling info
else
* Send a page of data.
*/
bool
-Class1Modem::sendPage(TIFF* tif, Class2Params& params, u_int pageChop, u_int ppmcmd, Status& eresult)
+Class1Modem::sendPage(TIFF* tif, Class2Params& params, u_int pageChop, u_int ppmcmd, Status& eresult, bool cover)
{
if (params.ec == EC_DISABLE) { // ECM does it later
/*
u_char* dp;
if (doTagLine) {
u_long totbytes = totdata;
- dp = imageTagLine(data+ts, fillorder, params, totbytes);
+ dp = imageTagLine(data+ts, fillorder, params, totbytes, cover);
// Because the whole image is processed with MMR,
// totdata is then determined during encoding.
totdata = (params.df == DF_2DMMR) ? totbytes : totdata+ts - (dp-data);
// transmission support
bool dataTransfer();
bool sendRTC(Class2Params params);
- bool sendPageData(TIFF* tif, u_int pageChop);
+ bool sendPageData(TIFF* tif, u_int pageChop, bool cover);
- virtual bool sendPage(TIFF* tif, u_int pageChop) = 0;
+ virtual bool sendPage(TIFF* tif, u_int pageChop, bool cover) = 0;
virtual bool pageDone(u_int ppm, u_int& ppr) = 0;
// reception support
const AnswerMsg* findAnswer(const char*);
CallStatus dialResponse(Status& eresult);
FaxSendStatus getPrologue(Class2Params&, bool&, Status& eresult, u_int&);
FaxSendStatus sendPhaseB(TIFF* tif, Class2Params&, FaxMachineInfo&,
- fxStr& pph, Status& eresult, u_int& batched);
+ fxStr& pph, Status& eresult, u_int& batched, PageType pt);
void sendAbort();
// receive support
* Send a page of data using the ``stream interface''.
*/
bool
-Class20Modem::sendPage(TIFF* tif, u_int pageChop)
+Class20Modem::sendPage(TIFF* tif, u_int pageChop, bool cover)
{
/*
* Support MT5634ZBA-V92 real-time fax compression conversion:
protoTrace("SEND begin page");
if (flowControl == FLOW_XONXOFF)
setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
- bool rc = sendPageData(tif, pageChop);
+ bool rc = sendPageData(tif, pageChop, cover);
if (!rc)
abortDataTransfer();
else if( conf.class2SendRTC )
class Class20Modem : public Class2Modem {
protected:
// transmission support
- bool sendPage(TIFF* tif, u_int pageChop);
+ bool sendPage(TIFF* tif, u_int pageChop, bool cover);
bool pageDone(u_int ppm, u_int& ppr);
void abortDataTransfer();
* Send a page of data using the ``stream interface''.
*/
bool
-Class2ErsatzModem::sendPage(TIFF* tif, u_int pageChop)
+Class2ErsatzModem::sendPage(TIFF* tif, u_int pageChop, bool cover)
{
protoTrace("SEND begin page");
if (flowControl == FLOW_XONXOFF)
setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
- bool rc = sendPageData(tif, pageChop);
+ bool rc = sendPageData(tif, pageChop, cover);
if (rc && conf.class2SendRTC)
rc = sendRTC(params);
if (rc)
class Class2ErsatzModem : public Class2Modem {
protected:
// transmission support
- bool sendPage(TIFF* tif, u_int pageChop);
+ bool sendPage(TIFF* tif, u_int pageChop, bool coverpage);
bool pageDone(u_int ppm, u_int& ppr);
bool sendEOT();
*/
FaxSendStatus
Class2Modem::sendPhaseB(TIFF* tif, Class2Params& next, FaxMachineInfo& info,
- fxStr& pph, Status& eresult, u_int& batched)
+ fxStr& pph, Status& eresult, u_int& batched, PageType pt)
{
int ntrys = 0; // # retraining/command repeats
u_int ppm, previousppm = 0;
goto failed;
if (ppm == PPH_SKIP)
protoTrace("Skiping page %d", FaxModem::getPageNumberOfCall());
- if (ppm == PPH_SKIP || (dataTransfer() && sendPage(tif, decodePageChop(pph, params)))) {
+ if (ppm == PPH_SKIP || (dataTransfer() && sendPage(tif, decodePageChop(pph, params), pt == PAGE_COVER))) {
/*
* Page transferred, process post page response from
* remote station (XXX need to deal with PRI requests).).
case PPR_PIP: // page good, interrupt requested
case PPR_RTP: // page good, retrain requested
ignore:
- countPage(ppm == PPH_SKIP); // bump page count
- if (ppm != PPH_SKIP || conf.countSkippedPages)
- notifyPageSent(tif);// update server
+ countPage(ppm == PPH_SKIP ? PAGE_SKIP : pt); // bump page count
+ notifyPageSent(tif, ppm == PPH_SKIP ? PAGE_SKIP : pt);// update server
if (pph[2] == 'Z')
pph.remove(0,2+5+1); // discard page-chop+handling
else
* is comprised of multiple strips.
*/
bool
-Class2Modem::sendPageData(TIFF* tif, u_int pageChop)
+Class2Modem::sendPageData(TIFF* tif, u_int pageChop, bool cover)
{
bool rc = true;
u_char* dp;
if (doTagLine) {
u_long totbytes = totdata;
- dp = imageTagLine(data+ts, fillorder, params, totbytes);
+ dp = imageTagLine(data+ts, fillorder, params, totbytes, cover);
totdata = (params.df == DF_2DMMR) ? totbytes : totdata+ts - (dp-data);
} else
dp = data;
#include "FaxFont.h"
#include "t.30.h"
#include "Sys.h"
+#include "SystemLog.h"
FaxModem::FaxModem(FaxServer& s, const ModemConfig& c)
: ClassModem(s,c)
minsp = fxmax((u_int) req.minbr, fxmax((u_int) conf.minSpeed, modemParams.getMinSpeed()));
pageNumber = 1;
pageNumberOfJob = req.npages + 1;
+ pageNumberCovered = pageNumberSkipped = 0;
+ if (conf.tagLineCoverNumString.length() )
+ pageNumberOfJob -= req.ncover;
+ if (! conf.countSkippedPages)
+ pageNumberOfJob -= req.nskip;
if (conf.useJobTagLine && req.desiredtl != 0)
setupTagLine(req, req.tagline);
else
}
void
-FaxModem::countPage(bool skipped)
+FaxModem::countPage(PageType pt)
{
- if (! skipped || conf.countSkippedPages)
- {
- pageNumber++;
- pageNumberOfJob++;
- pageNumberOfCall++;
- }
+logDebug("FaxModem::countPage(%s)", pt == PAGE_NORMAL ? "PAGE_NORMAL" :
+ (pt == PAGE_COVER ? "PAGE_COVER" : "PAGE_SKIP") );
+ pageNumber++;
+ pageNumberOfJob++;
+ pageNumberOfCall++;
- if (skipped)
+ if (pt == PAGE_COVER)
+ pageNumberCovered++;
+ if (pt == PAGE_SKIP)
pageNumberSkipped++;
}
}
void
-FaxModem::notifyPageSent(TIFF* tif)
+FaxModem::notifyPageSent(TIFF* tif, PageType pt)
{
if (curreq)
- server.notifyPageSent(*curreq, TIFFFileName(tif));
+ server.notifyPageSent(*curreq, TIFFFileName(tif), pt);
}
#include "MemoryDecoder.h"
typedef unsigned int RTNHandling; // RTN signal handling method
typedef unsigned int BadPageHandling; // bad page (received) handling method
typedef unsigned int JBIGSupport; // JBIG support available
+typedef unsigned int PageType;
/*
* This is an abstract class that defines the interface to
u_int pageNumberOfJob;// current transmit page number of Job
u_int pageNumberOfCall;// current transmit page number of call
u_int pageNumberSkipped;// current skipped page count
+ u_int pageNumberCovered;// current cover page count
FaxFont* tagLineFont; // font for imaging tag line
u_int tagLineSlop; // extra space reserved for tag line re-encoding
fxStr tagLine; // tag line formatted with transmit time
FaxModem(FaxServer&, const ModemConfig&);
// miscellaneous
- void countPage(bool skipped = false);
+ void countPage(PageType);
int getPageNumberOfCall();
void recvTrace(const char* fmt, ...);
void copyQualityTrace(const char* fmt, ...);
void recvResetPage(TIFF* tif);
u_int decodePageChop(const fxStr& pph, const Class2Params&);
bool decodePPM(const fxStr& pph, u_int& ppm, Status& eresult);
- void notifyPageSent(TIFF*);
+ void notifyPageSent(TIFF*, PageType pt);
// phase c data receive & copy quality checking
bool recvPageDLEData(TIFF* tif, bool checkQuality,
const Class2Params& params, Status& eresult);
// tag line support
bool setupTagLineSlop(const Class2Params&);
u_int getTagLineSlop() const;
- u_char* imageTagLine(u_char* buf, u_int fillorder, const Class2Params&, u_long& totdata);
+ u_char* imageTagLine(u_char* buf, u_int fillorder, const Class2Params&, u_long& totdata, PageType p);
/*
* Correct if neccessary Phase C (T.4/T.6) data (remove extra RTC/EOFB etc.)
*/
JBIG_SEND = 2, // send-only JBIG support
JBIG_FULL = 3 // full JBIG support
};
+ enum {
+ PAGE_NORMAL = 0,
+ PAGE_COVER = 1,
+ PAGE_SKIP = 2
+ };
+
virtual ~FaxModem();
bool& hasDoc, Status& eresult, u_int& batched) = 0;
virtual void sendSetupPhaseB(const fxStr& pwd, const fxStr& sub);
virtual FaxSendStatus sendPhaseB(TIFF*, Class2Params&, FaxMachineInfo&,
- fxStr& pph, Status& eresult, u_int& batched) = 0;
+ fxStr& pph, Status& eresult, u_int& batched, PageType = PAGE_NORMAL) = 0;
virtual void sendEnd();
virtual void sendAbort() = 0;
// query interfaces for optional state
pri = (u_short) -1;
usrpri = FAX_DEFPRIORITY;
pagewidth = pagelength = resolution = 0;
- npages = totpages = skippages = coverpages = 0;
+ npages = totpages = nskip = skippages = ncover = coverpages= 0;
ntries = ndials = 0;
minbr = BR_2400;
desiredbr = BR_33600;
{ "state", &FaxRequest::state },
{ "npages", &FaxRequest::npages },
{ "totpages", &FaxRequest::totpages },
+ { "nskip", &FaxRequest::nskip },
{ "skippages", &FaxRequest::skippages },
+ { "ncover", &FaxRequest::ncover },
{ "coverpages", &FaxRequest::coverpages },
{ "ntries", &FaxRequest::ntries },
{ "ndials", &FaxRequest::ndials },
case H_PAGELENGTH: pagelength = atoi(tag); break;
case H_PRIORITY: usrpri = atoi(tag); break;
case H_SCHEDPRI: pri = atoi(tag); break;
+ case H_NSKIP: nskip = atoi(tag); break;
case H_SKIPPAGES: skippages = atoi(tag); break;
case H_DESIREDBR: desiredbr = atoi(tag); break;
case H_DESIREDST: desiredst = tag[0] - '0'; break;
case H_DONEOP: doneop = tag; break;
case H_RETURNED: status = (FaxSendStatus) atoi(tag); break;
case H_MINBR: minbr = atoi(tag); break;
+ case H_NCOVER: ncover = atoi(tag); break;
case H_COVERPAGES: coverpages = atoi(tag); break;
case H_STATUS:
FaxSendStatus status; // request status indicator
u_short totpages; // total cummulative pages in documents
u_short skippages; // skipped pages in documents
- u_short npages; // total pages sent/received
u_short coverpages; // number of cover pages 1st
+ u_short npages; // total pages sent/received
+ u_short nskip; // total pages skipped so far
+ u_short ncover; // cover pages sent so far
u_short ntries; // # tries to send current page
u_short ndials; // # consecutive failed tries to call dest
u_short totdials; // total # calls to dest
{
TIFF* tif = TIFFOpen(freq.item, "r");
if (tif && (freq.dirnum == 0 || TIFFSetDirectory(tif, freq.dirnum))) {
+ bool coverpage = freq.item.find(0, "/cover") < freq.item.length();
if (dosetup) {
// set up DCS according to file characteristics
fax.status = sendSetupParams(tif, clientParams, clientInfo, fax.result);
*/
u_int prevPages = fax.npages;
fax.status = modem->sendPhaseB(tif, clientParams, clientInfo,
- fax.pagehandling, fax.result, batched);
+ fax.pagehandling, fax.result, batched, coverpage ? FaxModem::PAGE_COVER : FaxModem::PAGE_NORMAL);
if (fax.status == send_v17fail && fax.result.value() == 0) {
// non-fatal V.17 incompatibility
clientInfo.setHasV17Trouble(true);
*/
void
-FaxServer::notifyPageSent(FaxRequest& req, const char*)
+FaxServer::notifyPageSent(FaxRequest& req, const char*, PageType pt)
{
time_t now = Sys::now();
req.npages++; // count transmitted page
+ switch (pt) {
+ case FaxModem::PAGE_SKIP:
+ req.nskip++; break;
+ case FaxModem::PAGE_COVER:
+ req.ncover++; break;
+ }
req.writeQFile(); // update q file for clients
u_short tpages = req.totpages;
if (! modem->isCountingSkippedPages() )
// notification interfaces overridden in derived class
virtual void notifyCallPlaced(const FaxRequest&);
virtual void notifyConnected(const FaxRequest&);
- virtual void notifyPageSent(FaxRequest&, const char*);
+ virtual void notifyPageSent(FaxRequest&, const char*, PageType pt);
virtual void notifyDocumentSent(FaxRequest&, u_int index);
virtual void notifyPollRecvd(FaxRequest&, FaxRecvInfo&);
virtual void notifyPollDone(FaxRequest&, u_int index);
const char* def; // NULL is shorthand for ""
} strcmds[] = {
{ "modemtype", &ModemConfig::type, "unknown" },
+{ "taglinecovernumstring", &ModemConfig::tagLineCoverNumString },
{ "taglinefont", &ModemConfig::tagLineFontFile },
{ "taglineformat", &ModemConfig::tagLineFmt,
"From %%n|%c|Page %%p of %%t" },
bool waitForConnect; // modem sends multiple answer responses
fxStr tagLineFmt; // format string for tag lines
fxStr tagLineFontFile; // font file for imaging tag lines
+ fxStr tagLineCoverNumString; // format string for tagline cover page numbers
u_int recvDataFormat; // received facsimile data format
bool useJobTagLine; // Use Job tagline or use conf taglineformat
bool raiseATCmd; // whether or not to raise-case the AT commands
tag.insert(s, l);
}
+extern void logDebug(const char* fmt, ...);
/*
* Read in the PCF font to use for imaging the tag line and
* preformat as much of the tag line as possible.
strftime(line, sizeof (line)-1, tagLineFmt, tm);
tagLine = line;
u_int l = 0;
+
int tpages = req.totpages;
- if (! conf.countSkippedPages)
+ int npages = req.npages;
+ if (! conf.countSkippedPages) {
tpages -= req.skippages;
+ npages -= req.nskip;
+ }
+
+ if (conf.tagLineCoverNumString.length())
+ {
+ tpages -= req.coverpages;
+ npages -= req.ncover;
+ }
+
while (l < tagLine.length()) {
l = tagLine.next(l, '%');
if (l >= tagLine.length()-1)
case 's': insert(tagLine, l, req.sender); break;
case 'S': insert(tagLine, l, req.regarding); break;
case 't': insert(tagLine, l,
- fxStr((int)(tpages-req.npages), "%u")); break;
+ fxStr((int)(tpages-npages), "%u")); break;
case 'T': insert(tagLine, l,
fxStr((int)(tpages), "%u")); break;
case 'v': insert(tagLine, l, req.voice); break;
* setup the current page number.
*/
u_char*
-FaxModem::imageTagLine(u_char* buf, u_int fillorder, const Class2Params& params, u_long& totdata)
+FaxModem::imageTagLine(u_char* buf, u_int fillorder, const Class2Params& params, u_long& totdata, PageType pt)
{
u_int l;
+ u_int pn = pageNumber;
+ u_int pnj = pageNumberOfJob;
+
+ if (! conf.countSkippedPages) {
+ pn -= pageNumberSkipped;
+ pnj -= pageNumberSkipped;
+ }
/*
* Fill in any per-page variables used in the tag line.
+ * If the TagLineCoverNumString is set, then coverpages
+ * are not counted, and that is used instead of pages numbers on
+ * the cover pages themselves.
*/
+ fxStr pns, pnjs;
+ if (pt == PAGE_COVER && conf.tagLineCoverNumString.length()) {
+ // Actually on the cover page, with it CoverNumString set
+ pns = conf.tagLineCoverNumString;
+ pnjs = conf.tagLineCoverNumString;
+ } else if (conf.tagLineCoverNumString.length() ) {
+ // regular page, with it CoverNumString set, adjust page numbers
+ pns = fxStr::format("%d", pn-pageNumberCovered);
+ pnjs = fxStr::format("%d", pnj-pageNumberCovered);
+ } else {
+ // CoverNumString not set, just do it
+ pns = fxStr::format("%d", pnj);
+ pnjs = fxStr::format("%d", pnj);
+ }
+
fxStr tag = tagLine;
l = 0;
while (l < tag.length()) {
if (l >= tag.length()-1)
break;
if (tag[l+1] == 'p')
- insert(tag, l, fxStr((int) pageNumber, "%d"));
+ insert(tag, l, pns);
if (tag[l+1] == 'P')
- insert(tag, l, fxStr((int) pageNumberOfJob, "%d"));
+ insert(tag, l, pnjs);
else
l += 2;
}
Class2Params next; // parameters for ``next'' page
TIFF* tif = NULL; // current open TIFF image
req.totpages = req.npages; // count pages previously transmitted
- req.skippages = 0;
+ req.skippages = req.nskip;
+ req.coverpages = req.ncover;
bool firstpage = true;
bool skiplast = false;
bool coverdoc = false;
}
const FaxItem& fitem = req.items[i];
+ logDebug("req.items[%d].item = \"%s\" (%s)", i,
+ (const char*)fitem.item, (const char*)req.cover);
if (fitem.item.find(0, "/cover") < fitem.item.length())
coverdoc = true;
else
}
void
-faxSendApp::notifyPageSent(FaxRequest& req, const char* filename)
+faxSendApp::notifyPageSent(FaxRequest& req, const char* filename, bool skipped)
{
FaxSendInfo si(filename, req.commid, req.npages+1,
getPageTransferTime(), getClientParams());
sendJobStatus(req.jobid, "d%s", (const char*) si.encode());
- FaxServer::notifyPageSent(req, filename);
+ FaxServer::notifyPageSent(req, filename, skipped);
}
/*
void notifyModemWedged();
void notifyCallPlaced(const FaxRequest&);
void notifyConnected(const FaxRequest&);
- void notifyPageSent(FaxRequest& req, const char* filename);
+ void notifyPageSent(FaxRequest& req, const char* filename, bool skipped);
void notifyDocumentSent(FaxRequest&, u_int fileIndex);
void notifyPollRecvd(FaxRequest&, FaxRecvInfo&);
void notifyPollDone(FaxRequest&, u_int pollIndex);
hash("subaddr");
hash("passwd");
hash("state");
+ hash("ncover");
hash("coverpages");
hash("npages");
hash("totpages");
+ hash("nskip");
hash("skippages");
+ hash("coverpages");
hash("ntries");
hash("ndials");
hash("totdials");
ServerTracing\(S2 integer \s-11\s+1 non-session server tracing
SessionTracing\(S2 integer \s-11\s+1 send and receive session tracing
SpeakerVolume string \s-1Quiet\s+1 volume level for modem speaker
+TagLineCoverNumString string \- String substition when not counting cover pages
TagLineFont string \- tag line font filename
TagLineFormat string \s-1\fIsee below\fP\s+1 tag line format string
TIFF2FaxCmd\(S1 string \s-1bin/tiff2fax\s+1 \s-1TIFF\s+1 converter command script
see
.BR ModemSetVolumeCmd .
.TP
+.B TagLineCoverNumString
+
+Setting TagLineCoverNumString instructs faxsend to not include the cover pages
+in the normal page numbering mechanism. The page numbers used in the tagline
+generation will adjusted to not count the cover pages, and the TagLineCoverNumString value
+wil be used instead of a page number on the tagline of the cover page.
+.TP
.B TagLineFont
The filename of the font to use in imaging
.I "tag lines"