home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / driver / print / newhard.c < prev    next >
C/C++ Source or Header  |  1994-06-07  |  43KB  |  1,561 lines

  1. /*
  2. **    This file generated by localize 2.9 (AmigaDOS 2.1) from newhard.c
  3. */
  4. /****************************************************************************/
  5. /*                                        */
  6. /*     newhard.c                                */
  7. /*                                        */
  8. /*    Ein Ersatz fuer hardcopy.c.                        */
  9. /*    Druckt die Bitmap in 180dpi oder 360dpi auf einen NEC-P6        */
  10. /*    oder in 100dpi/300dpi auf einen HP-DESKJET.                */
  11. /*    Vorteil gegenueber hardcopy.c:                        */
  12. /*        - schneller (30%-50%)                        */
  13. /*        - besser kommentiert (zumindestens ich versteh's :-)        */
  14. /*                                        */
  15. /*                                  26.11.89 (hes)      */
  16. /*                                        */
  17. /*    Erweiterung auf EPSON-FX und kompatible 9-Nadel-Drucker            */
  18. /*    mit 120x72dpi (DRAFT) oder 240x216dpi (HQ)                */
  19. /*                                        */
  20. /*                                  05.02.90 (kb)       */
  21. /*                                        */
  22. /*    Einfuegen des Atari Laser Printer Treibers                */
  23. /*                                        */
  24. /*                                  28.03.90 (rbs)      */
  25. /*                                        */
  26. /*    Verbesserung (?) der NEC und Epson Treiber                */
  27. /*                            30.11.90 (jch)        */
  28. /*                                        */
  29. /****************************************************************************/
  30.  
  31. #include "defines.h"
  32.  
  33. #include <stdio.h>
  34.  
  35. #include <stdlib.h>
  36. #include <stddef.h>
  37.  
  38. #include <string.h>
  39. #define min(a,b) __builtin_min(a,b)
  40.  
  41. #include "globals.h"
  42. #include "bitmap.h"
  43.  
  44. #ifdef ATARI
  45. #  include <tos.h>
  46. #  define Chk_Abort()
  47. #endif
  48.  
  49. #ifdef AMIGA
  50. # include <dos.h>
  51. # include <clib/exec_protos.h>
  52. # include <pragmas/exec_pragmas.h>
  53. extern struct ExecBase *SysBase;
  54. # include <exec/ports.h>
  55. # include <devices/printer.h>
  56. # include <exec/types.h>
  57. # include <exec/exec.h>
  58. # include "amprint.h"
  59. # include "amprint.i"
  60. #endif
  61.  
  62.  
  63. #include "prhelp.h"
  64. #include "prhelp.i"
  65. #include "newhard.i"
  66. #include "globals.i"
  67. #include "landscap.i"
  68. #include "amprhelp.i"
  69. #include "muiprint.i"
  70.  
  71.  
  72. /*
  73.  * Fuer die locale-Library:
  74.  *
  75.  * Hier duerfen *nur* die MSG_#? Nummern eingebunden werden!
  76.  * Achtung:
  77.  * Es muss/sollte 'multiple-include' erlaubt sein!
  78.  */
  79. #include "local.i"
  80.  
  81. #undef  CATCOMP_ARRAY
  82. #undef  CATCOMP_BLOCK
  83. #undef  CATCOMP_STRINGS
  84. #define CATCOMP_NUMBERS
  85. #include "localstr.h"
  86.  
  87.  
  88.  
  89.  
  90. /* global vars */
  91.  
  92. extern int is_printer_started;    /* 0: no, 1: init ok, 2: print started    */
  93.  
  94. int       Skip_buffered = 0;    /* Number of Skips to execute        */
  95. char       *PrnBuffer = NULL;    /* Pointer to local buffer        */
  96.  
  97.  
  98. /* local vars */
  99.  
  100. static int PrnIndex,        /* [0..n] Index into local buffer    */
  101.        PrnBuffered;        /* Number of chars to buffer        */
  102.  
  103. static char ESCdollar[]    = {ESC,'$',PP_INS_LOW,PP_INS_HIGH};
  104. static char ESCU[]    = {ESC,'U',PP_INS_LOW};
  105.  
  106. static char *compbuf = NULL;    /* wird fuer HP Compress Alg. benoetigt */
  107.                 /* wird mit malloc() allociert.        */
  108.  
  109. static int  PrintedLines = 0;    /* Anzahl der bereits gedruckten Zeilen */
  110.                 /* wird immer nach einem ganzen Pass aktualisiert */
  111.  
  112. /* lokale Funktionen */
  113.  
  114. #define quickgfxout(c)    PrnBuffer[PrnIndex++]=(c), PrnBuffered--
  115.  
  116. #ifdef ATARI
  117. /***** A T A R I  -  Funktionen ********************************************/
  118. #include "ataridef.h"
  119.  
  120. static void check_key                Args((void));
  121. static void directout                Args((char c));
  122.  
  123. #else
  124. /***** A M I G A  -  Funktionen ********************************************/
  125.  
  126. #ifdef HES
  127. #define directout(c)    { buffer[bufferz++] = (char)c;\
  128.               if (bufferz==bufflen) { make_room(); }}
  129. #else
  130. #define directout(c)    if (buffer[bufferz++] = (char)c,\
  131.                 bufferz==bufflen) make_room(); else /* ; follows */
  132. #endif
  133.  
  134. #endif
  135.  
  136. /***** HP - DeskJet Graphic-Befehle ****************************************/
  137.  
  138. static void  CompressLine            Args((char *buf, short len));
  139. static short search_left_border            Args((char *in_line_ptr,
  140.                               short map_width));
  141. static short search_right_border        Args((char *in_line_ptr,
  142.                               short map_width));
  143. static void Hardcopy_HP                Args((struct bitmap *bmap,
  144.                               long lineno,
  145.                               int draft));
  146. static void Hardcopy_Canon            Args((struct bitmap *bmap,
  147.                               long lineno,
  148.                               int draft));
  149. static short search_next_blank            Args((short * blank_bytes,
  150.                               char * line_ptr,
  151.                               short left_border,
  152.                               short right_border));
  153.  
  154. /***** Standard Treiber ** NEC P6 * EPSON FX * EPSON LQ *******************/
  155.  
  156. static void Hardcopy_standard(struct bitmap *bmap, long lineno, int draft);
  157. //static void prepare_pass(int pass, struct printer_para *Printer);
  158. //static void end_pass(int pass, struct printer_para *Printer);
  159. static void print_empty_words(int empty, int words);
  160. //static int  setup_graphic_mode(void);
  161. static void print_buffered_line(void);
  162. static void prepare_skip(int skips);
  163.  
  164. /***** misc functions ****************************************************/
  165.  
  166. static int  jskip_blank_words_std        Args((WP_TYP * ptr,
  167.                               int lines, 
  168.                               int b_offset,
  169.                                   int max, 
  170.                               int l_offset));
  171. static int  jsearch_right_border_std        Args((WP_TYP * ptr,
  172.                               int lines, 
  173.                               int b_offset, 
  174.                               int max, 
  175.                               int l_offset));
  176. static int  jsearch_length_text_std        Args((WP_TYP * ptr,
  177.                                int lines, 
  178.                               int b_offset, 
  179.                               int max, 
  180.                               int l_offset));
  181. static void prepare_for_gfx            Args((int nr));
  182. static void skip_lines                Args((void));
  183. static void string_directout            Args((char *string,
  184.                               int length,
  185.                               int opt_argument));
  186.  
  187. #ifdef AZTEC_C        /* Version 5.0 */
  188. #pragma regcall ( /* d0 = */ search_left_border(a0,d0) )
  189. #pragma regcall ( /* d0 = */ search_right_border(a0,d0) )
  190. #pragma regcall ( Hardcopy_HP(a0,d0,d1) )
  191. #pragma regcall ( /* d0 = */ skip_blank_words(a0,d0,d1,d2) )
  192. #pragma regcall ( /* d0 = */ search_length_text(a0,d0,d1,d2) )
  193. #endif
  194.  
  195.  
  196. /****** misc macros *******************************************************/
  197.  
  198. #define take_Bit(nr,lword)    (lword & (1L<<nr))
  199.  
  200. #ifndef LATTICE
  201. #  define min(a,b)        (((a) < (b)) ? (a) : (b))
  202. #endif
  203.  
  204.  
  205. /*    getout
  206.  *
  207.  * Output one character, taking into account all kinds of buffering.
  208.  * This is the preferred routine to use. But if you know what you are
  209.  * doing, you may as well call directout().
  210.  */
  211. void getout(char c)
  212. {
  213. #if defined(HARDDEB)
  214.   printf("J:\tgetout:(%02X), Buffered: %d, Index: %d\n",
  215.     (unsigned char)c,PrnBuffered, PrnIndex);
  216. #endif
  217.   if (PrnBuffered) quickgfxout(c);
  218.     /* Aufeinanderfolgende Grafikdaten werden zwischengespeichert */
  219.   else {
  220.     /* ev. Zeilenvorschub ausfuehren */
  221.     /* (FF wird in FormFeed() abgefangen) */
  222.     if (Skip_buffered) skip_lines();
  223.     /* keine neuen Grafikdaten mehr, ev. Puffer leeren */
  224.     if (PrnIndex) print_buffered_line();
  225.     directout(c);    /* output the initial char */
  226.   }
  227. }
  228.  
  229.  
  230. /*    string_out
  231.  *
  232.  * print a buffer of given length with getout(), accepts numeric
  233.  * argument (ex: ESC * n1 n2)
  234.  */
  235. void string_out(char *buf, int number, int opt_arg)
  236. {
  237.   for (; 0 < number; number--, buf++) {
  238.     char c;
  239. #if defined(HARDDEB)
  240.     printf("J:\tstring_out %02X",(unsigned char) *buf);
  241. #endif
  242.     switch ((unsigned char)*buf) { /* Lattice, grrr */
  243.       case PP_INS_DEC:    /* not supported here */
  244.         continue;
  245.       case PP_INS_LOW:
  246.         c = (char) opt_arg;
  247.     break;
  248.       case PP_INS_HIGH:
  249.         c = (char) (opt_arg >> 8);
  250.     break;
  251.       case PP_INS_NR100:
  252.         c = (char) ((opt_arg / 100) % 10) + '0';
  253.     break;
  254.       case PP_INS_NR10:
  255.         c = (char) ((opt_arg / 10) % 10) + '0';
  256.     break;
  257.       case PP_INS_NR1:
  258.         c = (char) (opt_arg % 10) + '0';
  259.     break;
  260.       default:
  261.         c = *buf;
  262.       }
  263. #if defined(HARDDEB)
  264.     printf(" %02X ",(unsigned char) c);
  265. #endif
  266.     getout(c);
  267.     }
  268. }
  269.  
  270. /*    string_directout
  271.  *
  272.  * print the bytes using directout() instead of getout(), accepts
  273.  * numeric argument (ex: ESC * n1 n2). You should normally use
  274.  * string_out() (buffers automatically)
  275.  */
  276. static void string_directout(char *buf, int number, int opt_arg)
  277. {
  278.   /* if (NULL==buf) Fatal(20,"Printer command missing!"); */
  279.   for (; 0 < number; number--, buf++) {
  280.     char c;
  281. #if defined(HARDDEB)
  282.     printf("J:\tstring_directout %02X",(unsigned char) *buf);
  283. #endif
  284.     switch ((unsigned char)*buf) { /* Lattice, grrr */
  285.       case PP_INS_DEC: {
  286.         register char *buf = m_string;
  287.         sprintf(buf,"%d", opt_arg);
  288.     while (*buf) directout(*(buf++));
  289.     continue;    /* for/next loop */
  290.     }
  291.       case PP_INS_LOW:
  292.         c = (char) opt_arg;
  293.     break;
  294.       case PP_INS_HIGH:
  295.         c =(char) (opt_arg >> 8);
  296.     break;
  297.       case PP_INS_NR100:
  298.         c = (char) ((opt_arg / 100) % 10) + '0';
  299.     break;
  300.       case PP_INS_NR10:
  301.         c = (char) ((opt_arg / 10) % 10) + '0';
  302.     break;
  303.       case PP_INS_NR1:
  304.         c = (char) (opt_arg % 10) + '0';
  305.     break;
  306.       default:
  307.         c = *buf;
  308.       }
  309. #if defined(HARDDEB)
  310.     printf(" %02X\n",(unsigned char) c);
  311. #endif
  312.     directout(c);
  313.     }
  314. }
  315.  
  316.  
  317. /***** A T A R I  -  Funktionen ********************************************/
  318.  
  319. #ifdef ATARI
  320. long mymask = 0x08L;
  321.  
  322. static void check_key(void)
  323. {
  324.  if ((Kbshift(-1)&mymask)==0L)
  325.    {  return; }
  326.  Fatal(5,"Program aborted by user.");
  327. }
  328.  
  329. static void directout(c)
  330.   register char c;
  331. {
  332.  while ((long)Bcostat(0)==0L)
  333.   check_key();
  334.  Bconout(0,0xff&c);
  335. }
  336.  
  337.  
  338. #ifdef TEST_IT
  339. #  include <ctype.h>
  340.   static void directout(char c);
  341.  
  342.   static void directout(c)
  343.     char c;
  344.   {
  345.     if (isprint(c)) printf("%c",c);
  346.   }
  347. #endif    /* TEST_IT */
  348.  
  349.  
  350. /***** Atari SLM 804 Ansteuerung *******************************************/
  351.  
  352. typedef struct
  353.  {
  354.   char *s_form;
  355.   short s_xmin,
  356.         s_ymin,
  357.         s_nxln,
  358.         b_width,
  359.         b_height,
  360.         d_xmin,
  361.         d_ymin,
  362.         scalefac;
  363.  } SLM;
  364.  
  365. static void Hardcopy_SLM(struct bitmap *bmap, long lineno, int draft)
  366. {
  367.   FILE *fp;
  368.   SLM o;
  369.  
  370.   fp=fopen("PRN:","w");
  371.  
  372.   o.s_form   =     (char *)bmap->pixptr;
  373.   o.s_xmin   =     (short)0;
  374.   o.s_ymin   =     (short)0;
  375.   o.s_nxln   =     (short)(bmap->width/8);
  376.   o.b_width  =     (short)bmap->width;
  377.   o.b_height =     (short)bmap->height;
  378.   o.d_xmin   =     (short)0;
  379.   o.d_ymin   =     (short)0;
  380.   o.scalefac =     (short)(draft+1);
  381. /*
  382.   o.scalefac =     (short)1;
  383. */
  384.  
  385.   check_key();
  386.   fprintf(fp,"\033\022G%08lx \n\f",&o);
  387.   fclose(fp);
  388. }
  389. #endif /* ATARI */
  390.  
  391.  
  392.  
  393.  
  394. #define hp_str_n(str,num) string_directout((str),sizeof(str),(num))
  395.  
  396.  
  397.  
  398. /***** Canon CaPSL Graphic-Befehle ****************************************/
  399.  
  400. /* einmal am Anfang */
  401. static char init_canon_str[]        = {ESC,';',ESC,'[','2','1','%','y',
  402.                        ESC,'[','1','1','h',ESC,'[','7',' ','I',
  403.                        ESC,'[','0',';','1','u'};
  404. static char set_display_canon_str[]    = {ESC,'P','1','y','J','o','b','G',ESC,'\\'};
  405.  
  406. /* einmal am Anfang jeder Seite */
  407. static char set_portrait_mode_canon_str[]  = {ESC,'[','0','p'};
  408. static char set_landscape_mode_canon_str[] = {ESC,'[','1','p'};
  409. static char set_nr_of_copies_canon_str[]   = {ESC,'[',PP_INS_DEC,'v'};
  410. static char init_cursor_canon_str[]    = {ESC,'[','0','d','\015'};
  411.  
  412. /* Zeilenweise Graphicausgabe */
  413. static char send_graphic_1_canon_str[]    = {ESC,'[',PP_INS_DEC,';'};    /* die drei Befehle muessen */
  414. static char send_graphic_2_canon_str[]    = {PP_INS_DEC,';'};        /* direkt hintereinander */
  415. static char send_graphic_3_canon_str[]    = {PP_INS_DEC,'.','r'};        /* gesendet werden! */
  416. /* Cursor Move Befehle (0==1) Das obige Kommando setzt den Cursor nicht! */
  417. static char move_down_canon_str[]    = {ESC,'[',PP_INS_DEC,'e'};
  418. static char move_left_canon_str[]    = {ESC,'[',PP_INS_DEC,'l'};
  419. static char move_right_canon_str[]    = {ESC,'[',PP_INS_DEC,'a'};
  420. static char move_up_canon_str[]        = {ESC,'[',PP_INS_DEC,'k'};
  421. static char move_to_left_border_str[]    = {'\015'};
  422.  
  423. /* am Ende einer jeden Seite (das FF muss schon drausen sein!!) */
  424. static char end_page_canon_str[]    = {ESC,'[','2','1','%','z',
  425.                        ESC,'P','1','y','I','d','l','e',ESC,'\\'};
  426.  
  427. /* einmal am Ende: nichts zu schicken! */
  428.  
  429. /* einmal am Anfang */
  430. #define init_canon()            hp_str_n(init_canon_str,PP_NORMAL_STRING)
  431. #define set_display_canon()        hp_str_n(set_display_canon_str,PP_NORMAL_STRING)
  432.  
  433. /* einmal am Anfang jeder Seite */
  434. #define set_portrait_mode_canon()    hp_str_n(set_portrait_mode_canon_str,PP_NORMAL_STRING)
  435. #define set_landscape_mode_canon()    hp_str_n(set_landscape_mode_canon_str,PP_NORMAL_STRING)
  436. #define set_nr_of_copies_canon(n)    hp_str_n(set_nr_of_copies_canon_str,(n))
  437. #define init_cursor_canon()        hp_str_n(init_cursor_canon_str,PP_NORMAL_STRING)
  438.  
  439. /* Zeilenweise Graphikausgabe */
  440. #define send_graphic_1_canon(n)        hp_str_n(send_graphic_1_canon_str,(n))
  441. #define send_graphic_2_canon(n)        hp_str_n(send_graphic_2_canon_str,(n))
  442. #define send_graphic_3_canon(n)         hp_str_n(send_graphic_3_canon_str,(n))
  443. /* Cursor Move Befehle (0==1) Das obige Kommanodo setzt den cursor nicht */
  444. #define move_down_canon(n)        hp_str_n(move_down_canon_str,(n))
  445. #define move_left_canon(n)        hp_str_n(move_left_canon_str,(n))
  446. #define move_right_canon(n)        hp_str_n(move_right_canon_str,(n))
  447. #define move_up_canon(n)        hp_str_n(move_up_canon_str,(n))
  448. #define move_to_left_border()        hp_str_n(move_to_left_border_str,PP_NORMAL_STRING)
  449.  
  450. /* am Ende einer jeden Seite (das FF muss schon da gewesen sein!!) */
  451. #define end_page_canon()        hp_str_n(end_page_canon_str,PP_NORMAL_STRING)
  452.                     
  453.  
  454. /* einmal am Ende: nichts zu schicken! */
  455.  
  456.  
  457.  
  458.  
  459. /***** HP - DeskJet Graphic-Befehle ****************************************/
  460.  
  461. static char direction_hp_str[]        = {ESC,'&','k',PP_INS_DEC,'W'};
  462. static char end_raster_gfx_hp_str[]    = {ESC,'*','r','B'};
  463. static char set_raster_gfx_res_hp_str[]    = {ESC,'*','t',PP_INS_DEC,'R'};
  464. static char set_raster_gfx_width_hp_str[]={ESC,'*','r',PP_INS_DEC,'S'};
  465. static char set_raster_gfx_mode_hp_str[]= {ESC,'*','b',PP_INS_DEC,'M'};
  466. static char start_raster_gfx_hp_str[]    = {ESC,'*','r','0','A'};
  467. static char settempxofftransdatahp_str1[]
  468.                     = {ESC,'*','b',PP_INS_DEC};
  469. static char settempxofftransdatahp_str2[]
  470.                     = {'x',PP_INS_DEC,'W'};
  471. static char vert_pos_hp_str[]        = {ESC,'*','p','+',PP_INS_DEC,'Y'};
  472. static char set_draft_print_hp_str[]    = {ESC,'*','r','1','Q'};
  473. static char set_norm_print_hp_str[]    = {ESC,'*','r','0','Q'};
  474. static char transfer_data_hp_str[]    = {ESC,'*','b',PP_INS_DEC,'W'};
  475. static char compress_data_hp_str[]      = {ESC,'*','b','2','m',PP_INS_DEC,'W'};
  476.  
  477. static char set_nr_of_copies_hp_str[]    = {ESC,'&','l',PP_INS_DEC,'X'};
  478. static char reset_nr_copies_hp_str[]    = {ESC,'&','l','1','X'};
  479. static char init_cursor_hp_str[]    = {ESC,'*','p','0','x','0','Y'};
  480. static char init_resolution_hp_str[]    = {ESC,'*','t',PP_INS_DEC,'R'};
  481. static char init_position_hp_str[]    = {ESC,'*','r','0','f','0','A'};
  482.  
  483.  
  484.  
  485. #define print_uni_bi_direct_hp(n) \
  486.                 hp_str_n(direction_hp_str,(n))
  487. #define end_raster_graphics_hp() \
  488.                 hp_str_n(end_raster_gfx_hp_str,PP_NORMAL_STRING)
  489. #define set_raster_graphics_res_hp(res) \
  490.                 hp_str_n(set_raster_gfx_res_hp_str,(res))
  491. #define set_raster_graphics_width_hp(width) \
  492.                 hp_str_n(set_raster_gfx_width_hp_str,(width))
  493. #define set_raster_graphics_mode_hp(mode) \
  494.                 hp_str_n(set_raster_gfx_mode_hp_str,(mode))
  495. #define start_raster_graphics_hp() \
  496.                 hp_str_n(start_raster_gfx_hp_str,PP_NORMAL_STRING)
  497. #define set_temp_x_off_trans_data_hp(xoffset, number) \
  498.                 hp_str_n(settempxofftransdatahp_str1,(xoffset)), \
  499.                 hp_str_n(settempxofftransdatahp_str2,(number))
  500. #define vert_pos_hp(blank_lines) \
  501.                 hp_str_n(vert_pos_hp_str,(blank_lines))
  502. #define set_draft_print_hp() \
  503.                 hp_str_n(set_draft_print_hp_str,PP_NORMAL_STRING)
  504. #define set_norm_print_hp() \
  505.                 hp_str_n(set_norm_print_hp_str,PP_NORMAL_STRING)
  506. #define transfer_data_hp(nr) \
  507.                 hp_str_n(transfer_data_hp_str,(nr))
  508. #define compress_data_hp(nr) \
  509.                 hp_str_n(compress_data_hp_str,(nr))
  510.  
  511.  
  512. #define set_nr_of_copies_hp(nr) \
  513.                 hp_str_n(set_nr_of_copies_hp_str, (nr))
  514. #define init_cursor_hp() \
  515.                 hp_str_n(init_cursor_hp_str, PP_NORMAL_STRING)
  516. #define init_resolution_hp(dpi) \
  517.                 hp_str_n(init_resolution_hp_str, (dpi))
  518. #define init_position_hp() \
  519.                 hp_str_n(init_position_hp_str, PP_NORMAL_STRING)
  520. #define reset_nr_of_copies_hp() \
  521.                 hp_str_n(reset_nr_copies_hp_str, PP_NORMAL_STRING)
  522.  
  523.  
  524. /*    Hardcopy_HP
  525.  *
  526.  * The main HP hardcopy routine
  527.  */
  528. static void Hardcopy_HP(struct bitmap *bmap, long lineno, int draft)
  529. {
  530.   char *in_line_ptr;
  531.   short lines, map_width, blank_lines, i;
  532.   short left_border, right_border;
  533.   short is_LaserJet;
  534.  
  535.   is_LaserJet = (Printer->pp_printer == LASERJET) || (Printer->pp_printer == LASERJET4);
  536.  
  537.   map_width = ((int)bmap->width) >> 3;                /* /8 in Bytes */
  538.  
  539. #if 0
  540.   /* end_raster_graphics_hp(); warum? */
  541.   if (Printer->pp_printer == CHEAPDJ) {            /*DRAFT_CHEAP||HIGH_Q_CHEAP*/
  542.     set_draft_print_hp();
  543.   }
  544.  
  545.   set_raster_graphics_res_hp(Printer->pp_xdpi);         /*P_DRAFT_Q||DRAFT_CHEAP*/
  546.  
  547.   set_raster_graphics_mode_hp(0);                /* full graphics mode */
  548.   start_raster_graphics_hp();
  549. #endif
  550.  
  551.   blank_lines = Skip_buffered;                    /* counter for the blank lines */
  552.   Skip_buffered = 0;
  553.  
  554.   for (lines=0; lines<(int)min(bmap->height,lineno); lines++) {
  555.  
  556.     if ((lines & 63) == 63) MUISetGauge(PrintedLines+lines);
  557.  
  558.     in_line_ptr = ((char*)(bmap->pixptr))+(long)((long)lines*(long)map_width);
  559.     left_border = search_left_border(in_line_ptr,map_width);
  560.     if (left_border == map_width) {                /* the current line is totaly blank */
  561.       blank_lines++;
  562.       Chk_Abort();    /* test ^C */
  563.     }
  564.     else {                            /* the current line isn't blank */
  565.       if (blank_lines > 0) {
  566.         /* skip the blank lines */
  567.         if (!is_LaserJet && blank_lines > 6) {
  568.           /* grosse Luecke -> skip */
  569.           end_raster_graphics_hp();
  570.       vert_pos_hp( draft ? 3*blank_lines : blank_lines);
  571.           start_raster_graphics_hp();
  572.         }
  573.         else {
  574.           /* kleine Luecke -> Leerzeilen */
  575.           for (i=0; i<blank_lines; i++) {
  576.             transfer_data_hp(0);    /* skip line */
  577.             /*directout((char)0);*/
  578.           }
  579.         }
  580.         blank_lines = 0;
  581.       }
  582.       if (o_optimize) {
  583.         /* use compession alg */
  584.         CompressLine(in_line_ptr, map_width);
  585.       }
  586.       else {
  587.         right_border = search_right_border(in_line_ptr,map_width);
  588.         if (left_border > 0 && !is_LaserJet) {
  589.           /* skip blank left border */
  590.           set_temp_x_off_trans_data_hp(left_border<<3,right_border-left_border);
  591.           in_line_ptr += (long)left_border;
  592.         }
  593.         else {
  594.           transfer_data_hp(right_border);        /* alles bis right border */
  595.           left_border = 0;
  596.         }
  597. #ifdef AMIGA
  598.         if (bufferz + right_border-left_border < bufflen) {
  599.           CopyMem(in_line_ptr, buffer+bufferz, right_border-left_border);
  600.           bufferz += right_border-left_border;
  601.         }
  602.         else {
  603.           register short bytes;
  604.           for (bytes=left_border; bytes<right_border; bytes++) {    /* bytes of line */
  605.             directout((char)*in_line_ptr++);
  606.           }
  607.         }
  608. #else
  609.     {
  610.           register short bytes;
  611.           for (bytes=left_border; bytes<right_border; bytes++) {    /* bytes of line */
  612.             directout((char)*in_line_ptr++);
  613.           }
  614.         }
  615. #endif
  616.       }        /* else optimize */
  617.     }        /* else skip blank line */
  618.   }        /* end for lines */
  619.  
  620.   if (blank_lines > 0) {
  621.     Skip_buffered = blank_lines;    /* fuehre den Skip erst spaeter aus! */
  622.   }
  623.  
  624. #if 0
  625.   end_raster_graphics_hp();
  626.   if (Printer->pp_printer == CHEAPDJ) {
  627.     set_norm_print_hp();
  628.   }
  629. #endif
  630. }
  631.  
  632.  
  633.  
  634.  
  635. /*    Hardcopy_Canon
  636.  *
  637.  * The main Canon hardcopy routine
  638.  */
  639. static void Hardcopy_Canon(struct bitmap *bmap, long lineno, int draft)
  640. {
  641.   char *in_line_ptr;
  642.   short lines, map_width, blank_lines;
  643.   short left_border, right_border, blank_border, blank_bytes;
  644.   short cursor_moved = FALSE;
  645.   short is_blank_line;
  646.  
  647.   map_width = ((int)bmap->width) >> 3;                /* /8 in Bytes */
  648.  
  649.  
  650.   blank_lines = Skip_buffered;                    /* counter for the blank lines */
  651.   Skip_buffered = 0;
  652.  
  653.  
  654.   for (lines=0; lines<(int)min(bmap->height,lineno); lines++) {
  655.  
  656.     if ((lines & 63) == 63) MUISetGauge(PrintedLines+lines);
  657.  
  658.  
  659.     in_line_ptr = ((char*)(bmap->pixptr))+(long)((long)lines*(long)map_width);
  660.     left_border = search_left_border(in_line_ptr,map_width);
  661.     if (left_border == map_width) {                /* the current line is totaly blank */
  662.       is_blank_line = TRUE;
  663.       blank_lines++;
  664.       Chk_Abort();    /* test ^C */
  665.     }
  666.     else {                            /* the current line isn't blank */
  667.       is_blank_line = FALSE;
  668.       if (blank_lines > 0) {
  669.         /* skip the blank lines */
  670.         move_down_canon(blank_lines);
  671.         blank_lines = 0;
  672.       }
  673.       right_border = search_right_border(in_line_ptr,map_width);
  674.       do {
  675.         if (o_optimize) {
  676.           /* hier soll optimiert werden.. :) */
  677.           /* suche wie weit ausgegeben werden soll. also von left_border -- blank_border
  678.            * blank_border gibt an, wo das Schwarze aufhoert.
  679.            * Falls blank_border == right_border, dann ist die Zeile nach der letzten
  680.            * Ausgabe fertig ausgegeben.
  681.            * Es wird also von left_b bis nach blank_b ausgegeben.
  682.            * Dann wid in_line_ptr auf blank_b gesetzt. (Achtung auf Allignment!!!!!!)
  683.            * 
  684.            * Die Werte left_border, right_border und blank_border sind *immer*
  685.            * RELATIV zun in_line_ptr!!
  686.            */
  687.           blank_border = search_next_blank(&blank_bytes, in_line_ptr, left_border, right_border);
  688.         }
  689.         else {
  690.           blank_bytes = 0;        /* wird nicht gebraucht */
  691.           blank_border = right_border;    /* die ganze Zeile wird ausgegeben */
  692.         }
  693.         if (left_border > 0) {
  694.           /* skip blank left border */
  695.           move_right_canon(left_border<<3);
  696.           send_graphic_1_canon((blank_border-left_border));
  697.           send_graphic_2_canon((blank_border-left_border));
  698.           send_graphic_3_canon(Printer->pp_xdpi);
  699.           in_line_ptr += (long)left_border;    /* linken Bereich skippen */
  700.           cursor_moved = TRUE;
  701.         }
  702.         else {
  703.           send_graphic_1_canon(blank_border);
  704.           send_graphic_2_canon(blank_border);
  705.           send_graphic_3_canon(Printer->pp_xdpi);
  706.         }
  707.  
  708.         /* und nun Ausgabe der zu druckenden Bytes (von left_border bis blank_border */
  709. #      ifdef AMIGA
  710.         if (bufferz + blank_border-left_border < bufflen) {
  711.           CopyMem(in_line_ptr, buffer+bufferz, blank_border-left_border);
  712.           bufferz += blank_border-left_border;
  713.         }
  714.         else {
  715.           register short bytes;
  716.           for (bytes=left_border; bytes<blank_border; bytes++) {    /* bytes of line */
  717.             directout((char)*in_line_ptr++);
  718.           }
  719.         }
  720. #      else
  721.     {
  722.           register short bytes;
  723.           for (bytes=left_border; bytes<blank_border; bytes++) {    /* bytes of line */
  724.             directout((char)*in_line_ptr++);
  725.           }
  726.         }
  727. #      endif
  728.  
  729.         in_line_ptr += blank_border-left_border;    /* ausgegebenen Bereich skippen */
  730.         if (blank_border<right_border) {
  731.           /* nun wird der left_border so gesetzt, dass der leere Bereich geskipt wird */
  732.           /* in_line_ptr zeigt ja auf das erste freie Byte */
  733.           left_border = blank_bytes;
  734.         }
  735.         else {
  736.           left_border = 0;
  737.         }
  738.         right_border -= blank_border + left_border;    /* rechten Rand an die Anzahl der bearbeiteten Bytes anpassen */
  739.  
  740.       } while (right_border != 0);
  741.  
  742.     }        /* else skip blank line */
  743.  
  744.     if (cursor_moved) {
  745.       cursor_moved = FALSE;
  746.       move_to_left_border();
  747.     }
  748.     if (!is_blank_line) {        /* keine leere Zeile */
  749.       move_down_canon(1);
  750.     }
  751.  
  752.   }        /* end for lines */
  753.  
  754.   if (blank_lines > 0) {
  755.     Skip_buffered = blank_lines;    /* fuehre den Skip erst spaeter aus! */
  756.   }
  757. }
  758.  
  759.  
  760.  
  761. /*
  762.  * Sucht den naechsten freien Bereich von wenigstens 20 Bytes 
  763.  *
  764.  * Gibt den rechten Rand des schwarzen Bereichs aus.
  765.  * Die blank_bytes gibt an, wieviele Bytes nach dem rechten Rand weiss sind.
  766.  *
  767.  */
  768.  
  769. static short search_next_blank(short * blank_bytes, char * line_ptr, short left_border, short right_border)
  770. {
  771.   /* zuerst wird der schwarze Bereich geskippt.
  772.    * Die Anzahl der Bytes ergibt den Rueckgabewert.
  773.    * Dann wird der weisse Bereich geskippt.
  774.    * Falls er groesser als 20 Bytes ist, so wird die Anzahl die blank_bytes.
  775.    * Falls nicht, so wird das zum schwarzen Bereich gezaehlt und von vorne begonnen.
  776.    */
  777.   char * line = line_ptr + left_border;
  778.   int align = (int)line & 0x3;
  779.  
  780.   int blank_lw;
  781.   long *Line, *RLine;
  782.   
  783.   RLine = (long *)((int)(line_ptr + right_border) & 0xFFFFFFFC);
  784.  
  785.  
  786.   if (*line == 0) {
  787.     Fatal(20, MSG_INTERNAL_ERROR_W_ARG,"(in search_next_blank)");
  788.   }
  789.  
  790.  
  791.   /* falls im align eine schwarz-weiss-schwarz Kombination uebersprungen
  792.    * wird, so macht das nichts, da das ja korrekt ausgedruckt wird.
  793.    */
  794.  
  795.   line += align;        /* nun muesste line 4 Byte aligned sein */
  796.   
  797.   Line = (long *)line;
  798.  
  799.   do {
  800.  
  801.     /* skip black */ 
  802.     while (Line < RLine && *Line != 0) Line++;
  803.     
  804.     if (Line == RLine) {
  805.       /* black bis rborder ?
  806.        * falls im Ralign eine schwarz-weiss Kombination ist, so macht das nichts,
  807.        * da diese ja korrekt ausgedruckt wird!
  808.        */
  809.       *blank_bytes = 0;        /* beliebig */
  810.       return right_border;    /* alles schwartz */
  811.     }
  812.     
  813.     blank_lw = 0;
  814.     
  815.     /* skip white */
  816.     while (Line < RLine && *Line == 0) {
  817.       Line++;
  818.       blank_lw++;
  819.     }
  820.   
  821.   } while (Line < RLine && blank_lw < 5);
  822.  
  823.   if (Line == RLine) {
  824.     /* d.h. weiss geht bis zum right_border...sollte eigentlich nicht sein.
  825.      * ist vielleicht nur eine kleine Kombination, bzw. im Ralign mag noch
  826.      * etwas schwartz sein. Egal, gib alles aus...
  827.      */
  828.     *blank_bytes = 0;        /* beliebig */
  829.     return right_border;    /* alles schwartz */
  830.   }
  831.   
  832.   *blank_bytes = blank_lw * 4;
  833.   return (short)((char *)Line - line_ptr);
  834. }
  835.  
  836.  
  837.  
  838. void initialize_canon_printer(void)
  839. {
  840.   init_canon();
  841.   if (landscape) {
  842.     set_landscape_mode_canon();
  843.   }
  844.   else {
  845.     set_portrait_mode_canon();
  846.   }
  847. }
  848.  
  849. void end_canon_printer(void)
  850. {
  851.   end_page_canon();
  852. }
  853.  
  854.  
  855.  
  856. static void CompressLine(char *buf, short len)
  857. {
  858.   register char *ptr;
  859.   short b, c, l;
  860.   
  861.   /* Strip trailing zeros */
  862.  
  863.   while (len && buf[len - 1] == 0) len--;
  864.  
  865.   /* Compression */
  866.  
  867.   ptr = compbuf;
  868.   l = 0;
  869.   while (len--)
  870.   {   b = *buf++;                  /* Pick up a byte */
  871.       c = 1;
  872.       while (len && *buf == b && c < 128)
  873.       {   c++;
  874.           buf++;
  875.           len--;                   /* See if it begins a run */
  876.       }
  877.       if (c == 2 &&                /* If a two byte run */
  878.           l > 0 &&                 /*  and preceeded by literals */
  879.           l <= 125 &&              /*  and not more than 125 of them */
  880.           (len <= 2 ||             /*  and no more than 2 bytes left */
  881.            *buf != *(buf + 1)))    /*      or not followed by a run */
  882.       {   c = 1;                   /* Then make it a literal */
  883.           buf--;
  884.           len++;
  885.       }
  886.       if (c == 1)                  /* If not a run */
  887.       {   l++;                     /* Then it must be a literal */
  888.           c = 0;
  889.       }
  890.       if (l > 0 &&                 /* If we have some literals */
  891.           (c > 1 ||                /*  and beginning a run */
  892.            l == 127 ||             /*  or reached 127 */
  893.            len == 0))              /*  or no more bytes left */
  894.       {   *ptr++ = l - 1;          /* Then write out the literals */
  895.           memcpy(ptr, buf - c - l, l);
  896.           /* CopyMem(ptr, buf - c - l, l); */
  897.           ptr += l;
  898.           l = 0;
  899.       }
  900.       if (c > 1)                   /* If we have a run */
  901.       {   *ptr++ = 1 - c;          /* Then write it */
  902.           *ptr++ = b;
  903.       }
  904.   }
  905.  
  906.   len = ptr - compbuf;
  907.   compress_data_hp(len);
  908.   buf = compbuf;
  909.  
  910. #ifdef AMIGA
  911.   if (bufferz + len < bufflen) {
  912.     CopyMem(buf, buffer+bufferz, len);
  913.     bufferz += len;
  914.   }
  915.   else {
  916.     register short bytes;
  917.     for (bytes=0; bytes<len; bytes++) {    /* bytes of line */
  918.       directout((char)*buf++);
  919.     }
  920.   }
  921. #else
  922.   {
  923.     register short bytes;
  924.     for (bytes=0; bytes<len; bytes++) {    /* bytes of line */
  925.       directout((char)*buf++);
  926.     }
  927.   }
  928. #endif
  929. }
  930.  
  931.  
  932.  
  933. /***************************************************************************/
  934. /*****            N    A    D    E    L           *****/
  935. /***************************************************************************/
  936.  
  937. /***** Standard Graphic-Befehle ****    ****    ****    ****    ****    ****/
  938.  
  939. #if defined(COMMON_BUFFERS) && defined(AMIGA)
  940.  
  941. /* Das Splitten der Grafiksequenzen ist noch nicht eingebaut. Also diese
  942. Option vermeiden. */
  943.  
  944. static void prepare_for_gfx(int nr)
  945. {
  946.    if (PrnIndex) {
  947.      PrnBuffered=nr;         /* wir puffern schon */
  948.    }
  949.    else {
  950.       if (bufferz + MAXchars + 5 >= bufflen) {
  951.     make_room();
  952.       }
  953.       /* MAXchars so etwas wie map_width*printer_group ... */
  954.       PrnBuffer=&buffer[bufferz+5];    /* 5 Zeichen freihalten */
  955.    }
  956. }
  957. #else /* COMMON_BUFFERS */
  958.  
  959. /*    prepare_for_gfx
  960.  *
  961.  * The next sequence will be graphics, but we buffer it. We only print
  962.  * the whole sequence once we know how many bytes there are
  963.  */
  964. static void prepare_for_gfx(int nr)
  965. {
  966.    if (Skip_buffered) skip_lines();
  967. #if defined(HARDDEB)
  968.    printf("J:\t prepare PrnBuf %d\n",nr);
  969. #endif
  970.    PrnBuffered = nr;
  971. }
  972. #endif /* COMMON_BUFFERS */
  973.  
  974.  
  975.  
  976. /*    print_clear_buffer
  977.  *
  978.  * output one block(=piece WP_GROESSE large of bitmap) of data and
  979.  * reset the block used
  980.  *
  981.  * gibt Puffer aus und setzt ihn auf 0
  982.  */
  983. static void print_clear_buffer(char block[MAX_GROUPING][WP_GROESSE])
  984. {
  985.   int rows,j;
  986.  
  987.   for (j = WP_GROESSE-1; 0 <= j; j--) {
  988.      for (rows = 0; rows < Printer->pp_grouping; rows++) {
  989.         quickgfxout((char)block[rows][j]);
  990.      }
  991.   }
  992.   memset(block, 0, sizeof(char[MAX_GROUPING][WP_GROESSE]));
  993. }
  994.  
  995.  
  996. #define print_uni_bi_direct_nadel(n) \
  997.     string_out(ESCU, sizeof(ESCU), UNIDIR == (n) ? 1 : 0)
  998.  
  999. #define move_head_to_nadel(pos) \
  1000.     string_out(ESCdollar, sizeof(ESCdollar), (pos))
  1001.  
  1002.  
  1003.  
  1004. /*    print_empty_words
  1005.  *
  1006.  * skip white areas using one of the predefined methods.
  1007.  * ueberspringt Leerstellen
  1008.  */
  1009. static void print_empty_words(int empty, int toword)
  1010. {
  1011.    int method,
  1012.    rest, point, spaces;    /* fuer jede Methode, (1 Inch hier 60 point) */
  1013.    short num, den;
  1014.  
  1015.    method = Printer->pp_method;
  1016.    switch(method) {
  1017.      case METHOD_MOVE_POINT:
  1018.        num = toword * WP_GROESSE; den = pp_dots_per_point;
  1019.        point = num / den;
  1020.        rest  = num % den;
  1021.        break;
  1022.      case METHOD_USE_SPACES:
  1023.        num = empty * WP_GROESSE; den = pp_dots_per_space;
  1024.        spaces = num / den;
  1025.        if ( empty == toword || SPACES_GUT <= spaces)
  1026.      rest = num % den;
  1027.        else {
  1028.      rest = empty * WP_GROESSE;
  1029.      method = METHOD_GFX_ONLY;
  1030.      }
  1031.        break;
  1032.      case METHOD_GFX_ONLY:
  1033.        if (empty == toword) {
  1034.      num = empty * WP_GROESSE; den = pp_dots_per_space;
  1035.      spaces = num / den;
  1036.      rest  = num % den;
  1037.      method = METHOD_USE_SPACES;
  1038.      }
  1039.        else
  1040.      rest = empty * WP_GROESSE;
  1041.        break;
  1042.      }
  1043.  
  1044.    switch(method) {
  1045.      case METHOD_USE_SPACES:
  1046. #if defined(HARDDEB)
  1047.         printf("J:    Spaces %d\n",spaces);
  1048. #endif
  1049.         for (; 0 < spaces; spaces--) {
  1050.       getout(' ');
  1051.     }
  1052.     break;
  1053.  
  1054.      case METHOD_MOVE_POINT:        /* Speziellen Befehl ausfuehren */
  1055.         move_head_to_nadel(point);    /* 1 inch <-> 60 point */
  1056.     break;
  1057.    }
  1058.    if (rest) {        /* anschliessend Methode 0: mit 0 auffuellen */
  1059.       int i;
  1060.       prepare_for_gfx(Printer->pp_grouping * rest);
  1061.       for (i=Printer->pp_grouping*rest; 0<i; i--) quickgfxout('\0');
  1062.    }
  1063. }
  1064.  
  1065.  
  1066.  
  1067. /*    skip_lines
  1068.  *
  1069.  * Skip lines that have been buffered. Note that the graphics buffer
  1070.  * must have been flushed already.
  1071.  */
  1072. static void skip_lines()
  1073. {
  1074.    int lines;
  1075. #if defined(HARDDEB)
  1076.    printf("J:     Skip lines %d\n",Skip_buffered);
  1077. #endif
  1078.    for (lines = Skip_buffered; 0 < lines; lines -=255) {
  1079.      string_directout(Printer->pp_skip_cmd,
  1080.     Printer->pp_skip_cmd_len,
  1081.     255 < lines ? 255 : lines & 0xff);
  1082.      }
  1083.    Skip_buffered = 0;
  1084. }
  1085.  
  1086.  
  1087.  
  1088. /*    prepare_skip
  1089.  *
  1090.  * We even buffer line skips! If gfx are buffered, flush them.
  1091.  */
  1092. static void prepare_skip(skips)
  1093. {
  1094.    if (PrnIndex) print_buffered_line();
  1095. #if defined(HARDDEB)
  1096.    printf("J:     Buffer skip %d\n",skips);
  1097. #endif
  1098.    Skip_buffered += skips;
  1099. }
  1100.  
  1101.  
  1102. /*  0 == pass: Zeile wurde uebersprungen, voller Zeilenvorschub.
  1103.  *  (gibt es eigentlich nicht mehr)
  1104.  *  i.allg. werden zuerst kleine skips ausgefuehrt, dann kommt fuer
  1105.  *  printer_passes == pass ein grosser.
  1106.  */
  1107.  
  1108. #define prepare_pass(a,b)    /* nothing */
  1109. #define end_pass(pass, printer) prepare_skip(Printer->pp_skip[(pass)-1])
  1110.  
  1111.  
  1112.  
  1113.  
  1114. /*    print_buffered_line
  1115.  *
  1116.  *
  1117.  * We have buffered all the graphics of the current line, (we know how
  1118.  * many bytes there are), and we flush the buffer.
  1119.  */
  1120. static void print_buffered_line()
  1121. {
  1122. #ifdef AMIGA
  1123.   /* damit CopyMem oft angewendet werden kann, wird    *
  1124.    * ein ziemlich voller Puffer geleert.         *
  1125.    * +5 wegen den noch folgenden Graphikbefehlen.    */
  1126.  
  1127.   if (bufferz + PrnIndex + 5 >= bufflen) make_room();
  1128. #endif
  1129.   string_directout(Printer->pp_gfx_cmd,
  1130.     Printer->pp_gfx_cmd_len,
  1131.     PrnIndex / Printer->pp_grouping);
  1132. #if defined(HARDDEB)
  1133.   printf("J:     #Graphics: %d\n",PrnIndex);
  1134. #endif
  1135.  
  1136. #ifdef AMIGA
  1137.     if (bufferz + PrnIndex >= bufflen) {    /* a really small buffer ! */
  1138.       char *p;
  1139.       for (p = PrnBuffer; PrnIndex; PrnIndex--, p++) directout(*p);
  1140.       }
  1141.     else {
  1142.       CopyMem(PrnBuffer,&buffer[bufferz],(ULONG)PrnIndex);
  1143.       bufferz += PrnIndex;
  1144.       PrnIndex = 0;
  1145.       }
  1146. #else /* AMIGA */
  1147.     {
  1148.       char *p;
  1149.       for (p = PrnBuffer; PrnIndex; PrnIndex--, p++) directout(*p);
  1150.       }
  1151. #endif /* AMIGA */
  1152.  
  1153.   /* PrnIndex ist nun wieder 0 */
  1154. }
  1155.  
  1156.  
  1157.  
  1158.  
  1159. /*---------------------------------------------------------------------*/
  1160. /* this is the main function ! */
  1161. static void Hardcopy_standard(struct bitmap *bmap, long lineno, int draft)
  1162. {
  1163.    char block[MAX_GROUPING][WP_GROESSE];
  1164.    int usemap_width, lines;
  1165.    const int bitmap_width = ((int)bmap->width+(WP_GROESSE-1)) / WP_GROESSE;
  1166.    WP_TYP *bmap_base1;
  1167.    
  1168.    memset(&(block[0]),0,sizeof(block));
  1169.  
  1170.    usemap_width = (bmap->width > pp_max_dots_line) ? pp_max_dots_line /* abrunden */ / WP_GROESSE : bitmap_width;
  1171.  
  1172.   
  1173.    //printf("bmap->width = %d, bitmap_width = %d, usemap_width = %d\n",
  1174.    //         bmap->width, bitmap_width, usemap_width);
  1175.  
  1176.  
  1177. #if 0 || defined(HARDDEB)
  1178.    Message("J:bmap size %ldx%ld,\n   use      %dx%ld.\n",
  1179.     bmap->width, bmap->height,
  1180.     usemap_width*WP_GROESSE, lineno);
  1181. #endif
  1182.  
  1183.    for (lines = 0,                    /* for every line */
  1184.         bmap_base1 = ((WP_TYP *)(bmap->pixptr))
  1185.        ;lines < (int)(min(bmap->height,lineno))
  1186.        ;lines += Printer->pp_passes_height,         /* (was height) */
  1187.         bmap_base1 += (long)(Printer->pp_passes_height*bitmap_width)) { /* MULU/S.W Befehl */
  1188.       int pass;
  1189.       WP_TYP *bmap_base2;
  1190.  
  1191. #if 0 && defined(HARDDEB)
  1192.       printf("J:Line %d\n",lines);
  1193. #endif
  1194.  
  1195.       MUISetGauge(PrintedLines+lines);
  1196.  
  1197.  
  1198.       for (pass=1,                    /* for each pass */
  1199.            bmap_base2 = bmap_base1
  1200.           ;pass <= Printer->pp_passes
  1201.           ;pass++,
  1202.        bmap_base2 += bitmap_width) {
  1203.      int words;
  1204.          int full = 0;
  1205.      WP_TYP * in_line_ptr = bmap_base2;
  1206.  
  1207. #if 0 && defined(HARDDEB)
  1208.      printf("J: Pass %d\n",pass);
  1209. #endif
  1210.      prepare_pass(pass,Printer);
  1211.          for (words=0; words<usemap_width; words++) {    /* words of line */
  1212.  
  1213.         /* first skip blank areas to improve speed */
  1214.             if (full == 0) {
  1215.            int empty;
  1216. #if 0 && defined(HARDDEB)
  1217.            printf("J:  @word %d\n",words);
  1218. #endif
  1219.                empty = jskip_blank_words_std(in_line_ptr,
  1220.               Printer->pp_passes_height,
  1221.               bitmap_width * Printer->pp_passes,
  1222.               usemap_width-words,
  1223.               Printer->pp_passes);
  1224.                words += empty;                /* skip blank words */
  1225. #if 0 && defined(HARDDEB)
  1226.                printf("J:   empty %d\n",empty);
  1227. #endif
  1228.            if (words >= usemap_width) break;        /* EOL */
  1229.  
  1230.                if (empty > 0) {
  1231.                   in_line_ptr += empty;
  1232.               print_empty_words(empty, words);
  1233.            }
  1234.            if (Printer->pp_method == METHOD_GFX_ONLY)
  1235.               full = jsearch_right_border_std(
  1236.               in_line_ptr,
  1237.               Printer->pp_passes_height,
  1238.                   bitmap_width * Printer->pp_passes,
  1239.               usemap_width-words,
  1240.               Printer->pp_passes);
  1241.            else
  1242.                   full = jsearch_length_text_std(
  1243.               in_line_ptr,
  1244.               Printer->pp_passes_height,
  1245.               bitmap_width * Printer->pp_passes,
  1246.               usemap_width-words,
  1247.               Printer->pp_passes);
  1248. #if 0 && defined(HARDDEB)
  1249.            printf("J:   full %d\n",full);
  1250. #endif
  1251.                prepare_for_gfx(full*WP_GROESSE*Printer->pp_grouping);
  1252.             }
  1253.         full--;
  1254.  
  1255.         /* now transform bitmap to printer-data */
  1256.  
  1257.         {  /* make these variables local */
  1258.            WP_TYP *ptr;
  1259.            char *print;
  1260.            unsigned char mask;
  1261.            int j, rows;
  1262.  
  1263.            ptr = in_line_ptr++;
  1264.              for (rows=0; rows < Printer->pp_grouping; rows++) {
  1265.                print = &(block[rows][0]);    /* pointer aliasing */
  1266.                for (j=0, mask=128; j<8; j++, mask>>=1) {
  1267.                   int i;
  1268.                   WP_TYP read_word;
  1269.                       read_word = *ptr;
  1270.                       ptr += Printer->pp_passes*bitmap_width;/* `printer_passes' mal */
  1271.               if (read_word) {
  1272.                         for (i=0; i<WP_GROESSE; i++)    /* transf. a word */
  1273.                            if (take_Bit(i,read_word) != 0) print[i] |= mask;
  1274.                       }
  1275.            }
  1276.            }
  1277.         } /* end local */
  1278.  
  1279.         /* now send the data */
  1280.             print_clear_buffer(block);
  1281.          }
  1282.          /* end of words, now in pass */
  1283.  
  1284.      end_pass(pass, Printer);
  1285.          Chk_Abort();        /* erst nach end_pass() */
  1286.       }
  1287.       /* end of pass, now in line */
  1288.    }
  1289.    /* end of line */
  1290. }
  1291.  
  1292.  
  1293. /***** misc functions ****************************************************/
  1294.  
  1295.  
  1296. /* sucht wortweise nach der ersten Spalte != 0 */
  1297. static int jskip_blank_words_std(WP_TYP * ptr, int lines,
  1298.    int bitmap_offset, int max, int line_offset)
  1299. {
  1300.   int nr;
  1301.   WP_TYP *p;
  1302.   for (nr=0, p=ptr ; nr < max ; nr++, p=++ptr) {
  1303.      int i;
  1304.      for (i=0 ; i<lines ; i+=line_offset, p+=bitmap_offset)
  1305.         if (0 != *p) return nr;
  1306.      }
  1307.   return nr;
  1308. }
  1309.  
  1310.  
  1311. /* suche rueckwaerts ab rechtem Rand */
  1312. static int jsearch_right_border_std(WP_TYP *ptr, int lines,
  1313.    int bitmap_offset, int max, int line_offset)
  1314. {
  1315.   int nr;
  1316.   WP_TYP *p;
  1317.   ptr += max-1;
  1318.   for (nr=max, p=ptr ; 0 < nr ; nr--, p=--ptr) {
  1319.      int i;
  1320.      for (i=0 ; i<lines ; i+=line_offset, p+=bitmap_offset)
  1321.     if (0 != *p) return nr;
  1322.      }
  1323.   return 0; /* is never the case */
  1324. }
  1325.  
  1326.  
  1327. /* sucht wortweise nach der ersten Spalte == 0 */
  1328. static int jsearch_length_text_std(WP_TYP *ptr, int lines,
  1329.    int bitmap_offset, int max, int line_offset)
  1330. {
  1331.   int nr;
  1332.   WP_TYP *p;
  1333.   /* fange gleich mit 1 an, weil erstes Wort bekanntlich !=0 */
  1334.   for (nr=1, p=++ptr ; nr < max ; nr++, p=++ptr) {
  1335.      int i;
  1336.      for (i=0 ; i<lines && 0==*p ;
  1337.           i +=line_offset, p += bitmap_offset) ;
  1338.      if (i>=lines) break;
  1339.      }
  1340.   return nr;
  1341. }
  1342.  
  1343.  
  1344. #if 0
  1345. /*** suche erstes Byte != 0 von links ***/
  1346. static short search_left_border(char *in_line_ptr, short map_width)
  1347. {
  1348.   register short i;
  1349.   
  1350.   for (i=0; i<map_width && *in_line_ptr == 0; i++, in_line_ptr++);
  1351.  
  1352.   return i;
  1353. }
  1354. #else
  1355. static short search_left_border(char *in_line_ptr, short map_width)
  1356. {
  1357.   register short i;
  1358.   register short width;
  1359.   register long *ptr;
  1360.  
  1361.   width = map_width >> 2;
  1362.   ptr = (long *)((long)in_line_ptr & 0xFFFFFFFC);    /* sollte eigentlich nicht noetig sein */
  1363.   
  1364.   for (i=0; i<width && *ptr == 0; i++, ptr++);
  1365.  
  1366.   if (i == width) return map_width;
  1367.  
  1368.   i = i << 2;
  1369.  
  1370.   if (*ptr & 0xFF000000) return i;
  1371.   if (*ptr & 0x00FF0000) return (short)(i+1);
  1372.   if (*ptr & 0x0000FF00) return (short)(i+2);
  1373.   return (short)(i+3);
  1374. }
  1375. #endif
  1376.  
  1377. /*** suche erstes Byte != 0 von rechts ***/
  1378. static short search_right_border(char *in_line_ptr, short map_width)
  1379. {
  1380.   register short i;
  1381.  
  1382.   in_line_ptr += (long)((long)map_width-1L);
  1383.   for (i=map_width-1; *in_line_ptr == 0  && i>0; i--, in_line_ptr--);
  1384.  
  1385.   if (*in_line_ptr != 0) {
  1386.     i++;
  1387.   }
  1388.  
  1389.   return i;
  1390. }
  1391.  
  1392.  
  1393.  
  1394. /*************************************************************************/
  1395. /** Schnittstelle nach aussen:                        **/
  1396.  
  1397.  
  1398. void FormFeed(void)
  1399. {
  1400.    Skip_buffered = 0;
  1401.    if (Printer->pp_printer == CANON) {
  1402.      ;        /* beim Caonon wird das FF schon direkt nach dem latzten Pass ausgegeben! */
  1403.    }
  1404.    else {
  1405. #ifdef ATARI
  1406.      if (Printer->pp_printer != SLM_804) {
  1407.        getout(FF);
  1408.      }
  1409. #else
  1410. #if 0    /* generic macht nun schon selber ein FF */
  1411. # ifdef AMIGA
  1412.      if ((Printer->pp_special & SPECIAL_PREFS) && (ToDo & DO_REALPRINT)) {
  1413.        FormFeedGeneric();
  1414.      }
  1415.      else
  1416. # endif
  1417.     if (buffer) getout(FF);
  1418. #else
  1419.      if (!((Printer->pp_special & SPECIAL_PREFS) && (ToDo & DO_REALPRINT)) && buffer) {
  1420.        getout(FF);
  1421.      }
  1422. #endif
  1423. #endif  /* ATARI */
  1424.   }
  1425.  
  1426.   nr_printed_pages++;    /* wieder eine Seite mehr ausgegeben */
  1427. }
  1428.  
  1429.  
  1430. /*    Hardcopy
  1431.  *
  1432.  * The main dispatcher!
  1433.  */
  1434. void Hardcopy(struct bitmap *bmap, long lineno, int first_pass, int last_pass)
  1435. {
  1436.  
  1437.   if (first_pass) PrintedLines = 0;
  1438.  
  1439. #if defined(HARDDEB)
  1440.   if (NULL==Printer)
  1441.     Fatal(20,"Hardcopy(): Printer not initialized !\n");
  1442. #endif
  1443.  
  1444.   PrnBuffered=0;
  1445.   PrnIndex=0;
  1446.  
  1447. #if defined(HARDDEB)
  1448.   printf("J:Hardcopy(): printer_flags: %X, printer_group: %d, quality: %ld\n",
  1449.     Printer->pp_flags, Printer->pp_grouping, draft);
  1450. #endif
  1451.  
  1452.   switch (Printer->pp_printer)
  1453.    {
  1454.     case CANON:
  1455.     if (first_pass) {
  1456.       set_nr_of_copies_canon(ncopies);
  1457.       /* init_cursor_canon(); */
  1458.       set_display_canon();
  1459.     }
  1460.  
  1461.     Hardcopy_Canon(bmap,lineno,draft);
  1462.  
  1463.     if (last_pass) {
  1464.       getout(FF);
  1465.     }
  1466.     break;
  1467.  
  1468.     case DESKJET:
  1469.     case CHEAPDJ:
  1470.     case LASERJET:
  1471.     case LASERJET4:
  1472.      {
  1473.       const int is_LaserJet = (Printer->pp_printer == LASERJET) || 
  1474.                   (Printer->pp_printer == LASERJET4);
  1475.  
  1476.       if (o_optimize && compbuf == NULL) {
  1477.         int compsize;
  1478.         compsize = (((int)bmap->width) >> 3) + (((int)bmap->width) >> 3) / 128 + 2;
  1479.         compbuf = xmalloc(compsize);
  1480.       }
  1481.  
  1482.       if (first_pass) {
  1483.         if (is_LaserJet) {
  1484.           set_nr_of_copies_hp(ncopies);
  1485.         }
  1486.         init_cursor_hp();
  1487.         init_resolution_hp(Printer->pp_xdpi);
  1488.         init_position_hp();
  1489.         if (Printer->pp_printer == CHEAPDJ) {        /*DRAFT_CHEAP||HIGH_Q_CHEAP*/
  1490.           set_draft_print_hp();
  1491.         }
  1492.         if (!is_LaserJet) {            /* das geht nur bei den DeskJets */
  1493.           if (unidirect) {
  1494.             print_uni_bi_direct_hp(UNIDIR);
  1495.           }
  1496.           set_raster_graphics_width_hp((int)bmap->width);
  1497.         }
  1498.       }
  1499.  
  1500.       if (landscape) {
  1501.         Querdruck(bmap, Printer->pp_passes_height, draft, Hardcopy_HP);
  1502.       }
  1503.       else {
  1504.         Hardcopy_HP(bmap,lineno,draft);
  1505.       }
  1506.  
  1507.       if (last_pass) {
  1508.         end_raster_graphics_hp();
  1509.         if (is_LaserJet) {
  1510.           reset_nr_of_copies_hp();
  1511.         }
  1512.       }
  1513.      }
  1514.      break;
  1515.  
  1516. #ifdef AMIGA
  1517.     case GENERIC_PRINTER:
  1518.       if (landscape) {
  1519.         Fatal(5,MSG_NO_LAND_WITH_GENERIC);
  1520.       }
  1521.       else {
  1522.         HardcopyGeneric(bmap,lineno,draft,last_pass);
  1523.       }
  1524.       break;
  1525. #endif
  1526.  
  1527. #ifdef ATARI
  1528.     case SLM_804:
  1529.       if (landscape)
  1530.         Fatal(5,"Can't print in landscape modus!");
  1531.       else
  1532.         Hardcopy_SLM(bmap,lineno,draft);
  1533.       break;
  1534. #endif
  1535.  
  1536.     default:
  1537.       if (Printer->pp_grouping) {    /* Use Hardcopy_standard() routine */
  1538.         print_uni_bi_direct_nadel(unidirect ? UNIDIR : BIDIR);
  1539.     if (landscape)
  1540.       if (Printer->pp_xdpi == Printer->pp_ydpi)
  1541.         Querdruck(bmap, Printer->pp_passes_height<<1, draft, Hardcopy_standard);
  1542.       else
  1543.         Warning(MSG_NO_LAND_XDPI_YDPI);
  1544.     else 
  1545.       Hardcopy_standard(bmap,lineno,draft);
  1546.     }
  1547.       break;
  1548.     
  1549.    }
  1550.  
  1551.    PrintedLines += min(bmap->height,lineno);
  1552. }
  1553.  
  1554.  
  1555. /* Bemerkungen:
  1556.  
  1557. o Der Code fuer COMMON_BUFFERS ist noch nicht fertiggestellt, man muss
  1558. naemlich sicherstellen, dass der Puffer auch gross genug ist. 
  1559.  
  1560. */
  1561.