home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / CMTEX330 / SOURCE / DVI.C < prev    next >
C/C++ Source or Header  |  1992-02-19  |  17KB  |  953 lines

  1.  
  2. /*
  3.  * %Y%:%M%:%I%:%Q%
  4.  *
  5.  * Copyright 1987,1988,1991 Pat J Monardo
  6.  *
  7.  * Redistribution of this file is permitted through
  8.  * the specifications in the file COPYING.
  9.  *
  10.  *
  11.  */
  12.  
  13. #ifndef lint
  14. static char *sccsid = "%A%";
  15. #endif
  16.  
  17. #include "tex.h"
  18.  
  19. file    dvi_file;
  20. str    dvi_name;
  21.  
  22. #define HALF_BUF    2048
  23. #define DVI_BUF_SIZE    4096
  24.  
  25. byte    *dvi_buf;
  26. int    dvi_ptr;
  27. int    dvi_limit;
  28. int    dvi_offset;
  29. int    dvi_gone;
  30.  
  31. int    cur_s;
  32. scal    cur_h;
  33. scal    cur_v;
  34. fnt    dvi_f;
  35. scal    dvi_h;
  36. scal    dvi_v;
  37. scal    max_h;
  38. scal    max_v;
  39. scal    rule_dp;
  40. scal    rule_ht;
  41. scal    rule_wd;
  42. int    max_push;
  43. int    total_pages;
  44. int    dead_cycles;
  45. bool    doing_leaders;
  46. int    last_bop;
  47.  
  48. ptr    down_ptr;
  49. ptr    right_ptr;
  50.  
  51. void
  52. ship_out (p)
  53.     ptr    p;
  54. {
  55.     int    page_loc;
  56.     int    j, k;
  57.  
  58.     if (tracing_output > 0) {
  59.         print_ln();
  60.         print("Completed box being shipped out");
  61.     }
  62.     if (term_offset > MAX_PRINT_LINE - 9) {
  63.         print_ln();
  64.     } else if (term_offset > 0 || file_offset > 0) {
  65.         print(" ");
  66.     }
  67.     print("[");
  68.     for (j = 9; j > 0; decr(j)) {
  69.         if (count(j) != 0) {
  70.             break;
  71.         }
  72.     }
  73.     for (k = 0; k <= j; incr(k)) {
  74.         print_int(count(k));
  75.         if (k < j) {
  76.             print(".");
  77.         }
  78.     }
  79.     update_terminal();
  80.     if (tracing_output > 0) {
  81.         print("]");
  82.         begin_diagnostic();
  83.         show_box(p);
  84.         end_diagnostic(TRUE);
  85.     }
  86.     if (box_height(p) > MAX_DIMEN || box_depth(p) > MAX_DIMEN ||
  87.         box_height(p) + box_depth(p) + v_offset > MAX_DIMEN ||
  88.         box_width(p) + h_offset > MAX_DIMEN) {
  89.         print_err("Huge page cannot be shipped out");
  90.         help_huge_page();
  91.         error();
  92.         if (tracing_output <= 0) {
  93.             begin_diagnostic();
  94.             print_nl("The following box has been deleted:");
  95.             show_box(p);
  96.             end_diagnostic(TRUE);
  97.         }
  98.         goto done;
  99.     }
  100.     if (box_height(p) + box_depth(p) + v_offset > max_v) {
  101.         max_v = box_height(p) + box_depth(p) + v_offset;
  102.     }
  103.     if (box_width(p) + h_offset > max_h) {
  104.         max_h = box_width(p) + h_offset;
  105.     }
  106.     dvi_h = dvi_v = 0;
  107.     cur_h = h_offset;
  108.     dvi_f = null_font;
  109.     if (dvi_name == null_str) {
  110.         if (job_name == null_str) {
  111.             job_name = str_texput;
  112.         }
  113.         pack_job_name(str_dvi);
  114.         while ((dvi_file = b_open_out()) == null_file) {
  115.             prompt_file_name("file name for output", str_dvi);
  116.         }
  117.         dvi_name = make_name_str();
  118.     }
  119.     if (total_pages == 0) {
  120.         start_dvi();
  121.     }
  122.     page_loc = dvi_offset + dvi_ptr;
  123.     dvi_out(BOP);
  124.     for (k = 0; k <= 9; incr(k)) {
  125.         dvi_four(count(k));
  126.     }
  127.     dvi_four(last_bop);
  128.     last_bop = page_loc;
  129.     cur_v = box_height(p) + v_offset;
  130.     if (type(p) == VLIST_NODE) {
  131.         vlist_out(p);
  132.     } else {
  133.         hlist_out(p);
  134.     }
  135.     dvi_out(EOP);
  136.     incr(total_pages);
  137.     cur_s = -1;
  138.  
  139. done:
  140.     if (tracing_output <= 0) {
  141.         print("]");
  142.     }
  143.     dead_cycles = 0;
  144.     update_terminal();
  145. #ifdef STAT
  146.     if (tracing_stats > 1) {
  147.         print_nl("Memory usage before: ");
  148.         print_int(var_used);
  149.         print("&");
  150.         print_int(dyn_used);
  151.         print(";");
  152.     }
  153. #endif
  154.     flush_node_list(p);
  155. #ifdef STAT
  156.     if (tracing_stats > 1) {
  157.         print(" after: ");
  158.         print_int(var_used);
  159.         print("&");
  160.         print_int(dyn_used);
  161.         print_ln();
  162.     }
  163. #endif
  164. }
  165.  
  166. void
  167. hlist_out (this_box)
  168.     ptr    this_box;
  169. {
  170.     scal    left_edge, base_line;
  171.     int    save_loc;
  172.     ptr    p;
  173.  
  174.     p = list_ptr(this_box);
  175.     incr(cur_s);
  176.     if (cur_s > 0) {
  177.         dvi_out(PUSH);
  178.     }
  179.     if (cur_s > max_push) {
  180.         max_push = cur_s;
  181.     }
  182.     save_loc = dvi_offset + dvi_ptr;
  183.     left_edge = cur_h;
  184.     base_line = cur_v;
  185.     while (p != null) {
  186. reswitch:
  187.         if (is_char_node(p)) {
  188.             synch_h();
  189.             synch_v();
  190.             do {
  191.                 int f = font(p);
  192.                 int c = character(p);
  193.                 if (f != dvi_f) {
  194.                     fnt_out(f);
  195.                     dvi_f = f;
  196.                 }
  197.                 if (c >= 128) {
  198.                     dvi_out(SET1);
  199.                 }
  200.                 dvi_out(c);
  201.                 cur_h += char_width(f, char_info(f, c));
  202.                 p = link(p);
  203.             } while (is_char_node(p));
  204.             dvi_h = cur_h;
  205.         } else {
  206.             switch (type(p))
  207.             {
  208.             case HLIST_NODE:
  209.             case VLIST_NODE:
  210.                 if (list_ptr(p) == null) {
  211.                     cur_h += box_width(p);
  212.                 } else {
  213.                     scal save_h = dvi_h;
  214.                     scal save_v = dvi_v;
  215.                     scal edge = cur_h;
  216.                     cur_v = base_line + shift_amount(p);
  217.                     if (type(p) == VLIST_NODE) {
  218.                         vlist_out(p);
  219.                     } else {
  220.                         hlist_out(p);
  221.                     }
  222.                     dvi_h = save_h;
  223.                     dvi_v = save_v;
  224.                     cur_h = edge + box_width(p);
  225.                     cur_v = base_line;
  226.                 }
  227.                 break;
  228.             
  229.             case RULE_NODE:
  230.                 rule_wd = rule_width(p);
  231.                 rule_ht = rule_height(p);
  232.                 rule_dp = rule_depth(p);
  233.                 hrule_out(this_box, base_line);
  234.                 break;
  235.             
  236.             case WHATSIT_NODE:
  237.                 out_whatsit(p);
  238.                 break;
  239.             
  240.             case GLUE_NODE:
  241.                 hskip_out(p, this_box, left_edge, base_line);
  242.                 break;
  243.             
  244.             case KERN_NODE:
  245.                 cur_h += kern_width(p);
  246.                 break;
  247.  
  248.             case MATH_NODE:
  249.                 cur_h += math_width(p);
  250.                 break;
  251.             
  252.             case LIGATURE_NODE:
  253.                 p = make_char_from_lig(p);
  254.                 goto reswitch;
  255.  
  256.             default:
  257.                 break;
  258.             }
  259.             p = link(p);
  260.         }
  261.     }
  262.     prune_movements(save_loc);
  263.     if (cur_s > 0) {
  264.         dvi_pop(save_loc);
  265.     }
  266.     decr(cur_s);
  267. }
  268.  
  269. void
  270. hskip_out (p, this_box, left_edge, base_line)
  271.     ptr    p, this_box;
  272.     scal    left_edge, base_line;
  273. {
  274.     ptr    g;
  275.     int    g_sign, g_order;
  276.     ptr    leader_box;
  277.     scal    leader_wd;
  278.     scal    edge, lx, lq, lr;
  279.     bool    outer_doing_leaders;
  280.  
  281.     g = glue_ptr(p);
  282.     rule_wd = glue_width(g);
  283.     g_order = glue_order(this_box);
  284.     g_sign = glue_sign(this_box);
  285.     if (g_sign != NORMAL) {
  286.         if (g_sign == STRETCHING) {
  287.             if (stretch_order(g) == g_order) {
  288.                 rule_wd +=
  289.                     round(glue_set(this_box) * stretch(g));
  290.             }
  291.         } else {
  292.             if (shrink_order(g) == g_order) {
  293.                 rule_wd -=
  294.                     round(glue_set(this_box) * shrink(g));
  295.             }
  296.         }
  297.     }
  298.     if (subtype(p) >= A_LEADERS) {
  299.         leader_box = leader_ptr(p);
  300.         if (type(leader_box) == RULE_NODE) {
  301.             rule_ht = rule_height(leader_box);
  302.             rule_dp = rule_depth(leader_box);
  303.             hrule_out(this_box, base_line);
  304.             return;
  305.         }
  306.         leader_wd = box_width(leader_box);
  307.         if (leader_wd > 0 && rule_wd > 0) {
  308.             scal save_h, save_v;
  309.             rule_wd += 10;
  310.             edge = cur_h + rule_wd;
  311.             lx = 0;
  312.             if (subtype(p) == A_LEADERS) {
  313.                 save_h = cur_h;
  314.                 cur_h = left_edge;
  315.                 cur_h += leader_wd *
  316.                     ((save_h - left_edge) / leader_wd);
  317.                 if (cur_h < save_h) {
  318.                     cur_h += leader_wd;
  319.                 }
  320.             } else {
  321.                 lq = rule_wd / leader_wd;
  322.                 lr = rule_wd % leader_wd;
  323.                 if (subtype(p) == C_LEADERS) {
  324.                     cur_h += lr / 2;
  325.                 } else {
  326.                     lx = (2 * lr + lq + 1) / (2 * lq + 2);
  327.                     cur_h += (lr - (lq - 1) * lx) / 2;
  328.                 }
  329.             }
  330.             while (cur_h + leader_wd <= edge) {
  331.                 cur_v = base_line + shift_amount(leader_box);
  332.                 synch_v();
  333.                 save_v = dvi_v;
  334.                 synch_h();
  335.                 save_h = dvi_h;
  336.                 outer_doing_leaders = doing_leaders;
  337.                 doing_leaders = TRUE;
  338.                 if (type(leader_box) == VLIST_NODE) {
  339.                     vlist_out(leader_box);
  340.                 } else {
  341.                     hlist_out(leader_box);
  342.                 }
  343.                 doing_leaders = outer_doing_leaders;
  344.                 dvi_v = save_v;
  345.                 dvi_h = save_h;
  346.                 cur_v = save_v;
  347.                 cur_h = save_h + lx + leader_wd;
  348.             }
  349.             cur_h = edge - 10;
  350.             return;
  351.         }
  352.     }
  353.     cur_h += rule_wd;
  354. }
  355.  
  356. void
  357. hrule_out (this_box, base_line)
  358.     ptr    this_box;
  359.     int    base_line;
  360. {
  361.     if (is_running(rule_ht)) {
  362.         rule_ht = box_height(this_box);
  363.     }
  364.     if (is_running(rule_dp)) {
  365.         rule_dp = box_depth(this_box);
  366.     }
  367.     rule_ht = rule_ht + rule_dp;
  368.     if (rule_ht > 0 && rule_wd > 0) {
  369.         synch_h();
  370.         cur_v = base_line + rule_dp;
  371.         synch_v();
  372.         dvi_out(SET_RULE);
  373.         dvi_four(rule_ht);
  374.         dvi_four(rule_wd);
  375.         cur_v = base_line;
  376.         dvi_h += rule_wd;
  377.     }
  378.     cur_h += rule_wd;
  379. }
  380.  
  381. void
  382. vlist_out (this_box)
  383.     ptr    this_box;
  384. {
  385.     scal    left_edge, top_edge;
  386.     int    save_loc;
  387.     ptr    p;
  388.  
  389.     p = list_ptr(this_box);
  390.     incr(cur_s);
  391.     if (cur_s > 0) {
  392.         dvi_out(PUSH);
  393.     }
  394.     if (cur_s > max_push) {
  395.         max_push = cur_s;
  396.     }
  397.     save_loc = dvi_offset + dvi_ptr;
  398.     left_edge = cur_h;
  399.     cur_v -= box_height(this_box);
  400.     top_edge = cur_v;
  401.     while (p != null) {
  402.         if (is_char_node(p)) {
  403.             confusion("vlistout");
  404.         } else {
  405.             switch (type(p))
  406.             {
  407.             case HLIST_NODE:
  408.             case VLIST_NODE:
  409.                 if (list_ptr(p) == null) {
  410.                     cur_v += box_height(p) + box_depth(p);
  411.                 } else {
  412.                     scal save_h, save_v;
  413.                     cur_v += box_height(p);
  414.                     synch_v();
  415.                     save_h = dvi_h;
  416.                     save_v = dvi_v;
  417.                     cur_h = left_edge + shift_amount(p);
  418.                     if (type(p) == VLIST_NODE) {
  419.                         vlist_out(p);
  420.                     } else {
  421.                         hlist_out(p);
  422.                     }
  423.                     dvi_h = save_h;
  424.                     dvi_v = save_v;
  425.                     cur_v = save_v + box_depth(p);
  426.                     cur_h = left_edge;
  427.                 }
  428.                 break;
  429.             
  430.             case RULE_NODE:
  431.                 rule_ht = rule_height(p);
  432.                 rule_dp = rule_depth(p);
  433.                 rule_wd = rule_width(p);
  434.                 vrule_out(this_box);
  435.                 break;
  436.             
  437.             case WHATSIT_NODE:
  438.                 out_whatsit(p);
  439.                 break;
  440.             
  441.             case GLUE_NODE:
  442.                 vskip_out(p, this_box, left_edge, top_edge);
  443.                 break;
  444.  
  445.             case KERN_NODE:
  446.                 cur_v += kern_width(p);
  447.                 break;
  448.  
  449.             default:
  450.                 break;
  451.             }
  452.         }
  453.         p = link(p);
  454.     }
  455.     prune_movements(save_loc);
  456.     if (cur_s > 0) {
  457.         dvi_pop(save_loc);
  458.     }
  459.     decr(cur_s);
  460. }
  461.  
  462. void
  463. vskip_out (p, this_box, left_edge, top_edge)
  464.     ptr    p, this_box;
  465.     scal    left_edge, top_edge;
  466. {
  467.     ptr    g;
  468.     int    g_sign, g_order;
  469.     ptr    leader_box;
  470.     scal    leader_ht;
  471.     scal    edge, lq, lr, lx;
  472.     bool    outer_doing_leaders;
  473.  
  474.     g = glue_ptr(p);
  475.     rule_ht = glue_width(g);
  476.     g_order = glue_order(this_box);
  477.     g_sign = glue_sign(this_box);
  478.     if (g_sign != NORMAL) {
  479.         if (g_sign == STRETCHING) {
  480.             if (stretch_order(g) == g_order) {
  481.                 rule_ht += round(glue_set(this_box) *
  482.                     stretch(g));
  483.             }
  484.         } else if (shrink_order(g) == g_order) {
  485.             rule_ht -= round(glue_set(this_box) * shrink(g));
  486.         }
  487.     }
  488.     if (subtype(p) >= A_LEADERS) {
  489.         leader_box = leader_ptr(p);
  490.         if (type(leader_box) == RULE_NODE) {
  491.             rule_wd = box_width(leader_box);
  492.             rule_dp = 0;
  493.             vrule_out(this_box);
  494.             return;
  495.         }
  496.         leader_ht = box_height(leader_box) + box_depth(leader_box);
  497.         if (leader_ht > 0 && rule_ht > 0) {
  498.             scal save_h, save_v;
  499.             rule_ht += 10;
  500.             edge = cur_v + rule_ht;
  501.             lx = 0;
  502.             if (subtype(p) == A_LEADERS) {
  503.                 save_v = cur_v;
  504.                 cur_v = top_edge;
  505.                 cur_v += leader_ht *
  506.                     ((cur_v - top_edge) / leader_ht);
  507.                 if (cur_v < save_v)
  508.                     cur_v += leader_ht;
  509.             } else {
  510.                 lq = rule_ht / leader_ht;
  511.                 lr = rule_ht % leader_ht;
  512.                 if (subtype(p) == C_LEADERS) {
  513.                     cur_v += lr / 2;
  514.                 } else {
  515.                     lx = (2 * lr + lq + 1) / (2 * lq + 2);
  516.                     cur_v += (lr - (lq - 1) * lx) / 2;
  517.                 }
  518.             }
  519.             while (cur_v + leader_ht <= edge) {
  520.                 cur_h = left_edge + shift_amount(leader_box);
  521.                 synch_h();
  522.                 save_h = dvi_h;
  523.                 cur_v += box_height(leader_box);
  524.                 synch_v();
  525.                 save_v = dvi_v;
  526.                 outer_doing_leaders = doing_leaders;
  527.                 doing_leaders = TRUE;
  528.                 if (type(leader_box) == VLIST_NODE)  {
  529.                     vlist_out(leader_box);
  530.                 } else {
  531.                     hlist_out(leader_box);
  532.                 }
  533.                 doing_leaders = outer_doing_leaders;
  534.                 cur_v = dvi_v = save_v;
  535.                 cur_h = dvi_h = save_h;
  536.                 cur_v += lx + leader_ht -
  537.                     box_height(leader_box);
  538.             }
  539.             cur_v = edge - 10;
  540.             return;
  541.         }
  542.     }
  543.     cur_v += rule_ht;
  544. }
  545.  
  546. void
  547. vrule_out (this_box)
  548.     ptr    this_box;
  549. {
  550.     if (is_running(rule_wd)) {
  551.         rule_wd = box_width(this_box);
  552.     }
  553.     rule_ht += rule_dp;
  554.     cur_v += rule_ht;
  555.     if (rule_ht > 0 && rule_wd > 0) {
  556.         synch_h();
  557.         synch_v();
  558.         dvi_out(PUT_RULE);
  559.         dvi_four(rule_ht);
  560.         dvi_four(rule_wd);
  561.     }
  562. }
  563.  
  564. void
  565. dvi_swap ()
  566. {
  567.     if (dvi_limit == DVI_BUF_SIZE) {
  568.         write_dvi(0, HALF_BUF);
  569.         dvi_limit = HALF_BUF;
  570.         dvi_offset += DVI_BUF_SIZE;
  571.         dvi_ptr = 0;
  572.     } else {
  573.         write_dvi(HALF_BUF, DVI_BUF_SIZE);
  574.         dvi_limit = DVI_BUF_SIZE;
  575.     }
  576.     dvi_gone += HALF_BUF;
  577. }
  578.  
  579. void
  580. dvi_four (x)
  581.     int    x;
  582. {
  583.     if (x >= 0) {
  584.         dvi_out(x / 0100000000);
  585.     } else {
  586.         x += 010000000000;
  587.         x += 010000000000;
  588.         dvi_out(x / 0100000000 + 128);
  589.     }
  590.     x %= 0100000000;
  591.     dvi_out(x / 0200000);
  592.     x %= 0200000;
  593.     dvi_out(x / 0400);
  594.     dvi_out(x % 0400);
  595. }
  596.  
  597. void
  598. dvi_pop (l)
  599.     int    l;
  600. {
  601.     if (l == dvi_offset + dvi_ptr && dvi_ptr > 0) {
  602.         decr(dvi_ptr);
  603.     } else {
  604.         dvi_out(POP);
  605.     }
  606. }
  607.  
  608. void
  609. fnt_out (f)
  610.     fnt    f;
  611. {
  612.     if (!font_used(f)) {
  613.         dvi_font_def(f);
  614.         font_used(f) = TRUE;
  615.     }
  616.     if (f <= 64 + null_font) {
  617.         dvi_out(f - null_font - 1 + FNT_NUM_0);
  618.     } else {
  619.         dvi_out(FNT1);
  620.         dvi_out(f - null_font - 1);
  621.     }
  622. }
  623.  
  624. void
  625. dvi_font_def (f)
  626.     fnt    f;
  627. {
  628.     str    s;
  629.  
  630.     dvi_out(FNT_DEF1);
  631.     dvi_out(f - null_font - 1);
  632.     dvi_out(font_check(f).b0);
  633.     dvi_out(font_check(f).b1);
  634.     dvi_out(font_check(f).b2);
  635.     dvi_out(font_check(f).b3);
  636.     dvi_four(font_size(f));
  637.     dvi_four(font_dsize(f));
  638.     dvi_out(str_length(font_area(f)));
  639.     dvi_out(str_length(font_name(f)));
  640.     for (s = font_area(f); *s != NUL; incr(s)) {
  641.         dvi_out(*s);
  642.     }
  643.     for (s = font_name(f); *s != NUL; incr(s)) {
  644.         dvi_out(*s);
  645.     }
  646. }
  647.  
  648. #define Y_HERE        1
  649. #define Z_HERE        2
  650. #define YZ_OK        3
  651. #define Y_OK        4
  652. #define Z_OK        5
  653. #define D_FIXED        6
  654. #define NONE_SEEN    0
  655. #define Y_SEEN        6
  656. #define Z_SEEN        12
  657.  
  658. void
  659. movement (m, o)
  660.     scal    m;
  661.     int    o;
  662. {
  663.     int    k;
  664.     ptr    p;
  665.     ptr    q;
  666.     int    mstate;
  667.  
  668.     q = new_node(MOVEMENT_NODE_SIZE);
  669.     move_amount(q) = m;
  670.     location(q) = dvi_offset + dvi_ptr;
  671.     if (o == DOWN1) {
  672.         link(q) = down_ptr;
  673.         down_ptr = q;
  674.     } else {
  675.         link(q) = right_ptr;
  676.         right_ptr = q;
  677.     }
  678.     mstate = NONE_SEEN;
  679.     for (p = link(q); p != null; p = link(p)) {
  680.         if (move_amount(p) == m) {
  681.             switch (mstate + info(p))
  682.             {
  683.             case NONE_SEEN + YZ_OK:
  684.             case NONE_SEEN + Y_OK:
  685.             case Z_SEEN + YZ_OK:
  686.             case Z_SEEN + Y_OK:
  687.                 if (location(p) < dvi_gone) {
  688.                     goto not_found;
  689.                 } else {
  690.                     k = location(p) - dvi_offset;
  691.                     if (k < 0)
  692.                         k += DVI_BUF_SIZE;
  693.                     dvi_buf[k] += Y1 - DOWN1;
  694.                     info(p) = Y_HERE;
  695.                     goto found;
  696.                 }
  697.             
  698.             case NONE_SEEN + Z_OK:
  699.             case Y_SEEN + YZ_OK:
  700.             case Y_SEEN + Z_OK:
  701.                 if (location(p) < dvi_gone) {
  702.                     goto not_found;
  703.                 } else {
  704.                     k = location(p) - dvi_offset;
  705.                     if (k < 0) {
  706.                         k += DVI_BUF_SIZE;
  707.                     }
  708.                     dvi_buf[k] += Z1 - DOWN1;
  709.                     info(p) = Z_HERE;
  710.                     goto found;
  711.                 }
  712.             
  713.             case NONE_SEEN + Y_HERE:
  714.             case NONE_SEEN + Z_HERE:
  715.             case Y_SEEN + Z_HERE:
  716.             case Z_SEEN + Y_HERE:
  717.                 goto found;
  718.             }
  719.         } else {
  720.             switch (mstate + info(p))
  721.             {
  722.             case NONE_SEEN + Y_HERE:
  723.                 mstate = Y_SEEN;
  724.                 break;
  725.             
  726.             case NONE_SEEN + Z_HERE:
  727.                 mstate = Z_SEEN;
  728.                 break;
  729.             
  730.             case Y_SEEN + Z_HERE:
  731.             case Z_SEEN + Y_HERE:
  732.                 goto not_found;
  733.             
  734.             default:
  735.                 break;
  736.             }
  737.         }
  738.     }
  739.  
  740. not_found:
  741.     info(q) = YZ_OK;
  742.     if (abs(m) >= 040000000) {
  743.         dvi_out(o + 3);
  744.         dvi_four(m);
  745.         return;
  746.     }
  747.     if (abs(m) >= 0100000) {
  748.         dvi_out(o + 2);
  749.         if (m < 0) {
  750.             m += 0100000000;
  751.         }
  752.         dvi_out(m / 0200000);
  753.         m %= 0200000;
  754.         goto two;
  755.     }
  756.     if (abs(m) >= 0200) {
  757.         dvi_out(o + 1);
  758.         if (m < 0) {
  759.             m += 0200000;
  760.         }
  761.         goto two;
  762.     }
  763.     dvi_out(o);
  764.     if (m < 0) {
  765.         m += 0400;
  766.     }
  767.     goto one;
  768.  
  769. two: dvi_out(m / 0400);
  770. one: dvi_out(m % 0400);
  771.     return;
  772.  
  773. found:
  774.     info(q) = info(p);
  775.     if (info(q) == Y_HERE) {
  776.         dvi_out(o + Y0 - DOWN1);
  777.         while (link(q) != p) {
  778.             q = link(q);
  779.             switch (info(q))
  780.             {
  781.             case YZ_OK:
  782.                 info(q) = Z_OK;
  783.                 break;
  784.             
  785.             case Y_OK:
  786.                 info(q) = D_FIXED;
  787.                 break;
  788.             }
  789.         }
  790.     } else {
  791.         dvi_out(o + Z0 - DOWN1);
  792.         while (link(q) != p) {
  793.             q = link(q);
  794.             switch (info(q))
  795.             {
  796.             case YZ_OK:
  797.                 info(q) = Y_OK;
  798.                 break;
  799.             
  800.             case Z_OK:
  801.                 info(q) = D_FIXED;
  802.                 break;
  803.             default:
  804.                 break;
  805.             }
  806.         }
  807.     }
  808. }
  809.  
  810. void
  811. prune_movements (l)
  812.     int    l;
  813. {
  814.     ptr    p;
  815.  
  816.     while (down_ptr != null) {
  817.         if (location(down_ptr) < l)
  818.             break;
  819.         p = down_ptr;
  820.         down_ptr = link(p);
  821.         free_node(p, MOVEMENT_NODE_SIZE);
  822.     }
  823.     while (right_ptr != null) {
  824.         if (location(right_ptr) < l)
  825.             break;
  826.         p = right_ptr;
  827.         right_ptr = link(p);
  828.         free_node(p, MOVEMENT_NODE_SIZE);
  829.     }
  830. }
  831.  
  832. void
  833. start_dvi ()
  834. {
  835.     str    s;
  836.     int    old_setting;
  837.  
  838.     dvi_out(PRE);
  839.     dvi_out(ID_BYTE);
  840.     dvi_four(25400000);
  841.     dvi_four(473628672);
  842.     prepare_mag();
  843.     dvi_four(mag);
  844.     old_setting = selector;
  845.     selector = NEW_STRING;
  846.     print(" Common TeX output ");
  847.     print_int(year);
  848.     print(".");
  849.     print_two(month);
  850.     print(".");
  851.     print_two(day);
  852.     print(":");
  853.     print_two(time / 60);
  854.     print_two(time % 60);
  855.     selector = old_setting;
  856.     dvi_out(cur_length());
  857.     for (s = cur_str; s < cur_str_ptr; incr(s)) {
  858.         dvi_out(*s);
  859.     }
  860.     flush_str();
  861. }
  862.  
  863. void
  864. fin_dvi ()
  865. {
  866.     int    f;
  867.  
  868.     while (cur_s > -1) {
  869.         if (cur_s > 0) {
  870.             dvi_out(POP);
  871.         } else {
  872.             dvi_out(EOP);
  873.             incr(total_pages);
  874.         }
  875.         decr(cur_s);
  876.     }
  877.     if (total_pages == 0) {
  878.         print_nl("No pages of output.");
  879.         return;
  880.     }
  881.     dvi_out(POST);
  882.     dvi_four(last_bop);
  883.     last_bop = dvi_offset + dvi_ptr - 5;
  884.     dvi_four(25400000);
  885.     dvi_four(473628672);
  886.     prepare_mag();
  887.     dvi_four(mag);
  888.     dvi_four(max_v);
  889.     dvi_four(max_h);
  890.     dvi_out(max_push / 256);
  891.     dvi_out(max_push % 256);
  892.     dvi_out(total_pages / 256 % 256);
  893.     dvi_out(total_pages % 256);
  894.     for (f = null_font + font_ptr - font_info - 1;
  895.         f > null_font; decr(f)) {
  896.         if (font_used(f)) {
  897.             dvi_font_def(f);
  898.         }
  899.     }
  900.     dvi_out(POST_POST);
  901.     dvi_four(last_bop);
  902.     dvi_out(ID_BYTE);
  903.     for (f = 4 + (DVI_BUF_SIZE - dvi_ptr) % 4; f > 0; decr(f)) {
  904.         dvi_out(223);
  905.     }
  906.     if (dvi_limit == HALF_BUF) {
  907.         write_dvi(HALF_BUF, DVI_BUF_SIZE);
  908.     }
  909.     if (dvi_ptr > 0) {
  910.         write_dvi(0, dvi_ptr);
  911.     }
  912.     print_nl("Output written on ");
  913.     print(dvi_name);
  914.     print(" (");
  915.     print_int(total_pages);
  916.     print(" page");
  917.     if (total_pages != 1) {
  918.         print("s");
  919.     }
  920.     print(", ");
  921.     print_int(dvi_offset + dvi_ptr);
  922.     print(" bytes).");
  923.     b_close(dvi_file);
  924. }
  925.  
  926. void
  927. _dvi_init ()
  928. {
  929.     dvi_limit = DVI_BUF_SIZE;
  930.     dvi_name = null_str;
  931.     last_bop = -1;
  932.     cur_s = -1;
  933. }
  934.  
  935. void
  936. _dvi_init_once ()
  937. {
  938.     dvi_buf = (byte *)malloc(DVI_BUF_SIZE);
  939.     if (dvi_buf == (byte *) 0) {
  940.         overflow("dvi buffer", DVI_BUF_SIZE);
  941.     }
  942. }
  943.  
  944. /*
  945. **    Help text
  946. */
  947.  
  948. help_huge_page ()
  949. {
  950.     help2("The page just created is more than 18 feet tall or",
  951.     "more than 18 feet wide, so I suspect something went wrong.");
  952. }
  953.