root/src/add-ons/print/drivers/lpstyl/Lpstyl.cpp
/*
* Copyright 2017, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
*               Adrien Destugues <pulkomandy@pulkomandy.tk>
*/
#include "Lpstyl.h"


LpstylDriver::LpstylDriver(BMessage* message, PrinterData* printerData,
        const PrinterCap* printerCap)
        : GraphicsDriver(message, printerData, printerCap)
{
}


bool
LpstylDriver::StartDocument()
{
        _EjectAndReset();
        _IdentifyPrinter();
        _ColorCartridge();
        return true;
}


bool
LpstylDriver::StartPage()
{
        if (fPrinterType < kStyleWriter2400)
                WriteSpoolData("nuA", 3);
        else
                WriteSpoolChar('L');
        return true;
}


bool
LpstylDriver::NextBand(BBitmap* bitmap, BPoint* offset)
{
        fprintf(stderr, "Next band at %f %f\n", offset->x, offset->y);

        int page_height = GetPageHeight();

        // Advance the cursor
        offset->y += bitmap->Bounds().Height();

        // Have we reached the end of the page yet?
        if (offset->y >= page_height)
        {
                offset->y = -1;
                offset->x = -1;
        }

        return true;
}


bool
LpstylDriver::EndPage(int page)
{
        fprintf(stderr, "end page %d\n", page);
        return true;
}


bool
LpstylDriver::EndDocument(bool success)
{
        return true;
}


/** Eject the current page (if any) and reset the printer.
 */
void
LpstylDriver::_EjectAndReset(void)
{
        _WriteFFFx('I');

        int s1;

        do {
                for (;;) {
                        try {
                                s1 = _GetStatus('1');
                                break;
                        } catch(const TransportException&) {
                                continue;
                        }
                }

                if (s1 == 1) {
                        // Check for stylewriter1, where status 1 doesn't g to 0 on init.
                        if (_GetStatus('2') == 0 && _GetStatus('B') == 0xa0)
                                break;
                }
        } while (s1 == 1);
}


void
LpstylDriver::_IdentifyPrinter(void)
{
        WriteSpoolChar('?');

        char smallBuf[32];
        int i = 0;
        for (i = 0; i < 31; i++) {
                smallBuf[i] = ReadSpoolChar();
                if (smallBuf[i] == 0x0D)
                        break;
        }
        smallBuf[i] = 0;

        if (strcmp(smallBuf, "IJ10\x0D") == 0)
                fPrinterType = kStyleWriter;
        else if (strcmp(smallBuf, "SW\x0D") == 0)
                fPrinterType = kStyleWriter2;
        else if (strcmp(smallBuf, "SW3\x0D") == 0)
                fPrinterType = kStyleWriter3;
        else if (strcmp(smallBuf, "CS\x0D") == 0) {
                switch (_GetStatus('p'))
                {
                        default:
                        case 1:
                                fPrinterType = kStyleWriter2400;
                                break;
                        case 2:
                                fPrinterType = kStyleWriter2200;
                                break;
                        case 4:
                                fPrinterType = kStyleWriter1500;
                                break;
                        case 5:
                                fPrinterType = kStyleWriter2500;
                                break;
                }
        }
}


bool
LpstylDriver::_ColorCartridge()
{
        WriteSpoolChar('D');
        unsigned char i = _GetStatus('H');
        return i & 0x80;
}


/** Send a 4-byte command to the printer.
 *
 * These commands can be sent at any time, because their prefix is FFFFFF, a
 * sequence which can't be generated by the data compression algorithm
 */
void
LpstylDriver::_WriteFFFx(char x)
{
        unsigned char str[4];
        str[0] = str[1] = str[2] = 0xFF;
        str[3] = x;
        WriteSpoolData(str, 4);
}


/** Get one of the printer status bytes.
 *
 * There are 3 status registers, 1, 2, and B. Each returns some different
 * information about the printer state.
 */
int
LpstylDriver::_GetStatus(char reg)
{
        _WriteFFFx(reg);
        return ReadSpoolChar();
}