# This file belongs to the CEP package | Ten plik nale/zy do pakietu CEP
# This package is public domain        | Pakiet stanowi dobro powszechne
# For more info see `0CEP_LIC.ENG'     | Wi/ecej informacji w ,,0CEP_LIC.POL''
# ===========================================================================
# E: "Hex bitmap EPS" --> "filtered EPS" converter
#      input - input file name
#      OUTF  - output file name
#      CVM   - conversion method
#      TMPSX - temporary PostScript file name 
#
# P: Konwerter "Hex bitmap EPS" --> "filtered EPS"
#      wej/scie - nazwa pliku konwertowanego
#      OUTF     - nazwa pliku wyj/sciowego
#      CVM      - metoda konwersji EPS-a
#      TMPSX    - nazwa tymczasowego pliku PostScriptowego

BEGIN {
  ver_no=1.03
  gs_abort="2 2 .quit"
  RS="\015|\012|\015\012"
   # preparing temporary files | przygotowywanie plik/ow tymczasowych
  if (TMPSX=="") TMPSX="tmp.psx"
  if (CVM!~/[LlRrFfNn]/) CVM=CVM "R" # Default coding and compression method
  if (CVM!~/[Hh8]/) CVM=CVM "8"      # Domy/slna metoda kodowania i kompresji
  printf "CEP ver. " ver_no ", Coding:"
  if (is_A85()) printf " A85"
  if (is_HEX()) printf " Hex"
  if (is_LZW()) printf ", LZW"
  if (is_RLE()) printf ", RLE"
  if (is_ZIP()) printf ", Flate (non-standard in PostScript Level 2!)"
  print ""
  flag="pre"
}

 # searching for ``strange lines'' is due to the following problem:
 #   a single hex char in line or Postscript command "def" and "add" in prolog
 #   may be misunderstood for a HEX bitmap (see also ``heuristic trick'')
 # poszukiwanie ,,dziwnych wierszy'' wi/a/ze si/e z nast/epuj/acym problemem:
 #   pojedynczy znak w wierszu oraz instrukcje Postscriptu "def" i "add"
 #   stanowi/ace cz/e/s/c prologu mog/a zosta/c b/l/ednie uznane za 
 #   fragment szesnastkowej mapy bitowej (patrz ,,heurystyczny fortel'')

{is_hex_line=/^[0-9A-Fa-f]*$/
  if (flag=="hex") {
    if (is_hex_line) {hex_dig_num+=length($0)} else {flag="post"; pos_lines++}
  } else {is_odd_line=/^(def|add|[0-9A-Fa-f]|)$/
    if (flag=="pre") {
      if (is_hex_line && !is_odd_line) {flag="hex"; hex_dig_num+=length($0)}
        else {prolog=prolog $0 "\n"; pre_lines++}
    } else {
      if (is_hex_line && !is_odd_line) {flag="xhex"; exit} else {pos_lines++}
    }
  }
}

END {
  if (flag=="pre")  errmessage("HEX bitmap not found.", 1)
  if (flag=="xhex") errmessage("more than one HEX bitmap's found.", 2)

   # fix (somehow) length of bitmap bufor
   # ustalanie d/lugo/sci bufora b/ed/acej dzielnikiem d/lugo/sci mapy bitowej
  if ((hex_dig_num%2)!=0)
    errmessage("Odd number of HEX digits in the bitmap.", 3)
  hex_dig_num=hex_dig_num/2
  buff_len=8192
  while (hex_dig_num%buff_len!=0) buff_len--
  buff_num=hex_dig_num/buff_len

   # modification of the preamble of compressed EPS file
   # dostosowanie preambu/ly pliku EPS do czytania kompresowanych danych
  if (match(prolog,/\n%%BoundingBox:[^\n]*\n/))
    prolog = substr(prolog,1,RSTART+RLENGTH-1) banner() "\n" uncep_comment() "\n" substr(prolog,RSTART+RLENGTH)
  else
    errmessage("\"%%BoundingBox:\" not found.", 4)
  if (gsub(/currentfile/,"_fltrd_file",prolog)==0)
    errmessage("illegible EPS preamble.", 5)
  if (gsub(/readhexstring/,"_read_string",prolog)==0)
    errmessage("illegible EPS preamble.", 6)
  if (match(prolog, /\n[^%\n]/))
    prolog = substr(prolog,1,RSTART-1) "\n" source() substr(prolog,RSTART)
  else
    errmessage("illegible EPS preamble.", 7)
   # heuristic trick: | heurystyczny fortel:
   # odd lines at the end of prolog are to be considered as a bitmap beginning
   # dziwne linie na ko/ncu prologu nale/zy uzna/c za pocz/atek mapy bitowej
  if (match(prolog,/\n((def|add|[0-9A-Fa-f])\n)+$/)) {
    prolog = substr(prolog,1,RSTART);
    print "CEP warning: peculiar bitmap beginning."
  }
  gsub(/%/,"%%",prolog) # neutralizing printf | podmiana dla printf

   # WRITE PostScript ENCODING PROGRAM | TWORZENIE PROGRAMU Postscript-owego
  out_ps_errorhandler()
   #
  out_ps("(" ps_fname(OUTF) ") (w) file /w_file exch def")
  out_ps("(" ps_fname(FILENAME) ") (r) file /r_file exch def")
  out_ps("/l_string 255 string def")
  out_ps("/p_string 4096 string def")
  out_ps("/b_string " buff_len " string def")
  out_ps("/flushclose {dup flushfile closefile} def")
   # copy preamble | przepisywanie preambu/ly
  out_ps(pre_lines  " {r_file l_string readline pop pop} repeat")
  out_ps(pre_lines+3  " {currentfile l_string readline pop")
  out_ps("w_file exch writestring w_file (\\n) writestring} repeat")
  out_ps_block(prolog)
  out_ps("%--- PROLOG END | KONIEC PROLOGU")
   # special treatment of the ASCII85 encoded lines looking like DSC comments
   # dodatkowa obr/obka wierszy (zakodowanych jako ASCII85) zaczynaj/acych 
   # si/e tak jak komentarze DSC
  if (is_A85()) {
    out_ps("{pop (%) anchorsearch {pop w_file (%\\n ) writestring} if")
    out_ps(" {(\\n%) search not {exit} if")
    out_ps("  w_file exch writestring pop w_file (\\n%\\n ) writestring} loop")
    out_ps(" w_file exch writestring p_string}")
    out_ps("/NullEncode filter dup")
  } else out_ps("w_file")
   # prepare encoding filters | przygotowywanie filtr/ow koduj/acych
  if (is_A85()) out_ps("/ASCII85Encode filter")
  if (is_HEX()) out_ps("/ASCIIHexEncode filter")
  if (is_LZW()) out_ps("dup /LZWEncode filter")
  if (is_RLE()) out_ps("dup 0 /RunLengthEncode filter")
  if (is_ZIP()) out_ps("dup /FlateEncode filter")
   # loop encoding bitmap | p/etla koduj/aca map/e bitow/a
  out_ps(buff_num " {r_file b_string readhexstring pop")
  out_ps("1 index exch writestring} repeat")
  if (is_A85()) out_ps("flushclose flushclose")
  if (is_HEX()) out_ps("flushclose")
  if (is_LZW()) out_ps("flushclose")
  if (is_RLE()) out_ps("flushclose")
  if (is_ZIP()) out_ps("flushclose")
   # copy postamble | przepisanie postambu/ly
  out_ps(pos_lines+1 " {r_file l_string readline pop")
  out_ps("w_file exch writestring w_file (\\n) writestring} repeat")
  out_ps("w_file flushclose r_file closefile quit")
  printf "."
}

function banner() {return "%%Creator: CEP ver. " ver_no " by BOP s.c."}

function ps_fname(s) {gsub(/\\/,"/",s); return(s)}

function out_ps(s) {print s > TMPSX}
function out_ps_block(block) {printf block > TMPSX}

function out_ps_errorhandler() {
  out_ps("/errq {" gs_abort "} def")
  out_ps("errordict begin ")
  out_ps("/typecheck {255 string cvs (filter) search")
  out_ps("  {(\\010!Filter failed) print")
  out_ps("  ( (ASCII85Encode used with GS version<3.0?)\\n\\007) print}")
  out_ps("  {(\\010!Something went wrong\\n Error: typecheck\\n\\007) print}")
  out_ps("  ifelse errq} def")
  out_ps("/ioerror {(\\010!Input/Output error occurred. (Disk full?)\\n\\007)")
  out_ps("  print errq} def")
  out_ps("/handleerror {$error begin (Something went wrong) print")
  out_ps("  (\\n Error: ) print errorname 255 string cvs print")
  out_ps("  (\\n\\007) print end errq} def")
  out_ps("end")
   #
  out_ps("systemdict /resourcestatus known not")
  out_ps("{(\\010!This version of Ghostscript doesn't support required Level 2 features\\n\\007)")
  out_ps("  print quit} if")
  if (is_A85()) {
    check_filter("ASCII85Encode", "ASCII85Encode filter")
    check_filter("NullEncode", "required Level 2 filters")
  }
  if (is_HEX()) check_filter("ASCIIHexEncode", "ASCIIHexEncode filter")
  if (is_LZW()) check_filter("LZWEncode", "LZWEncode filter")
  if (is_RLE()) check_filter("RunLengthEncode", "RunLengthEncode filter")
  if (is_ZIP()) check_filter("FlateEncode", "FlateEncode filter")
}
  function check_filter(name, expl) {
    out_ps("/" name " /Filter resourcestatus {pop pop}")
    out_ps("{(\\010!This version of Ghostscript doesn't support " expl "\\n\\007)")
    out_ps("  print errq} ifelse")
  }

function errmessage(errname, errnum) {
 print "CEP ERROR:", errname "\007"; exit(errnum)
}

 # searching for the most recent, i.e., active, options
 # poszukiwanie ostatniej (obowi/azuj/acej) opcji
function is_A85() {return (CVM~/8[^Hh]*$/) }
function is_HEX() {return (CVM~/[Hh][^8]*$/) }
function is_LZW() {return (CVM~/[Ll][^NnRrFf]*$/) }
function is_RLE() {return (CVM~/[Rr][^NnLlFf]*$/) }
function is_ZIP() {return (CVM~/[Ff][^NnLlRr]*$/) }

function uncep_comment() {
  s="%UNCEPInfo: " pre_lines+3 " " buff_num " " buff_len " " pos_lines+1
  return s
}

function source() {
  s="/_fltrd_file currentfile"
  if (is_A85()) s=s " /ASCII85Decode filter"
  if (is_HEX()) s=s " /ASCIIHexDecode filter"
  if (is_LZW()) s=s " /LZWDecode filter"
  if (is_RLE()) s=s " /RunLengthDecode filter"
  if (is_ZIP()) s=s " /FlateDecode filter"
  s=s " def /_read_string /readstring load def"
  return s
}