📄 printer.cpp
字号:
err = Send (InputRaster->rasterdata[COLORTYPE_COLOR], InputRaster->rastersize[COLORTYPE_COLOR]); } } } } else { scratchLen = sprintf (scratch, "\033*b%uW", InputRaster->rastersize[COLORTYPE_COLOR]); err = Send ((const BYTE*) scratch, scratchLen); if (err == NO_ERROR) { err = Send (InputRaster->rasterdata[COLORTYPE_COLOR], InputRaster->rastersize[COLORTYPE_COLOR]); } } } else { scratchLen = sprintf (scratch, "\033*b%uV", InputRaster->rastersize[COLORTYPE_COLOR]); err = Send ((const BYTE*) scratch, scratchLen); if (err == NO_ERROR) { err = Send (InputRaster->rasterdata[COLORTYPE_COLOR], InputRaster->rastersize[COLORTYPE_COLOR]); } } return err;}DRIVER_ERROR Printer::Send( const BYTE* pWriteBuff){ ASSERT(pWriteBuff); int len = strlen((const char*)pWriteBuff); return Send(pWriteBuff,len);} //Send/* * Function name: Printer::Send * * Owner: Darrell Walker * * Purpose: Encapsulate error handling generated by performing I/O * * Called by: * * Calls made: WritePort(), GetStatus(), BusyWait(), ParseError(), * DisplayPrinterStatus(), YieldToSystem() * * Parameters on entry: pJob is a pointer to the current JOBSTRUCT, * pWriteBuff is a pointer to the data the * caller wishes to send to the pritner, * wWriteCount is the number of bytes of * pWriteBuff to send * * Parameters on exit: Unchanged * * Side effects: Sends data to the printer, may update print dialog, * may change pJob->InSlowPollMode, * pJob->ErrorTerminationState * * Return Values: NO_ERROR or JOB_CANCELED or IO_ERROR * * Comments: (TJL) This routine now has functionality to attempt iterating * through wWriteCount bytes of data (until we hit slow poll mode) * before sending PCL cleanup code. This still leaves the possibility of * prematurely exiting with an incomplete raster, but gives I/O a fighting chance * of completing the raster while also protecting from a bogged down slow poll phase * which would prevent a timely exit from CANCEL. A JobCanceled flag is used * because JOB_CANCELED cannot be maintained by write_error through the while * loop since it will be overwritten by next ToDevice. * */DRIVER_ERROR Printer::Send( const BYTE* pWriteBuff, DWORD dwWriteCount){ ASSERT(pWriteBuff); DRIVER_ERROR write_error = NO_ERROR; DWORD residual = 0; const BYTE * pWritePos = NULL; BOOL error_displayed = FALSE; BYTE status_reg = 0; DISPLAY_STATUS eDisplayStatus = DISPLAY_PRINTING; BOOL JobCanceled = FALSE; // see comments in function header // these are just an abstraction layer - buffered vs. non-buffered const BYTE * pBuffer = pWriteBuff; DWORD dwSendSize = dwWriteCount;////////////////////////////////////////////////////////////////#ifdef NULL_IO // test imaging speed independent of printer I/O, will not // send any data to the device return NO_ERROR;#endif//////////////////////////////////////////////////////////////// if (ErrorTerminationState) // don't try any more IO if we previously { return JOB_CANCELED; // terminated in an error state } if (EndJob == FALSE && dwWriteCount == 0) // don't bother processing { return NO_ERROR; // an empty Send call }#ifdef APDK_BUFFER_SEND DWORD BytesToWrite = dwWriteCount; do { // we should bypass the buffering for a large Send, but don't lose what may already be buffered if ( (BytesToWrite >= iBuffSize) && (iCurrBuffSize == 0) ) { pBuffer = pWriteBuff+(dwWriteCount-BytesToWrite); dwSendSize = BytesToWrite; BytesToWrite = 0; // this is checked for at the end of the outer loop } else // we will buffer this data { // if it'll fit then just copy everything to the buffer if (BytesToWrite <= DWORD(iBuffSize-iCurrBuffSize)) { memcpy((void*)(pSendBuffer+iCurrBuffSize), (void*)(pWriteBuff+(dwWriteCount-BytesToWrite)),BytesToWrite); iCurrBuffSize += BytesToWrite; BytesToWrite = 0; } else // copy what we can into the buffer, we'll get the rest later { memcpy((void*)(pSendBuffer+iCurrBuffSize), (void*)(pWriteBuff+(dwWriteCount-BytesToWrite)), iBuffSize-iCurrBuffSize); BytesToWrite -= (iBuffSize-iCurrBuffSize); iCurrBuffSize = iBuffSize; } // if the buffer is now full (ready-to-send) or if we're at // the end of the job, then send what we have in the buffer. // otherwise just break (the buffer isn't ready to send) if ( (EndJob == FALSE) && (iCurrBuffSize != iBuffSize) ) { break; // we're not ready to send yet } else // send this buffered data { pBuffer = pSendBuffer; dwSendSize = iCurrBuffSize; } }#endif // initialize our 'residual' to the full send size residual = dwSendSize; if (bCheckForCancelButton && (ulBytesSentSinceCancelCheck >= CANCEL_BUTTON_CHECK_THRESHOLD) ) { ulBytesSentSinceCancelCheck = 0; char* tmpStr; BYTE DevIDBuffer[DevIDBuffSize]; DRIVER_ERROR tmpErr = pSS->GetDeviceID(DevIDBuffer, DevIDBuffSize, TRUE); if(tmpErr) return tmpErr; BOOL cancelcheck=FALSE; if((tmpStr = strstr((char*)DevIDBuffer + 2,"CNCL"))) { cancelcheck=TRUE; } else { int iVersion = pSS->GetVIPVersion (); if((tmpStr = strstr((char*)DevIDBuffer + 2,";S:")) && iVersion < 6) // aladdin devID style { // point to PrinterState/* * VIPVersion = DevID Version + 1 - DevID Version no is 2 bytes following ;S: * Version 00 and 01 report 12 bytes for status info * Version 02 and onwards, report two additional bytes before pen info */ if (iVersion < 3) { tmpStr += 17; // 3 for ";S:", 2 for version, 12 for features = 17 } else if (iVersion < 5) { tmpStr += 19; // 17 as above plus 1 for MaxPaperSize, 1 reserved = 19 } else { tmpStr += 23; // Crystal added 4 more nibbles } BYTE b1=*tmpStr++; BYTE b2=*tmpStr++; if (((b1=='0') && (b2=='5')) && iVersion <= 5) // 05 = cancel { cancelcheck=TRUE; } } } if (cancelcheck) { // Since the printer is now just throwing data away, we can bail // immediately w/o worrying about finishing the raster so the // end-of-job FF will work. ErrorTerminationState = TRUE; pSS->DisplayPrinterStatus(DISPLAY_PRINTING_CANCELED); return JOB_CANCELED; } } // If we have nothing to send, we need to bail to avoid spurious dialogs // at the end of the ::send function. I'd prefer a solution where we don't // bail from a while loop but in practice this shouldn't have any ill effects. if (residual <= 0) { return NO_ERROR; } while (residual > 0) // while still data to send in this request { DWORD prev_residual = residual; // WritePort overwrites request // count, need to save pWritePos = (const BYTE *) &(pBuffer[dwSendSize-residual]); write_error = pSS->ToDevice(pWritePos, &residual); // The following error handling code is recommended, but is not supported // on several current platforms for this reason: when the printer buffer // fills and declines more data, the O/S returns a BUSY error in one form // or another. The real solution is to allow the code below and have the // derived pSS->ToDevice functions catch and ignore any BUSY error - only // returning a real error to ::Send. The current workaround here is that we // literally ignore all errors returned from the I/O system and ultimately catch // them after we've reached our slow poll limit via the slow poll logic below. -TL// if(write_error != NO_ERROR)// {// DBG1("IO_ERROR returned from ToDevice - ABORT!\n");// ErrorTerminationState = TRUE;// return write_error;// } write_error = NO_ERROR; eDisplayStatus = DISPLAY_PRINTING; if (residual == 0) // no more data to send this time { if (m_bStatusByPJL) { status_reg = (BYTE) DISPLAY_PRINTING; eDisplayStatus = ParseError (status_reg); if (eDisplayStatus != DISPLAY_PRINTING) write_error = IO_ERROR; } // did we want to transition out of slow poll? if ( (InSlowPollMode != 0) && (prev_residual > MIN_XFER_FOR_SLOW_POLL) ) { InSlowPollMode = 0; iTotal_SLOW_POLL_Count = 0; } if (write_error == NO_ERROR) break; // out of while loop } // if we are here, WritePort() was not able to // send the full request so start looking for errors // decide whether we've waited long enough to check for an error if (InSlowPollMode > iMax_SLOW_POLL_Count ) { if (JobCanceled == TRUE) // Well, I/O didn't finish in time to meet the CANCEL request and avoid // the SlowPoll threshold. We have to bail for prompt cancel response. { DBG1("Send(SlowPoll): Premature return w/ JOB_CANCELED\n"); ErrorTerminationState = TRUE; return JOB_CANCELED; } DBG1("Printer slow poll times exceeded\n"); // reset counter so we will not pop it next time InSlowPollMode = 1; write_error = IO_ERROR; } else { write_error = NO_ERROR; } // are we in slow poll mode? If so, track our count if ( (prev_residual - residual) <= MIN_XFER_FOR_SLOW_POLL) { InSlowPollMode++;#if defined(DEBUG) && (DBG_MASK & DBG_LVL1) if (InSlowPollMode == 1) { printf("entering slow poll mode\n"); } else { printf("still in slow poll mode, count = %d\n", InSlowPollMode); }#endif // give the printer some time to process if (pSS->BusyWait((DWORD)200) == JOB_CANCELED) { DBG1("Send: JOB_CANCELED\n"); JobCanceled = TRUE; pSS->DisplayPrinterStatus(DISPLAY_PRINTING_CANCELED); } } else { // still busy, but taking enough data that // we are not in slow poll mode DBG1("Partial Send but not slow poll mode\n"); InSlowPollMode = 0; iTotal_SLOW_POLL_Count = 0; } if (write_error != NO_ERROR || (m_bStatusByPJL && eDisplayStatus != DISPLAY_PRINTING)) // slow poll times exceeded // the printer isn't taking data so let's see what's wrong... { DBG1("Parsing possible error state...\n"); error_displayed = TRUE; if (m_bStatusByPJL) { status_reg = (BYTE) eDisplayStatus; } else { // go get the status of the printer if (IOMode.bStatus) { pSS->GetStatusInfo(&status_reg); } // determine the error eDisplayStatus = ParseError(status_reg); } switch (eDisplayStatus) { case DISPLAY_PRINTING_CANCELED: // user canceled in an error state, // so we don't want to attempt any // further communication with the printer ErrorTerminationState = TRUE; pSS->DisplayPrinterStatus(eDisplayStatus); return JOB_CANCELED; case DISPLAY_ERROR_TRAP: case DISPLAY_COMM_PROBLEM: // these are unrecoverable cases // don't let any more of this job // be sent to the printer ErrorTerminationState = TRUE; pSS->DisplayPrinterStatus(eDisplayStatus); // wait for user to cancel the job, // otherwise they might miss the // error message while (pSS->BusyWait(500) != JOB_CANCELED) { // nothing.... ; } return IO_ERROR; case DISPLAY_TOP_COVER_OPEN: pSS->DisplayPrinterStatus(DISPLAY_TOP_COVER_OPEN); // wait for top cover to close while ( eDisplayStatus == DISPLAY_TOP_COVER_OPEN) { if (pSS->BusyWait((DWORD)500) == JOB_CANCELED) // although we'll leave an incomplete job in the printer, // we really need to bail for proper CANCEL response. { ErrorTerminationState = TRUE; return JOB_CANCELED; } if (m_bStatusByPJL) { status_reg = (BYTE) eDisplayStatus; } else { if (IOMode.bStatus) { pSS->GetStatusInfo(&status_reg); } } eDisplayStatus = ParseError(status_reg); } pSS->DisplayPrinterStatus(DISPLAY_PRINTING); // Wait for printer to come back online if (pSS->BusyWait((DWORD)1000) == JOB_CANCELED) // Since the top_cover error HAS been handled, we have // the opportunity to finish the raster before we hit // the next slowpoll threshold.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -