home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Tex29 / StTeXsrc.zoo / src / dvi.c < prev    next >
C/C++ Source or Header  |  1988-03-13  |  24KB  |  872 lines

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