/* GEM-View 3.00 PRINTER Modul: NEC P6/24 Nadeln/180 dpi
   (c) 22.10.1993 by Dieter Fiebelkorn
                     Grner Weg 29a
                     D-45768 Marl
                     (GERMANY)
*/

#include <stdio.h>
#include "image.h"
#include "moduls.h"

typedef size_t    bit32;

#define ltable(name,n)\
    static bit32 name[16] =\
    {\
        0x00000000UL<<n, 0x00000001UL<<n, 0x00000100UL<<n, 0x00000101UL<<n,\
        0x00010000UL<<n, 0x00010001UL<<n, 0x00010100UL<<n, 0x00010101UL<<n,\
        0x01000000UL<<n, 0x01000001UL<<n, 0x01000100UL<<n, 0x01000101UL<<n,\
        0x01010000UL<<n, 0x01010001UL<<n, 0x01010100UL<<n, 0x01010101UL<<n,\
    };

ltable(ltab0,7)
ltable(ltab1,6)
ltable(ltab2,5)
ltable(ltab3,4)
ltable(ltab4,3)
ltable(ltab5,2)
ltable(ltab6,1)
ltable(ltab7,0)


static void printRotate8n(char *src, size_t srcstep, char *dst, long lines)
{
    register char    *s, *d;
    register size_t  sstep, dstep,
                     lownyb, hinyb;
    register bit32   low, hi;

    low = hi = 0;
    
#define extract(p,t)\
    if (lines > 0) { lines--;            \
    lownyb = *p & 0x0F; hinyb = *p >> 4; \
    low |= t[lownyb]; hi |= t[hinyb]; p+= sstep;}
    
#define unpack(p,w)\
    *p = (w >> 24) & 0xFF; p += dstep; \
    *p = (w >> 16) & 0xFF; p += dstep; \
    *p = (w >> 8)  & 0xFF; p += dstep; \
    *p = w         & 0xFF; p += dstep;

    s = src; sstep = srcstep;
    d = dst; dstep = 1;

    extract(s,ltab0); extract(s,ltab1); extract(s,ltab2); extract(s,ltab3);
    extract(s,ltab4); extract(s,ltab5); extract(s,ltab6); extract(s,ltab7);
    unpack(d,hi); unpack(d,low);
}



/* 8 Zoll Papierbreite bei 120 dpi */
#define MAX_PAPERWIDTH  960

#define INIT_GRAPH        2
#define INIT_LINE         4
#define EXIT_LINE         4
#define EXIT_GRAPH        0
#define LINE_HI           3
#define LINE_LO           2

#if INIT_GRAPH
static char init_graph[INIT_GRAPH] = { 0x1B, 0x40 };
#endif
#if INIT_LINE
static char init_line [INIT_LINE ] = { 0x1B, 0x59, 0x00, 0x00 };
#endif
#if EXIT_LINE
static char exit_line [EXIT_LINE ] = { 0x1B, 0x4A, 0x18, 0x0D };
#endif
#if EXIT_GRAPH
static char exit_graph[EXIT_GRAPH] = { };
#endif


void gvw_main(PRINT_Structure *printS, int verbose)
{
    Image  *image;
    char   *data, out[8];
    long    width, height;
    long    output_width;
    long    linelen, x;
    int     fd;
    
    image = printS->image;
    if (image == NULL)
    {
      printS->events.alert(1, "[3][ | No image to print!  | ][  Abort  ]");
      return;
    }
    data = image->data;
    if (data == NULL)
    {
      printS->events.alert(1, "[3][ | No data in image!  | ][  Abort  ]");
      return;
    }
    fd = printS->output.open("PRN:");
    if (fd <= 0)
    {
      printS->events.alert(1, "[3][ | Printer not ready!  | ][  Abort  ]");
      return;
    }
    
    linelen = image->width / 8;
    output_width = image->unalignwidth;
    if (output_width > MAX_PAPERWIDTH)
      output_width = MAX_PAPERWIDTH;
#if INIT_GRAPH
    printS->output.write(fd, INIT_GRAPH, init_graph);
#endif
    for (height = image->height; height > 0; height -= 8)
    {
#if INIT_LINE
        init_line[LINE_HI] = (output_width >> 8) & 0xFF;
        init_line[LINE_LO] = (output_width     ) & 0xFF;
        printS->output.write(fd, INIT_LINE, init_line);
#endif
        for (x = 0, width = output_width; width >= 8; width -= 8) {
            printRotate8n(&data[x++], linelen, out, height);
            printS->output.write(fd, 8L, out);
        }
        if (width) {
            printRotate8n(&data[x++], linelen, out, height);
            printS->output.write(fd, width, out);
        }
#if EXIT_LINE
        printS->output.write(fd, EXIT_LINE, exit_line);
#endif
        data += 8 * linelen;
    }
#if EXIT_GRAPH
    printS->output.write(fd, EXIT_GRAPH, exit_graph);
#endif
    printS->output.close(fd);
}
