home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
texmf
/
source
/
driver
/
print
/
newhard.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-07
|
43KB
|
1,561 lines
/*
** This file generated by localize 2.9 (AmigaDOS 2.1) from newhard.c
*/
/****************************************************************************/
/* */
/* newhard.c */
/* */
/* Ein Ersatz fuer hardcopy.c. */
/* Druckt die Bitmap in 180dpi oder 360dpi auf einen NEC-P6 */
/* oder in 100dpi/300dpi auf einen HP-DESKJET. */
/* Vorteil gegenueber hardcopy.c: */
/* - schneller (30%-50%) */
/* - besser kommentiert (zumindestens ich versteh's :-) */
/* */
/* 26.11.89 (hes) */
/* */
/* Erweiterung auf EPSON-FX und kompatible 9-Nadel-Drucker */
/* mit 120x72dpi (DRAFT) oder 240x216dpi (HQ) */
/* */
/* 05.02.90 (kb) */
/* */
/* Einfuegen des Atari Laser Printer Treibers */
/* */
/* 28.03.90 (rbs) */
/* */
/* Verbesserung (?) der NEC und Epson Treiber */
/* 30.11.90 (jch) */
/* */
/****************************************************************************/
#include "defines.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#define min(a,b) __builtin_min(a,b)
#include "globals.h"
#include "bitmap.h"
#ifdef ATARI
# include <tos.h>
# define Chk_Abort()
#endif
#ifdef AMIGA
# include <dos.h>
# include <clib/exec_protos.h>
# include <pragmas/exec_pragmas.h>
extern struct ExecBase *SysBase;
# include <exec/ports.h>
# include <devices/printer.h>
# include <exec/types.h>
# include <exec/exec.h>
# include "amprint.h"
# include "amprint.i"
#endif
#include "prhelp.h"
#include "prhelp.i"
#include "newhard.i"
#include "globals.i"
#include "landscap.i"
#include "amprhelp.i"
#include "muiprint.i"
/*
* Fuer die locale-Library:
*
* Hier duerfen *nur* die MSG_#? Nummern eingebunden werden!
* Achtung:
* Es muss/sollte 'multiple-include' erlaubt sein!
*/
#include "local.i"
#undef CATCOMP_ARRAY
#undef CATCOMP_BLOCK
#undef CATCOMP_STRINGS
#define CATCOMP_NUMBERS
#include "localstr.h"
/* global vars */
extern int is_printer_started; /* 0: no, 1: init ok, 2: print started */
int Skip_buffered = 0; /* Number of Skips to execute */
char *PrnBuffer = NULL; /* Pointer to local buffer */
/* local vars */
static int PrnIndex, /* [0..n] Index into local buffer */
PrnBuffered; /* Number of chars to buffer */
static char ESCdollar[] = {ESC,'$',PP_INS_LOW,PP_INS_HIGH};
static char ESCU[] = {ESC,'U',PP_INS_LOW};
static char *compbuf = NULL; /* wird fuer HP Compress Alg. benoetigt */
/* wird mit malloc() allociert. */
static int PrintedLines = 0; /* Anzahl der bereits gedruckten Zeilen */
/* wird immer nach einem ganzen Pass aktualisiert */
/* lokale Funktionen */
#define quickgfxout(c) PrnBuffer[PrnIndex++]=(c), PrnBuffered--
#ifdef ATARI
/***** A T A R I - Funktionen ********************************************/
#include "ataridef.h"
static void check_key Args((void));
static void directout Args((char c));
#else
/***** A M I G A - Funktionen ********************************************/
#ifdef HES
#define directout(c) { buffer[bufferz++] = (char)c;\
if (bufferz==bufflen) { make_room(); }}
#else
#define directout(c) if (buffer[bufferz++] = (char)c,\
bufferz==bufflen) make_room(); else /* ; follows */
#endif
#endif
/***** HP - DeskJet Graphic-Befehle ****************************************/
static void CompressLine Args((char *buf, short len));
static short search_left_border Args((char *in_line_ptr,
short map_width));
static short search_right_border Args((char *in_line_ptr,
short map_width));
static void Hardcopy_HP Args((struct bitmap *bmap,
long lineno,
int draft));
static void Hardcopy_Canon Args((struct bitmap *bmap,
long lineno,
int draft));
static short search_next_blank Args((short * blank_bytes,
char * line_ptr,
short left_border,
short right_border));
/***** Standard Treiber ** NEC P6 * EPSON FX * EPSON LQ *******************/
static void Hardcopy_standard(struct bitmap *bmap, long lineno, int draft);
//static void prepare_pass(int pass, struct printer_para *Printer);
//static void end_pass(int pass, struct printer_para *Printer);
static void print_empty_words(int empty, int words);
//static int setup_graphic_mode(void);
static void print_buffered_line(void);
static void prepare_skip(int skips);
/***** misc functions ****************************************************/
static int jskip_blank_words_std Args((WP_TYP * ptr,
int lines,
int b_offset,
int max,
int l_offset));
static int jsearch_right_border_std Args((WP_TYP * ptr,
int lines,
int b_offset,
int max,
int l_offset));
static int jsearch_length_text_std Args((WP_TYP * ptr,
int lines,
int b_offset,
int max,
int l_offset));
static void prepare_for_gfx Args((int nr));
static void skip_lines Args((void));
static void string_directout Args((char *string,
int length,
int opt_argument));
#ifdef AZTEC_C /* Version 5.0 */
#pragma regcall ( /* d0 = */ search_left_border(a0,d0) )
#pragma regcall ( /* d0 = */ search_right_border(a0,d0) )
#pragma regcall ( Hardcopy_HP(a0,d0,d1) )
#pragma regcall ( /* d0 = */ skip_blank_words(a0,d0,d1,d2) )
#pragma regcall ( /* d0 = */ search_length_text(a0,d0,d1,d2) )
#endif
/****** misc macros *******************************************************/
#define take_Bit(nr,lword) (lword & (1L<<nr))
#ifndef LATTICE
# define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
/* getout
*
* Output one character, taking into account all kinds of buffering.
* This is the preferred routine to use. But if you know what you are
* doing, you may as well call directout().
*/
void getout(char c)
{
#if defined(HARDDEB)
printf("J:\tgetout:(%02X), Buffered: %d, Index: %d\n",
(unsigned char)c,PrnBuffered, PrnIndex);
#endif
if (PrnBuffered) quickgfxout(c);
/* Aufeinanderfolgende Grafikdaten werden zwischengespeichert */
else {
/* ev. Zeilenvorschub ausfuehren */
/* (FF wird in FormFeed() abgefangen) */
if (Skip_buffered) skip_lines();
/* keine neuen Grafikdaten mehr, ev. Puffer leeren */
if (PrnIndex) print_buffered_line();
directout(c); /* output the initial char */
}
}
/* string_out
*
* print a buffer of given length with getout(), accepts numeric
* argument (ex: ESC * n1 n2)
*/
void string_out(char *buf, int number, int opt_arg)
{
for (; 0 < number; number--, buf++) {
char c;
#if defined(HARDDEB)
printf("J:\tstring_out %02X",(unsigned char) *buf);
#endif
switch ((unsigned char)*buf) { /* Lattice, grrr */
case PP_INS_DEC: /* not supported here */
continue;
case PP_INS_LOW:
c = (char) opt_arg;
break;
case PP_INS_HIGH:
c = (char) (opt_arg >> 8);
break;
case PP_INS_NR100:
c = (char) ((opt_arg / 100) % 10) + '0';
break;
case PP_INS_NR10:
c = (char) ((opt_arg / 10) % 10) + '0';
break;
case PP_INS_NR1:
c = (char) (opt_arg % 10) + '0';
break;
default:
c = *buf;
}
#if defined(HARDDEB)
printf(" %02X ",(unsigned char) c);
#endif
getout(c);
}
}
/* string_directout
*
* print the bytes using directout() instead of getout(), accepts
* numeric argument (ex: ESC * n1 n2). You should normally use
* string_out() (buffers automatically)
*/
static void string_directout(char *buf, int number, int opt_arg)
{
/* if (NULL==buf) Fatal(20,"Printer command missing!"); */
for (; 0 < number; number--, buf++) {
char c;
#if defined(HARDDEB)
printf("J:\tstring_directout %02X",(unsigned char) *buf);
#endif
switch ((unsigned char)*buf) { /* Lattice, grrr */
case PP_INS_DEC: {
register char *buf = m_string;
sprintf(buf,"%d", opt_arg);
while (*buf) directout(*(buf++));
continue; /* for/next loop */
}
case PP_INS_LOW:
c = (char) opt_arg;
break;
case PP_INS_HIGH:
c =(char) (opt_arg >> 8);
break;
case PP_INS_NR100:
c = (char) ((opt_arg / 100) % 10) + '0';
break;
case PP_INS_NR10:
c = (char) ((opt_arg / 10) % 10) + '0';
break;
case PP_INS_NR1:
c = (char) (opt_arg % 10) + '0';
break;
default:
c = *buf;
}
#if defined(HARDDEB)
printf(" %02X\n",(unsigned char) c);
#endif
directout(c);
}
}
/***** A T A R I - Funktionen ********************************************/
#ifdef ATARI
long mymask = 0x08L;
static void check_key(void)
{
if ((Kbshift(-1)&mymask)==0L)
{ return; }
Fatal(5,"Program aborted by user.");
}
static void directout(c)
register char c;
{
while ((long)Bcostat(0)==0L)
check_key();
Bconout(0,0xff&c);
}
#ifdef TEST_IT
# include <ctype.h>
static void directout(char c);
static void directout(c)
char c;
{
if (isprint(c)) printf("%c",c);
}
#endif /* TEST_IT */
/***** Atari SLM 804 Ansteuerung *******************************************/
typedef struct
{
char *s_form;
short s_xmin,
s_ymin,
s_nxln,
b_width,
b_height,
d_xmin,
d_ymin,
scalefac;
} SLM;
static void Hardcopy_SLM(struct bitmap *bmap, long lineno, int draft)
{
FILE *fp;
SLM o;
fp=fopen("PRN:","w");
o.s_form = (char *)bmap->pixptr;
o.s_xmin = (short)0;
o.s_ymin = (short)0;
o.s_nxln = (short)(bmap->width/8);
o.b_width = (short)bmap->width;
o.b_height = (short)bmap->height;
o.d_xmin = (short)0;
o.d_ymin = (short)0;
o.scalefac = (short)(draft+1);
/*
o.scalefac = (short)1;
*/
check_key();
fprintf(fp,"\033\022G%08lx \n\f",&o);
fclose(fp);
}
#endif /* ATARI */
#define hp_str_n(str,num) string_directout((str),sizeof(str),(num))
/***** Canon CaPSL Graphic-Befehle ****************************************/
/* einmal am Anfang */
static char init_canon_str[] = {ESC,';',ESC,'[','2','1','%','y',
ESC,'[','1','1','h',ESC,'[','7',' ','I',
ESC,'[','0',';','1','u'};
static char set_display_canon_str[] = {ESC,'P','1','y','J','o','b','G',ESC,'\\'};
/* einmal am Anfang jeder Seite */
static char set_portrait_mode_canon_str[] = {ESC,'[','0','p'};
static char set_landscape_mode_canon_str[] = {ESC,'[','1','p'};
static char set_nr_of_copies_canon_str[] = {ESC,'[',PP_INS_DEC,'v'};
static char init_cursor_canon_str[] = {ESC,'[','0','d','\015'};
/* Zeilenweise Graphicausgabe */
static char send_graphic_1_canon_str[] = {ESC,'[',PP_INS_DEC,';'}; /* die drei Befehle muessen */
static char send_graphic_2_canon_str[] = {PP_INS_DEC,';'}; /* direkt hintereinander */
static char send_graphic_3_canon_str[] = {PP_INS_DEC,'.','r'}; /* gesendet werden! */
/* Cursor Move Befehle (0==1) Das obige Kommando setzt den Cursor nicht! */
static char move_down_canon_str[] = {ESC,'[',PP_INS_DEC,'e'};
static char move_left_canon_str[] = {ESC,'[',PP_INS_DEC,'l'};
static char move_right_canon_str[] = {ESC,'[',PP_INS_DEC,'a'};
static char move_up_canon_str[] = {ESC,'[',PP_INS_DEC,'k'};
static char move_to_left_border_str[] = {'\015'};
/* am Ende einer jeden Seite (das FF muss schon drausen sein!!) */
static char end_page_canon_str[] = {ESC,'[','2','1','%','z',
ESC,'P','1','y','I','d','l','e',ESC,'\\'};
/* einmal am Ende: nichts zu schicken! */
/* einmal am Anfang */
#define init_canon() hp_str_n(init_canon_str,PP_NORMAL_STRING)
#define set_display_canon() hp_str_n(set_display_canon_str,PP_NORMAL_STRING)
/* einmal am Anfang jeder Seite */
#define set_portrait_mode_canon() hp_str_n(set_portrait_mode_canon_str,PP_NORMAL_STRING)
#define set_landscape_mode_canon() hp_str_n(set_landscape_mode_canon_str,PP_NORMAL_STRING)
#define set_nr_of_copies_canon(n) hp_str_n(set_nr_of_copies_canon_str,(n))
#define init_cursor_canon() hp_str_n(init_cursor_canon_str,PP_NORMAL_STRING)
/* Zeilenweise Graphikausgabe */
#define send_graphic_1_canon(n) hp_str_n(send_graphic_1_canon_str,(n))
#define send_graphic_2_canon(n) hp_str_n(send_graphic_2_canon_str,(n))
#define send_graphic_3_canon(n) hp_str_n(send_graphic_3_canon_str,(n))
/* Cursor Move Befehle (0==1) Das obige Kommanodo setzt den cursor nicht */
#define move_down_canon(n) hp_str_n(move_down_canon_str,(n))
#define move_left_canon(n) hp_str_n(move_left_canon_str,(n))
#define move_right_canon(n) hp_str_n(move_right_canon_str,(n))
#define move_up_canon(n) hp_str_n(move_up_canon_str,(n))
#define move_to_left_border() hp_str_n(move_to_left_border_str,PP_NORMAL_STRING)
/* am Ende einer jeden Seite (das FF muss schon da gewesen sein!!) */
#define end_page_canon() hp_str_n(end_page_canon_str,PP_NORMAL_STRING)
/* einmal am Ende: nichts zu schicken! */
/***** HP - DeskJet Graphic-Befehle ****************************************/
static char direction_hp_str[] = {ESC,'&','k',PP_INS_DEC,'W'};
static char end_raster_gfx_hp_str[] = {ESC,'*','r','B'};
static char set_raster_gfx_res_hp_str[] = {ESC,'*','t',PP_INS_DEC,'R'};
static char set_raster_gfx_width_hp_str[]={ESC,'*','r',PP_INS_DEC,'S'};
static char set_raster_gfx_mode_hp_str[]= {ESC,'*','b',PP_INS_DEC,'M'};
static char start_raster_gfx_hp_str[] = {ESC,'*','r','0','A'};
static char settempxofftransdatahp_str1[]
= {ESC,'*','b',PP_INS_DEC};
static char settempxofftransdatahp_str2[]
= {'x',PP_INS_DEC,'W'};
static char vert_pos_hp_str[] = {ESC,'*','p','+',PP_INS_DEC,'Y'};
static char set_draft_print_hp_str[] = {ESC,'*','r','1','Q'};
static char set_norm_print_hp_str[] = {ESC,'*','r','0','Q'};
static char transfer_data_hp_str[] = {ESC,'*','b',PP_INS_DEC,'W'};
static char compress_data_hp_str[] = {ESC,'*','b','2','m',PP_INS_DEC,'W'};
static char set_nr_of_copies_hp_str[] = {ESC,'&','l',PP_INS_DEC,'X'};
static char reset_nr_copies_hp_str[] = {ESC,'&','l','1','X'};
static char init_cursor_hp_str[] = {ESC,'*','p','0','x','0','Y'};
static char init_resolution_hp_str[] = {ESC,'*','t',PP_INS_DEC,'R'};
static char init_position_hp_str[] = {ESC,'*','r','0','f','0','A'};
#define print_uni_bi_direct_hp(n) \
hp_str_n(direction_hp_str,(n))
#define end_raster_graphics_hp() \
hp_str_n(end_raster_gfx_hp_str,PP_NORMAL_STRING)
#define set_raster_graphics_res_hp(res) \
hp_str_n(set_raster_gfx_res_hp_str,(res))
#define set_raster_graphics_width_hp(width) \
hp_str_n(set_raster_gfx_width_hp_str,(width))
#define set_raster_graphics_mode_hp(mode) \
hp_str_n(set_raster_gfx_mode_hp_str,(mode))
#define start_raster_graphics_hp() \
hp_str_n(start_raster_gfx_hp_str,PP_NORMAL_STRING)
#define set_temp_x_off_trans_data_hp(xoffset, number) \
hp_str_n(settempxofftransdatahp_str1,(xoffset)), \
hp_str_n(settempxofftransdatahp_str2,(number))
#define vert_pos_hp(blank_lines) \
hp_str_n(vert_pos_hp_str,(blank_lines))
#define set_draft_print_hp() \
hp_str_n(set_draft_print_hp_str,PP_NORMAL_STRING)
#define set_norm_print_hp() \
hp_str_n(set_norm_print_hp_str,PP_NORMAL_STRING)
#define transfer_data_hp(nr) \
hp_str_n(transfer_data_hp_str,(nr))
#define compress_data_hp(nr) \
hp_str_n(compress_data_hp_str,(nr))
#define set_nr_of_copies_hp(nr) \
hp_str_n(set_nr_of_copies_hp_str, (nr))
#define init_cursor_hp() \
hp_str_n(init_cursor_hp_str, PP_NORMAL_STRING)
#define init_resolution_hp(dpi) \
hp_str_n(init_resolution_hp_str, (dpi))
#define init_position_hp() \
hp_str_n(init_position_hp_str, PP_NORMAL_STRING)
#define reset_nr_of_copies_hp() \
hp_str_n(reset_nr_copies_hp_str, PP_NORMAL_STRING)
/* Hardcopy_HP
*
* The main HP hardcopy routine
*/
static void Hardcopy_HP(struct bitmap *bmap, long lineno, int draft)
{
char *in_line_ptr;
short lines, map_width, blank_lines, i;
short left_border, right_border;
short is_LaserJet;
is_LaserJet = (Printer->pp_printer == LASERJET) || (Printer->pp_printer == LASERJET4);
map_width = ((int)bmap->width) >> 3; /* /8 in Bytes */
#if 0
/* end_raster_graphics_hp(); warum? */
if (Printer->pp_printer == CHEAPDJ) { /*DRAFT_CHEAP||HIGH_Q_CHEAP*/
set_draft_print_hp();
}
set_raster_graphics_res_hp(Printer->pp_xdpi); /*P_DRAFT_Q||DRAFT_CHEAP*/
set_raster_graphics_mode_hp(0); /* full graphics mode */
start_raster_graphics_hp();
#endif
blank_lines = Skip_buffered; /* counter for the blank lines */
Skip_buffered = 0;
for (lines=0; lines<(int)min(bmap->height,lineno); lines++) {
if ((lines & 63) == 63) MUISetGauge(PrintedLines+lines);
in_line_ptr = ((char*)(bmap->pixptr))+(long)((long)lines*(long)map_width);
left_border = search_left_border(in_line_ptr,map_width);
if (left_border == map_width) { /* the current line is totaly blank */
blank_lines++;
Chk_Abort(); /* test ^C */
}
else { /* the current line isn't blank */
if (blank_lines > 0) {
/* skip the blank lines */
if (!is_LaserJet && blank_lines > 6) {
/* grosse Luecke -> skip */
end_raster_graphics_hp();
vert_pos_hp( draft ? 3*blank_lines : blank_lines);
start_raster_graphics_hp();
}
else {
/* kleine Luecke -> Leerzeilen */
for (i=0; i<blank_lines; i++) {
transfer_data_hp(0); /* skip line */
/*directout((char)0);*/
}
}
blank_lines = 0;
}
if (o_optimize) {
/* use compession alg */
CompressLine(in_line_ptr, map_width);
}
else {
right_border = search_right_border(in_line_ptr,map_width);
if (left_border > 0 && !is_LaserJet) {
/* skip blank left border */
set_temp_x_off_trans_data_hp(left_border<<3,right_border-left_border);
in_line_ptr += (long)left_border;
}
else {
transfer_data_hp(right_border); /* alles bis right border */
left_border = 0;
}
#ifdef AMIGA
if (bufferz + right_border-left_border < bufflen) {
CopyMem(in_line_ptr, buffer+bufferz, right_border-left_border);
bufferz += right_border-left_border;
}
else {
register short bytes;
for (bytes=left_border; bytes<right_border; bytes++) { /* bytes of line */
directout((char)*in_line_ptr++);
}
}
#else
{
register short bytes;
for (bytes=left_border; bytes<right_border; bytes++) { /* bytes of line */
directout((char)*in_line_ptr++);
}
}
#endif
} /* else optimize */
} /* else skip blank line */
} /* end for lines */
if (blank_lines > 0) {
Skip_buffered = blank_lines; /* fuehre den Skip erst spaeter aus! */
}
#if 0
end_raster_graphics_hp();
if (Printer->pp_printer == CHEAPDJ) {
set_norm_print_hp();
}
#endif
}
/* Hardcopy_Canon
*
* The main Canon hardcopy routine
*/
static void Hardcopy_Canon(struct bitmap *bmap, long lineno, int draft)
{
char *in_line_ptr;
short lines, map_width, blank_lines;
short left_border, right_border, blank_border, blank_bytes;
short cursor_moved = FALSE;
short is_blank_line;
map_width = ((int)bmap->width) >> 3; /* /8 in Bytes */
blank_lines = Skip_buffered; /* counter for the blank lines */
Skip_buffered = 0;
for (lines=0; lines<(int)min(bmap->height,lineno); lines++) {
if ((lines & 63) == 63) MUISetGauge(PrintedLines+lines);
in_line_ptr = ((char*)(bmap->pixptr))+(long)((long)lines*(long)map_width);
left_border = search_left_border(in_line_ptr,map_width);
if (left_border == map_width) { /* the current line is totaly blank */
is_blank_line = TRUE;
blank_lines++;
Chk_Abort(); /* test ^C */
}
else { /* the current line isn't blank */
is_blank_line = FALSE;
if (blank_lines > 0) {
/* skip the blank lines */
move_down_canon(blank_lines);
blank_lines = 0;
}
right_border = search_right_border(in_line_ptr,map_width);
do {
if (o_optimize) {
/* hier soll optimiert werden.. :) */
/* suche wie weit ausgegeben werden soll. also von left_border -- blank_border
* blank_border gibt an, wo das Schwarze aufhoert.
* Falls blank_border == right_border, dann ist die Zeile nach der letzten
* Ausgabe fertig ausgegeben.
* Es wird also von left_b bis nach blank_b ausgegeben.
* Dann wid in_line_ptr auf blank_b gesetzt. (Achtung auf Allignment!!!!!!)
*
* Die Werte left_border, right_border und blank_border sind *immer*
* RELATIV zun in_line_ptr!!
*/
blank_border = search_next_blank(&blank_bytes, in_line_ptr, left_border, right_border);
}
else {
blank_bytes = 0; /* wird nicht gebraucht */
blank_border = right_border; /* die ganze Zeile wird ausgegeben */
}
if (left_border > 0) {
/* skip blank left border */
move_right_canon(left_border<<3);
send_graphic_1_canon((blank_border-left_border));
send_graphic_2_canon((blank_border-left_border));
send_graphic_3_canon(Printer->pp_xdpi);
in_line_ptr += (long)left_border; /* linken Bereich skippen */
cursor_moved = TRUE;
}
else {
send_graphic_1_canon(blank_border);
send_graphic_2_canon(blank_border);
send_graphic_3_canon(Printer->pp_xdpi);
}
/* und nun Ausgabe der zu druckenden Bytes (von left_border bis blank_border */
# ifdef AMIGA
if (bufferz + blank_border-left_border < bufflen) {
CopyMem(in_line_ptr, buffer+bufferz, blank_border-left_border);
bufferz += blank_border-left_border;
}
else {
register short bytes;
for (bytes=left_border; bytes<blank_border; bytes++) { /* bytes of line */
directout((char)*in_line_ptr++);
}
}
# else
{
register short bytes;
for (bytes=left_border; bytes<blank_border; bytes++) { /* bytes of line */
directout((char)*in_line_ptr++);
}
}
# endif
in_line_ptr += blank_border-left_border; /* ausgegebenen Bereich skippen */
if (blank_border<right_border) {
/* nun wird der left_border so gesetzt, dass der leere Bereich geskipt wird */
/* in_line_ptr zeigt ja auf das erste freie Byte */
left_border = blank_bytes;
}
else {
left_border = 0;
}
right_border -= blank_border + left_border; /* rechten Rand an die Anzahl der bearbeiteten Bytes anpassen */
} while (right_border != 0);
} /* else skip blank line */
if (cursor_moved) {
cursor_moved = FALSE;
move_to_left_border();
}
if (!is_blank_line) { /* keine leere Zeile */
move_down_canon(1);
}
} /* end for lines */
if (blank_lines > 0) {
Skip_buffered = blank_lines; /* fuehre den Skip erst spaeter aus! */
}
}
/*
* Sucht den naechsten freien Bereich von wenigstens 20 Bytes
*
* Gibt den rechten Rand des schwarzen Bereichs aus.
* Die blank_bytes gibt an, wieviele Bytes nach dem rechten Rand weiss sind.
*
*/
static short search_next_blank(short * blank_bytes, char * line_ptr, short left_border, short right_border)
{
/* zuerst wird der schwarze Bereich geskippt.
* Die Anzahl der Bytes ergibt den Rueckgabewert.
* Dann wird der weisse Bereich geskippt.
* Falls er groesser als 20 Bytes ist, so wird die Anzahl die blank_bytes.
* Falls nicht, so wird das zum schwarzen Bereich gezaehlt und von vorne begonnen.
*/
char * line = line_ptr + left_border;
int align = (int)line & 0x3;
int blank_lw;
long *Line, *RLine;
RLine = (long *)((int)(line_ptr + right_border) & 0xFFFFFFFC);
if (*line == 0) {
Fatal(20, MSG_INTERNAL_ERROR_W_ARG,"(in search_next_blank)");
}
/* falls im align eine schwarz-weiss-schwarz Kombination uebersprungen
* wird, so macht das nichts, da das ja korrekt ausgedruckt wird.
*/
line += align; /* nun muesste line 4 Byte aligned sein */
Line = (long *)line;
do {
/* skip black */
while (Line < RLine && *Line != 0) Line++;
if (Line == RLine) {
/* black bis rborder ?
* falls im Ralign eine schwarz-weiss Kombination ist, so macht das nichts,
* da diese ja korrekt ausgedruckt wird!
*/
*blank_bytes = 0; /* beliebig */
return right_border; /* alles schwartz */
}
blank_lw = 0;
/* skip white */
while (Line < RLine && *Line == 0) {
Line++;
blank_lw++;
}
} while (Line < RLine && blank_lw < 5);
if (Line == RLine) {
/* d.h. weiss geht bis zum right_border...sollte eigentlich nicht sein.
* ist vielleicht nur eine kleine Kombination, bzw. im Ralign mag noch
* etwas schwartz sein. Egal, gib alles aus...
*/
*blank_bytes = 0; /* beliebig */
return right_border; /* alles schwartz */
}
*blank_bytes = blank_lw * 4;
return (short)((char *)Line - line_ptr);
}
void initialize_canon_printer(void)
{
init_canon();
if (landscape) {
set_landscape_mode_canon();
}
else {
set_portrait_mode_canon();
}
}
void end_canon_printer(void)
{
end_page_canon();
}
static void CompressLine(char *buf, short len)
{
register char *ptr;
short b, c, l;
/* Strip trailing zeros */
while (len && buf[len - 1] == 0) len--;
/* Compression */
ptr = compbuf;
l = 0;
while (len--)
{ b = *buf++; /* Pick up a byte */
c = 1;
while (len && *buf == b && c < 128)
{ c++;
buf++;
len--; /* See if it begins a run */
}
if (c == 2 && /* If a two byte run */
l > 0 && /* and preceeded by literals */
l <= 125 && /* and not more than 125 of them */
(len <= 2 || /* and no more than 2 bytes left */
*buf != *(buf + 1))) /* or not followed by a run */
{ c = 1; /* Then make it a literal */
buf--;
len++;
}
if (c == 1) /* If not a run */
{ l++; /* Then it must be a literal */
c = 0;
}
if (l > 0 && /* If we have some literals */
(c > 1 || /* and beginning a run */
l == 127 || /* or reached 127 */
len == 0)) /* or no more bytes left */
{ *ptr++ = l - 1; /* Then write out the literals */
memcpy(ptr, buf - c - l, l);
/* CopyMem(ptr, buf - c - l, l); */
ptr += l;
l = 0;
}
if (c > 1) /* If we have a run */
{ *ptr++ = 1 - c; /* Then write it */
*ptr++ = b;
}
}
len = ptr - compbuf;
compress_data_hp(len);
buf = compbuf;
#ifdef AMIGA
if (bufferz + len < bufflen) {
CopyMem(buf, buffer+bufferz, len);
bufferz += len;
}
else {
register short bytes;
for (bytes=0; bytes<len; bytes++) { /* bytes of line */
directout((char)*buf++);
}
}
#else
{
register short bytes;
for (bytes=0; bytes<len; bytes++) { /* bytes of line */
directout((char)*buf++);
}
}
#endif
}
/***************************************************************************/
/***** N A D E L *****/
/***************************************************************************/
/***** Standard Graphic-Befehle **** **** **** **** **** ****/
#if defined(COMMON_BUFFERS) && defined(AMIGA)
/* Das Splitten der Grafiksequenzen ist noch nicht eingebaut. Also diese
Option vermeiden. */
static void prepare_for_gfx(int nr)
{
if (PrnIndex) {
PrnBuffered=nr; /* wir puffern schon */
}
else {
if (bufferz + MAXchars + 5 >= bufflen) {
make_room();
}
/* MAXchars so etwas wie map_width*printer_group ... */
PrnBuffer=&buffer[bufferz+5]; /* 5 Zeichen freihalten */
}
}
#else /* COMMON_BUFFERS */
/* prepare_for_gfx
*
* The next sequence will be graphics, but we buffer it. We only print
* the whole sequence once we know how many bytes there are
*/
static void prepare_for_gfx(int nr)
{
if (Skip_buffered) skip_lines();
#if defined(HARDDEB)
printf("J:\t prepare PrnBuf %d\n",nr);
#endif
PrnBuffered = nr;
}
#endif /* COMMON_BUFFERS */
/* print_clear_buffer
*
* output one block(=piece WP_GROESSE large of bitmap) of data and
* reset the block used
*
* gibt Puffer aus und setzt ihn auf 0
*/
static void print_clear_buffer(char block[MAX_GROUPING][WP_GROESSE])
{
int rows,j;
for (j = WP_GROESSE-1; 0 <= j; j--) {
for (rows = 0; rows < Printer->pp_grouping; rows++) {
quickgfxout((char)block[rows][j]);
}
}
memset(block, 0, sizeof(char[MAX_GROUPING][WP_GROESSE]));
}
#define print_uni_bi_direct_nadel(n) \
string_out(ESCU, sizeof(ESCU), UNIDIR == (n) ? 1 : 0)
#define move_head_to_nadel(pos) \
string_out(ESCdollar, sizeof(ESCdollar), (pos))
/* print_empty_words
*
* skip white areas using one of the predefined methods.
* ueberspringt Leerstellen
*/
static void print_empty_words(int empty, int toword)
{
int method,
rest, point, spaces; /* fuer jede Methode, (1 Inch hier 60 point) */
short num, den;
method = Printer->pp_method;
switch(method) {
case METHOD_MOVE_POINT:
num = toword * WP_GROESSE; den = pp_dots_per_point;
point = num / den;
rest = num % den;
break;
case METHOD_USE_SPACES:
num = empty * WP_GROESSE; den = pp_dots_per_space;
spaces = num / den;
if ( empty == toword || SPACES_GUT <= spaces)
rest = num % den;
else {
rest = empty * WP_GROESSE;
method = METHOD_GFX_ONLY;
}
break;
case METHOD_GFX_ONLY:
if (empty == toword) {
num = empty * WP_GROESSE; den = pp_dots_per_space;
spaces = num / den;
rest = num % den;
method = METHOD_USE_SPACES;
}
else
rest = empty * WP_GROESSE;
break;
}
switch(method) {
case METHOD_USE_SPACES:
#if defined(HARDDEB)
printf("J: Spaces %d\n",spaces);
#endif
for (; 0 < spaces; spaces--) {
getout(' ');
}
break;
case METHOD_MOVE_POINT: /* Speziellen Befehl ausfuehren */
move_head_to_nadel(point); /* 1 inch <-> 60 point */
break;
}
if (rest) { /* anschliessend Methode 0: mit 0 auffuellen */
int i;
prepare_for_gfx(Printer->pp_grouping * rest);
for (i=Printer->pp_grouping*rest; 0<i; i--) quickgfxout('\0');
}
}
/* skip_lines
*
* Skip lines that have been buffered. Note that the graphics buffer
* must have been flushed already.
*/
static void skip_lines()
{
int lines;
#if defined(HARDDEB)
printf("J: Skip lines %d\n",Skip_buffered);
#endif
for (lines = Skip_buffered; 0 < lines; lines -=255) {
string_directout(Printer->pp_skip_cmd,
Printer->pp_skip_cmd_len,
255 < lines ? 255 : lines & 0xff);
}
Skip_buffered = 0;
}
/* prepare_skip
*
* We even buffer line skips! If gfx are buffered, flush them.
*/
static void prepare_skip(skips)
{
if (PrnIndex) print_buffered_line();
#if defined(HARDDEB)
printf("J: Buffer skip %d\n",skips);
#endif
Skip_buffered += skips;
}
/* 0 == pass: Zeile wurde uebersprungen, voller Zeilenvorschub.
* (gibt es eigentlich nicht mehr)
* i.allg. werden zuerst kleine skips ausgefuehrt, dann kommt fuer
* printer_passes == pass ein grosser.
*/
#define prepare_pass(a,b) /* nothing */
#define end_pass(pass, printer) prepare_skip(Printer->pp_skip[(pass)-1])
/* print_buffered_line
*
*
* We have buffered all the graphics of the current line, (we know how
* many bytes there are), and we flush the buffer.
*/
static void print_buffered_line()
{
#ifdef AMIGA
/* damit CopyMem oft angewendet werden kann, wird *
* ein ziemlich voller Puffer geleert. *
* +5 wegen den noch folgenden Graphikbefehlen. */
if (bufferz + PrnIndex + 5 >= bufflen) make_room();
#endif
string_directout(Printer->pp_gfx_cmd,
Printer->pp_gfx_cmd_len,
PrnIndex / Printer->pp_grouping);
#if defined(HARDDEB)
printf("J: #Graphics: %d\n",PrnIndex);
#endif
#ifdef AMIGA
if (bufferz + PrnIndex >= bufflen) { /* a really small buffer ! */
char *p;
for (p = PrnBuffer; PrnIndex; PrnIndex--, p++) directout(*p);
}
else {
CopyMem(PrnBuffer,&buffer[bufferz],(ULONG)PrnIndex);
bufferz += PrnIndex;
PrnIndex = 0;
}
#else /* AMIGA */
{
char *p;
for (p = PrnBuffer; PrnIndex; PrnIndex--, p++) directout(*p);
}
#endif /* AMIGA */
/* PrnIndex ist nun wieder 0 */
}
/*---------------------------------------------------------------------*/
/* this is the main function ! */
static void Hardcopy_standard(struct bitmap *bmap, long lineno, int draft)
{
char block[MAX_GROUPING][WP_GROESSE];
int usemap_width, lines;
const int bitmap_width = ((int)bmap->width+(WP_GROESSE-1)) / WP_GROESSE;
WP_TYP *bmap_base1;
memset(&(block[0]),0,sizeof(block));
usemap_width = (bmap->width > pp_max_dots_line) ? pp_max_dots_line /* abrunden */ / WP_GROESSE : bitmap_width;
//printf("bmap->width = %d, bitmap_width = %d, usemap_width = %d\n",
// bmap->width, bitmap_width, usemap_width);
#if 0 || defined(HARDDEB)
Message("J:bmap size %ldx%ld,\n use %dx%ld.\n",
bmap->width, bmap->height,
usemap_width*WP_GROESSE, lineno);
#endif
for (lines = 0, /* for every line */
bmap_base1 = ((WP_TYP *)(bmap->pixptr))
;lines < (int)(min(bmap->height,lineno))
;lines += Printer->pp_passes_height, /* (was height) */
bmap_base1 += (long)(Printer->pp_passes_height*bitmap_width)) { /* MULU/S.W Befehl */
int pass;
WP_TYP *bmap_base2;
#if 0 && defined(HARDDEB)
printf("J:Line %d\n",lines);
#endif
MUISetGauge(PrintedLines+lines);
for (pass=1, /* for each pass */
bmap_base2 = bmap_base1
;pass <= Printer->pp_passes
;pass++,
bmap_base2 += bitmap_width) {
int words;
int full = 0;
WP_TYP * in_line_ptr = bmap_base2;
#if 0 && defined(HARDDEB)
printf("J: Pass %d\n",pass);
#endif
prepare_pass(pass,Printer);
for (words=0; words<usemap_width; words++) { /* words of line */
/* first skip blank areas to improve speed */
if (full == 0) {
int empty;
#if 0 && defined(HARDDEB)
printf("J: @word %d\n",words);
#endif
empty = jskip_blank_words_std(in_line_ptr,
Printer->pp_passes_height,
bitmap_width * Printer->pp_passes,
usemap_width-words,
Printer->pp_passes);
words += empty; /* skip blank words */
#if 0 && defined(HARDDEB)
printf("J: empty %d\n",empty);
#endif
if (words >= usemap_width) break; /* EOL */
if (empty > 0) {
in_line_ptr += empty;
print_empty_words(empty, words);
}
if (Printer->pp_method == METHOD_GFX_ONLY)
full = jsearch_right_border_std(
in_line_ptr,
Printer->pp_passes_height,
bitmap_width * Printer->pp_passes,
usemap_width-words,
Printer->pp_passes);
else
full = jsearch_length_text_std(
in_line_ptr,
Printer->pp_passes_height,
bitmap_width * Printer->pp_passes,
usemap_width-words,
Printer->pp_passes);
#if 0 && defined(HARDDEB)
printf("J: full %d\n",full);
#endif
prepare_for_gfx(full*WP_GROESSE*Printer->pp_grouping);
}
full--;
/* now transform bitmap to printer-data */
{ /* make these variables local */
WP_TYP *ptr;
char *print;
unsigned char mask;
int j, rows;
ptr = in_line_ptr++;
for (rows=0; rows < Printer->pp_grouping; rows++) {
print = &(block[rows][0]); /* pointer aliasing */
for (j=0, mask=128; j<8; j++, mask>>=1) {
int i;
WP_TYP read_word;
read_word = *ptr;
ptr += Printer->pp_passes*bitmap_width;/* `printer_passes' mal */
if (read_word) {
for (i=0; i<WP_GROESSE; i++) /* transf. a word */
if (take_Bit(i,read_word) != 0) print[i] |= mask;
}
}
}
} /* end local */
/* now send the data */
print_clear_buffer(block);
}
/* end of words, now in pass */
end_pass(pass, Printer);
Chk_Abort(); /* erst nach end_pass() */
}
/* end of pass, now in line */
}
/* end of line */
}
/***** misc functions ****************************************************/
/* sucht wortweise nach der ersten Spalte != 0 */
static int jskip_blank_words_std(WP_TYP * ptr, int lines,
int bitmap_offset, int max, int line_offset)
{
int nr;
WP_TYP *p;
for (nr=0, p=ptr ; nr < max ; nr++, p=++ptr) {
int i;
for (i=0 ; i<lines ; i+=line_offset, p+=bitmap_offset)
if (0 != *p) return nr;
}
return nr;
}
/* suche rueckwaerts ab rechtem Rand */
static int jsearch_right_border_std(WP_TYP *ptr, int lines,
int bitmap_offset, int max, int line_offset)
{
int nr;
WP_TYP *p;
ptr += max-1;
for (nr=max, p=ptr ; 0 < nr ; nr--, p=--ptr) {
int i;
for (i=0 ; i<lines ; i+=line_offset, p+=bitmap_offset)
if (0 != *p) return nr;
}
return 0; /* is never the case */
}
/* sucht wortweise nach der ersten Spalte == 0 */
static int jsearch_length_text_std(WP_TYP *ptr, int lines,
int bitmap_offset, int max, int line_offset)
{
int nr;
WP_TYP *p;
/* fange gleich mit 1 an, weil erstes Wort bekanntlich !=0 */
for (nr=1, p=++ptr ; nr < max ; nr++, p=++ptr) {
int i;
for (i=0 ; i<lines && 0==*p ;
i +=line_offset, p += bitmap_offset) ;
if (i>=lines) break;
}
return nr;
}
#if 0
/*** suche erstes Byte != 0 von links ***/
static short search_left_border(char *in_line_ptr, short map_width)
{
register short i;
for (i=0; i<map_width && *in_line_ptr == 0; i++, in_line_ptr++);
return i;
}
#else
static short search_left_border(char *in_line_ptr, short map_width)
{
register short i;
register short width;
register long *ptr;
width = map_width >> 2;
ptr = (long *)((long)in_line_ptr & 0xFFFFFFFC); /* sollte eigentlich nicht noetig sein */
for (i=0; i<width && *ptr == 0; i++, ptr++);
if (i == width) return map_width;
i = i << 2;
if (*ptr & 0xFF000000) return i;
if (*ptr & 0x00FF0000) return (short)(i+1);
if (*ptr & 0x0000FF00) return (short)(i+2);
return (short)(i+3);
}
#endif
/*** suche erstes Byte != 0 von rechts ***/
static short search_right_border(char *in_line_ptr, short map_width)
{
register short i;
in_line_ptr += (long)((long)map_width-1L);
for (i=map_width-1; *in_line_ptr == 0 && i>0; i--, in_line_ptr--);
if (*in_line_ptr != 0) {
i++;
}
return i;
}
/*************************************************************************/
/** Schnittstelle nach aussen: **/
void FormFeed(void)
{
Skip_buffered = 0;
if (Printer->pp_printer == CANON) {
; /* beim Caonon wird das FF schon direkt nach dem latzten Pass ausgegeben! */
}
else {
#ifdef ATARI
if (Printer->pp_printer != SLM_804) {
getout(FF);
}
#else
#if 0 /* generic macht nun schon selber ein FF */
# ifdef AMIGA
if ((Printer->pp_special & SPECIAL_PREFS) && (ToDo & DO_REALPRINT)) {
FormFeedGeneric();
}
else
# endif
if (buffer) getout(FF);
#else
if (!((Printer->pp_special & SPECIAL_PREFS) && (ToDo & DO_REALPRINT)) && buffer) {
getout(FF);
}
#endif
#endif /* ATARI */
}
nr_printed_pages++; /* wieder eine Seite mehr ausgegeben */
}
/* Hardcopy
*
* The main dispatcher!
*/
void Hardcopy(struct bitmap *bmap, long lineno, int first_pass, int last_pass)
{
if (first_pass) PrintedLines = 0;
#if defined(HARDDEB)
if (NULL==Printer)
Fatal(20,"Hardcopy(): Printer not initialized !\n");
#endif
PrnBuffered=0;
PrnIndex=0;
#if defined(HARDDEB)
printf("J:Hardcopy(): printer_flags: %X, printer_group: %d, quality: %ld\n",
Printer->pp_flags, Printer->pp_grouping, draft);
#endif
switch (Printer->pp_printer)
{
case CANON:
if (first_pass) {
set_nr_of_copies_canon(ncopies);
/* init_cursor_canon(); */
set_display_canon();
}
Hardcopy_Canon(bmap,lineno,draft);
if (last_pass) {
getout(FF);
}
break;
case DESKJET:
case CHEAPDJ:
case LASERJET:
case LASERJET4:
{
const int is_LaserJet = (Printer->pp_printer == LASERJET) ||
(Printer->pp_printer == LASERJET4);
if (o_optimize && compbuf == NULL) {
int compsize;
compsize = (((int)bmap->width) >> 3) + (((int)bmap->width) >> 3) / 128 + 2;
compbuf = xmalloc(compsize);
}
if (first_pass) {
if (is_LaserJet) {
set_nr_of_copies_hp(ncopies);
}
init_cursor_hp();
init_resolution_hp(Printer->pp_xdpi);
init_position_hp();
if (Printer->pp_printer == CHEAPDJ) { /*DRAFT_CHEAP||HIGH_Q_CHEAP*/
set_draft_print_hp();
}
if (!is_LaserJet) { /* das geht nur bei den DeskJets */
if (unidirect) {
print_uni_bi_direct_hp(UNIDIR);
}
set_raster_graphics_width_hp((int)bmap->width);
}
}
if (landscape) {
Querdruck(bmap, Printer->pp_passes_height, draft, Hardcopy_HP);
}
else {
Hardcopy_HP(bmap,lineno,draft);
}
if (last_pass) {
end_raster_graphics_hp();
if (is_LaserJet) {
reset_nr_of_copies_hp();
}
}
}
break;
#ifdef AMIGA
case GENERIC_PRINTER:
if (landscape) {
Fatal(5,MSG_NO_LAND_WITH_GENERIC);
}
else {
HardcopyGeneric(bmap,lineno,draft,last_pass);
}
break;
#endif
#ifdef ATARI
case SLM_804:
if (landscape)
Fatal(5,"Can't print in landscape modus!");
else
Hardcopy_SLM(bmap,lineno,draft);
break;
#endif
default:
if (Printer->pp_grouping) { /* Use Hardcopy_standard() routine */
print_uni_bi_direct_nadel(unidirect ? UNIDIR : BIDIR);
if (landscape)
if (Printer->pp_xdpi == Printer->pp_ydpi)
Querdruck(bmap, Printer->pp_passes_height<<1, draft, Hardcopy_standard);
else
Warning(MSG_NO_LAND_XDPI_YDPI);
else
Hardcopy_standard(bmap,lineno,draft);
}
break;
}
PrintedLines += min(bmap->height,lineno);
}
/* Bemerkungen:
o Der Code fuer COMMON_BUFFERS ist noch nicht fertiggestellt, man muss
naemlich sicherstellen, dass der Puffer auch gross genug ist.
*/