#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <error.h>
#include <errno.h>

#ifndef FALSE
#define FALSE (0!=0)
#define TRUE (0==0)
#endif

/*

Add parameters:

  --a3
  --ledger (11x17) --tabloid
  --legal (11x14) (unlikely to be needed)
  --a4
  --letter (8.5x11)
  --half-letter (5.5x8.5)

letter_letter -> ledger

half-letter+half-letter -> letter

a4+a4 -> a3

a5+a5 -> a4


Table 1: Paper Size
     w bp h bp w in  h in  w mm h mm
A0b  2594 3370 36.03 46.81 915  1189
A0   2380 3368 33.06 46.78 840  1188
A1   1684 2380 23.39 33.06 594   840
A2   1190 1684 16.53 23.39 420   594
A3   842  1190 11.69 16.53 297   420
A4   595  842   8.26 11.69 210   297
A5   421  595   5.85  8.26 149   210
A6   298  421   4.14  5.85 105   149
A7   211  298   2.93  4.14  74   105
A8   149  211   2.07  2.93  53    74
A9   106  149   1.47  2.07  37    53
A10   75  106   1.04  1.47  26    37

to scale to given paper size, or use unscaled if it fits already.


Want to force page size to Letter (8.5x11) then abut 2 letter pages side by side.
(If getting fancy, slight left/right offset for margin at spine.)

this may do it:

  /usr/bin/pdfjam --nup '2x1' --landscape --papersize '{11in,17in}' --noautoscale 'true' --outfile pdfjam1+2.pdf -- foliotmp2.pdf - foliotmp4.pdf -


if you wanted to glue pages vertically, use --nup 1x2 --no-landscape
If you wanted no auto-scaling of pages (mine stretches output to fill a4 by default), use --noautoscale true 
Setting the paper size to something unconventional works with another switch, such as --papersize '{6.125in,9.250in}'.

Suppose we have a document made up of 'US letter' size pages, and we want to convert it to A4:
  pdfjam 'my US letter file.pdf' --a4paper --outfile 'my A4 file.pdf'

To offset the content of double-sided printed pages so that they are suitable for binding with a Heftstreifen,
 use the --twoside option:

  pdfjam --twoside myfile.pdf --offset '1cm 0cm' --suffix 'offset'



Check for pages being a multiple of 4 or 4X+1 if front cover included. (do we need to check for a back cover?)

gtoal@linux:~/src/printer_spread$ pdfinfo TG.pdf
Creator:        Adobe Acrobat 7.05
Producer:       Adobe Acrobat 7.05 Image Conversion Plug-in
CreationDate:   Sat Jun 17 15:49:07 2006 CDT
ModDate:        Sat Jun 17 15:50:00 2006 CDT
Tagged:         no
UserProperties: no
Suspects:       no
Form:           AcroForm
JavaScript:     no
Pages:          69
Encrypted:      no
Page size:      610.56 x 773.52 pts
Page rot:       0
File size:      2269880 bytes
Optimized:      no
PDF version:    1.6
 */

#define ELEVENby17 1
#define A3         2

int main(int argc, char **argv) {
  int sheet = 1;
  int i, rc;
  static char pdfseparate[1024];
  static char pdfinfo[1024];
  static char twoup[1024];
  static char landscape[1024];
  static char portrait[1024];
  int skip_cover = FALSE;
  int pages = 0, rotation, paper = 0;
  int base_page;
  FILE *info;
  float width, height;
  char *line = NULL;
  size_t len = 0;
  ssize_t nread;

  if ((argc >= 2) && (strcmp(argv[1], "--nocover")==0)) {
    argv += 1; argc -= 1; skip_cover = TRUE;
  }

  if ((argc >= 2) && (strcmp(argv[1], "--11x17")==0)) {
    argv += 1; argc -= 1; paper = ELEVENby17;
  }

  if ((argc >= 2) && (strcmp(argv[1], "--a3")==0)) {
    argv += 1; argc -= 1; paper = A3;
  }

  if (paper == 0) paper = ELEVENby17; // my default
  
  if (argc != 2) {
    fprintf(stderr, "syntax: layout [--nocover] file.pdf\n");
    exit(1);
  }

  sprintf(pdfinfo, "pdfinfo %s", argv[1]);
  info = popen(pdfinfo, "r");
  if (info == NULL) {
    fprintf(stderr, "layout: %s\n", strerror(errno));
    exit(3);
  }

  while ((nread = getline(&line, &len, info)) != -1) {

    rc = sscanf(line, "Pages:          %d\n", &pages);
    if (rc == 1) {
      fprintf(stderr, "Document contains %d pages\n", pages);
    }

    rc = sscanf(line, "Page size:      %f x %f pts\n", &width, &height);
    if (rc == 2) {
      fprintf(stderr, "Page size is %f by %f pts\n", width, height);
    }

    rc = sscanf(line, "Page rot:       %d\n", &rotation);
    if (rc == 1) {
      fprintf(stderr, "Rotation is %d\n", rotation);
    }
  }
  free(line);
  pclose(info);

  if (pages == 0) {
    fprintf(stderr, "layout: no pages to arrange\?\n");
    exit(4);
  }
  
  system("rm -f foliotmp[0-9]*.pdf");
  if (skip_cover) {
    sprintf(pdfseparate, "pdfseparate -f 2 %s foliotmp%%d.pdf", argv[1]); // pages numbered from 1 upwards.  so cover sheet is page 1
    pages -= 1; base_page = 2;
  } else {
    sprintf(pdfseparate, "pdfseparate %s foliotmp%%d.pdf", argv[1]);
    base_page = 1;
  }
  fprintf(stderr, "%s\n", pdfseparate);
  rc = system(pdfseparate);
  if (WIFSIGNALED(rc) && (WTERMSIG(rc) == SIGINT || WTERMSIG(rc) == SIGQUIT)) exit(rc);

  if (rc != 0) {
    if (errno != 0) fprintf(stderr, "layout: %s\n", strerror(errno));
    exit(2);
  }

  // convert each pdf page to an image,
  // use imagemagik (convert) to threshold it to remove grey background
  // repackage back into same-sized pages
  //   pdftoppm foliotmp69.pdf |pnmtopng -hist |convert png:- -sharpen 0x3 -white-threshold '90%' foliotmp69-new.pdf
  
  printf("     two-sided printing\n");
  printf(" lower side     upper side\n");
  system("rm -f twoup[0-9]*.pdf");
  for (i = 0; i < pages/2; i += 2) {
    printf("+-----+-----+  +-----+-----+\n");
    printf("|     |     |  |     |     |\n");
    printf("| %02d  |  %02d |  | %02d  | %02d  |\n",  pages+1-(i+2)+1, i+0+1, i+1+1, pages+1-(i+3)+1);
    printf("|     |     |  |     |     |\n");
    printf("|     |     |  |     |     |\n");
    printf("+-----+-----+  +-----+-----+  sheet %d\n\n", sheet);
    sprintf(twoup, "/usr/bin/pdfjam --nup '2x1' --landscape --papersize '{11in,17in}'"
            " --noautoscale 'true' --outfile twoup%04d-a.pdf -- foliotmp%0d.pdf - foliotmp%0d.pdf -", sheet, pages+1-(i+2), i+0);
    fprintf(stderr, "%s\n", twoup);
    system(twoup);
    sprintf(twoup, "/usr/bin/pdfjam --nup '2x1' --landscape --papersize '{11in,17in}'"
            " --noautoscale 'true' --outfile twoup%04d-b.pdf -- foliotmp%0d.pdf - foliotmp%0d.pdf -", sheet, i+1, pages+1-(i+3));
    fprintf(stderr, "%s\n", twoup);
    system(twoup);
    sheet += 1;
  }
  system("pdfjam twoup*.pdf");
  sprintf(landscape, "mv twoup%04d-b-pdfjam.pdf landscape-tmp.pdf", sheet-1);
  system(landscape);
  system("cpdf -rotate 90 -i landscape-tmp.pdf -o portrait-tmp.pdf");
  system("/usr/bin/pdfjam --papersize '{17in,11in}' --landscape --twoside --scale 2.2 --outfile portrait.pdf  portrait-tmp.pdf");
  fprintf(stderr, "Output is in portrait.pdf\n");
  //  system("rm -f foliotmp[0-9]*.pdf twoup[0-9]*.pdf landscape-tmp.pdf portrait-tmp.pdf");
  if (pages&3) {
    fprintf(stderr, "Warning: not a multiple of 4 pages.  Need to tweak the code to fix that...\n");
    exit(5);
  }
  
  exit(0);
}