home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xconq55.zip / xc5.5 / output.c < prev    next >
C/C++ Source or Header  |  1992-02-14  |  18KB  |  662 lines

  1. /* Copyright (c) 1987, 1988  Stanley T. Shebs. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. /* This file concentrates on the more textual parts of the interface, mainly */
  6. /* the windows dedicated to messages and the like. */
  7.  
  8. #include "config.h"
  9. #include "misc.h"
  10. #include "period.h"
  11. #include "side.h"
  12. #include "unit.h"
  13. #include "map.h"
  14. #include "global.h"
  15.  
  16. char *modenames[] = MODENAMES;  /* names of the modes */
  17. char tmpnbuf[BUFSIZE];          /* tmp buf for notices only. */
  18.  
  19. /* Variables for the "window printf" utility. */
  20.  
  21. bool wprintmode;        /* true when printing is going into a file */
  22.  
  23. char wbuf[BUFSIZE];             /* accumulated line of text */
  24.  
  25. int wline;                      /* current position of output */
  26.  
  27. FILE *wfp;                      /* file pointer for wprintf */
  28.  
  29. /* Send a message to everybody who's got a screen. */
  30.  
  31. /*VARARGS*/
  32. notify_all(control, a1, a2, a3, a4, a5, a6)
  33. char *control, *a1, *a2, *a3, *a4, *a5, *a6;
  34. {
  35.     Side *side;
  36.  
  37.     for_all_sides(side) notify(side, control, a1, a2, a3, a4, a5, a6);
  38. }
  39.  
  40. /* Main message-sending routine - does its own formatting and spits out to */
  41. /* the given side.  A large chunk of memory is allocated for notices.  Scrolling is by copying pointers to strings. */
  42.  
  43. /*VARARGS*/
  44. notify(side, control, a1, a2, a3, a4, a5, a6, a7, a8)
  45. Side *side;
  46. char *control, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
  47. {
  48.     int i;
  49.     static char *note_space = NULL;
  50.     static char *next_string = NULL;
  51.  
  52.  
  53.     if (NULL == note_space) {
  54.       note_space = (char *) malloc(NOTIFY_SPACE * sizeof(char));
  55.       next_string = note_space;
  56.     }
  57.     if (active_display(side)) {
  58.     for (i = MAXNOTES-1; i > 0; --i) {
  59.       side->noticebuf[i] =  side->noticebuf[i-1];
  60.     }
  61.     sprintf(tmpnbuf, control, a1, a2, a3, a4, a5, a6, a7, a8);
  62.     if (islower(tmpnbuf[0])) tmpnbuf[0] = toupper(tmpnbuf[0]);
  63.  
  64.     /* Once we are out of space, just reuse it.  It is possible */
  65.     /* that we will clobber old messages, but enough should be */
  66.     /* around that that is not a real problem. */
  67.        
  68.     if (next_string + strlen(tmpnbuf) + 10 > note_space + NOTIFY_SPACE)
  69.       next_string = note_space;
  70.     side->noticebuf[0] = next_string;
  71.     sprintf(side->noticebuf[0], "%d: %s", global.time, tmpnbuf);
  72.     show_note(side,TRUE);
  73.     flush_output(side);
  74.     while (*next_string++ != '\0');
  75.     side->bottom_note = 0;
  76.     if (Debug) printf("%s\n", side->noticebuf[0]);
  77.     }
  78. }
  79.  
  80. /* Notice area refresher.  All notes except the most recent one are grayed */
  81. /* out (no effect for monochrome). */
  82.  
  83. show_note(side,clear)
  84. Side *side;
  85. int clear;
  86. {
  87.     int i, sy = 0;
  88.  
  89.     if (active_display(side)) {
  90.         if (clear)
  91.       clear_window(side, side->msg);
  92.     for (i = side->nh+side->bottom_note-1; i >= side->bottom_note; --i) {
  93.         draw_text(side, side->msg, side->margin, sy, side->noticebuf[i],
  94.               ((i == 0) ? side->fgcolor : side->graycolor));
  95.         sy += side->fh;
  96.     }
  97.     }
  98. }
  99.  
  100. /* Info about a unit is complicated by the overriding requirement that it */
  101. /* be quickly graspable.  Graphics is helpful, so is fixed format (trains */
  102. /* eyes to get a value of interest from same place each time). */
  103.  
  104. /* Verbal description of what you can see in your view.  Can't always show */
  105. /* names because the view doesn't store them, and the unit at that spot may */
  106. /* not exist anymore.  Units that are "always seen" (like cities) can be */
  107. /* described in more detail, however. */
  108.  
  109. extern int *localworth;                /* for evaluation of nearby hexes */
  110. #define aref(m,x,y) ((m)[(x)+world.width*(y)])
  111. extern Unit *munit;
  112. int printing = FALSE;
  113. extern evaluate_hex();
  114.  
  115. show_info(side)
  116. Side *side;
  117. {
  118.     bool more = (Debug || Build);
  119.     int u, terr, age;
  120.     char *filler = "";
  121.     viewdata view, prevview;
  122.     Unit *unit = side->curunit, *realunit;
  123.     Side *side2;
  124.  
  125.     if (active_display(side)) {
  126.       if (side->curx >= 0 && side->cury >= 0) {
  127.     view = side_view(side, side->curx, side->cury);
  128.     terr = terrain_at(side->curx, side->cury);
  129.     realunit = unit_at(side->curx, side->cury);
  130.     put_on_screen(side, side->curx, side->cury);
  131.     if (unit != NULL) {
  132.       sprintf(tmpbuf, "%s", unit_handle(side, unit));
  133.       draw_info_text(side, 0, 0, 30, tmpbuf);
  134.       more = TRUE;
  135.     } else {
  136.       /* Describe any unit image that might be present. */
  137.       if (view == UNSEEN || view == EMPTY) {
  138.           sprintf(tmpbuf, "");
  139.       } else {
  140.           side2 = side_n(vside(view));
  141.           u = vtype(view);
  142.           if ((utypes[u].seealways ||
  143.            cover(side, side->curx, side->cury) > 0
  144.            || more) && realunit != NULL) {
  145.           sprintf(tmpbuf, "%s", unit_handle(side, realunit));
  146.           } else {
  147.           sprintf(tmpbuf, "%s %s",
  148.               (side2 == NULL ? "neutral" : side2->name),
  149.               utypes[u].name);
  150.           }
  151.           filler = "In ";
  152.       }
  153.       draw_info_text(side, 0, 0, 60, tmpbuf);
  154.       /* Now describe terrain and position. */
  155.       sprintf(tmpbuf, "%s%s at %d,%d",
  156.           filler, (view == UNSEEN ? "(unknown)" : ttypes[terr].name),
  157.           side->curx, side->cury);
  158.       draw_info_text(side, 0, 1, 60, tmpbuf);
  159.         }
  160.     /* put here so overwrites any spillover from name writing */
  161.      if (more) {
  162.       if (unit == NULL) unit = realunit;
  163.       if (unit != NULL) show_intimate_details(side, unit);
  164.     } else {
  165. #ifdef PREVVIEW
  166.       /* Compose and display view history of this hex. */
  167.       if (Debug) printf("Drawing previous view info\n");
  168.       age = side_view_age(side, side->curx, side->cury);
  169.       prevview = side_prevview(side, side->curx, side->cury);
  170.       if (age == 0) {
  171.           if (prevview != view) {
  172.           if (prevview == EMPTY) {
  173.               /* misleading if prevview was set during init. */
  174.               sprintf(tmpbuf, "Up to date; had been empty.");
  175.           } else if (prevview == UNSEEN) {
  176.               sprintf(tmpbuf, "Up to date; had been unexplored.");
  177.           } else {
  178.               side2 = side_n(vside(prevview));
  179.               u = vtype(prevview);
  180.               if (side2 != side) {
  181.               sprintf(tmpbuf, "Up to date; had seen %s %s.",
  182.                   (side2 == NULL ? "neutral" : side2->name),
  183.                   utypes[u].name);
  184.               } else {
  185.               sprintf(tmpbuf,
  186.                   "Up to date; had been occupied by your %s.",
  187.                   utypes[u].name);
  188.               }
  189.           }
  190.           } else {
  191.           sprintf(tmpbuf, "Up to date.");
  192.           }
  193.       } else {
  194.           if (prevview == EMPTY) {
  195.           sprintf(tmpbuf, "Was empty %d turns ago.", age);
  196.           } else if (prevview == UNSEEN) {
  197.           sprintf(tmpbuf, "Terrain first seen %d turns ago.", age);
  198.           } else {
  199.           side2 = side_n(vside(prevview));
  200.           u = vtype(prevview);
  201.           if (side2 != side) {
  202.               sprintf(tmpbuf, "Saw %s %s, %d turns ago.",
  203.                   (side2 == NULL ? "neutral" : side2->name),
  204.                   utypes[u].name, age);
  205.           } else {
  206.               sprintf(tmpbuf, "Was occupied by your %s %d turns ago.",
  207.                   utypes[u].name, age);
  208.           }
  209.           }
  210.       }
  211.       draw_info_text(side, 0, 2, 60, tmpbuf);
  212. #endif
  213.       if (side->curdeadunit != NULL &&
  214.           side->curdeadunit->prevx == side->curx &&
  215.           side->curdeadunit->prevy == side->cury) {
  216.         sprintf(tmpbuf, "%s died here",
  217.             unit_handle(side, side->curdeadunit));
  218.         draw_info_text(side, 0, 4, 80, tmpbuf);
  219.       }
  220.     }
  221.       }
  222.     }
  223. }
  224.  
  225.  
  226. /* Display all the details that only the owner or God (== debugger) sees. */
  227.  
  228. show_intimate_details(side, unit)
  229. Side *side;
  230. Unit *unit;
  231. {
  232.     int i, u = unit->type, r, nums[MAXUTYPES], xpos, p = unit->product;
  233.     Unit *occ;
  234.     char tmp2[BUFSIZE];
  235.  
  236.     sprintf(spbuf, "");
  237.     sprintf(spbuf, "In %s at %d,%d",
  238.         (unit->transport != NULL ? short_unit_handle(unit->transport) :
  239.          ttypes[terrain_at(unit->x, unit->y)].name),
  240.          unit->x, unit->y);
  241.     sprintf(tmpbuf, "");
  242.     draw_info_text(side, 0, 1, 30, spbuf);
  243.     sprintf(spbuf, "");
  244.     if (unit->occupant != NULL) {
  245.     strcpy(spbuf, "Occ ");
  246.     for_all_unit_types(i) nums[i] = 0;
  247.     for_all_occupants(unit, occ) nums[occ->type]++;
  248.     for_all_unit_types(i) {
  249.         if (nums[i] > 0) {
  250.         sprintf(tmpbuf, "%d %c  ", nums[i], utypes[i].uchar);
  251.         strcat(spbuf, tmpbuf);
  252.         }
  253.     }
  254.     }
  255.     draw_info_text(side, 0, 2, 30, spbuf);
  256.     /* If we woke up, add an explanation. */
  257.     tmp2[0] = '\0';
  258.     if (unit->wakeup_reason) { /* and test that unit is awake? */
  259.     if (unit->wakeup_reason == WAKEENEMY) 
  260.       sprintf(tmp2, " (Saw %s %s)",
  261.           (unit->waking_side == NULL ? "neutral" :
  262.            unit->waking_side->name),
  263.           utypes[unit->waking_type].name);
  264.     if (unit->wakeup_reason == WAKERESOURCE) 
  265.       sprintf(tmp2, " (Low on fuel)");
  266.     /*      if (unit->wakeup_reason == WAKETIME) 
  267.         sprintf(tmp2, " (Last order done)"); */
  268.     if (unit->wakeup_reason == WAKELEADERDEAD) 
  269.       sprintf(tmp2, " (Leader died)");
  270.     if (unit->wakeup_reason == WAKELOST) 
  271.       sprintf(tmp2, " (Lost & confused)");
  272.     }
  273.     sprintf(spbuf, "%s%s %s Moves %d",
  274.         order_desig(&(unit->orders)), tmp2,
  275.         (unit->standing != NULL ? "*" : ""),
  276.         unit->movesleft);
  277.     draw_info_text(side, 0, 4, 80, spbuf);
  278.     sprintf(spbuf, "HP %d/%d", unit->hp, utypes[u].hp);
  279.     draw_info_text(side, 30, 0, -1, spbuf);
  280.     if (producing(unit)) {
  281.     sprintf(spbuf, "New %s in %d turns",
  282.         utypes[p].name, unit->schedule);
  283.     draw_info_text(side, 30, 1, -1, spbuf);
  284.     }
  285.     if (producing(unit) && unit->product != unit->next_product) {
  286.     sprintf(spbuf, "Next product is %s",
  287.         utypes[unit->next_product].name);
  288.     draw_info_text(side, 30, 2, -1, spbuf);
  289.     }
  290.     sprintf(spbuf, "");
  291.     for_all_resource_types(r) {
  292.     if (utypes[u].storage[r] > 0) {
  293.         sprintf(tmpbuf, "%s %d/%d  ",
  294.             rtypes[r].name, unit->supply[r], utypes[u].storage[r]);
  295.         strcat(spbuf, tmpbuf);
  296.     }
  297.     }
  298.     draw_info_text(side, 30, 3, -1, spbuf);
  299. }
  300.  
  301. /* Display improvement can be achieved by padding out lines with blanks, */
  302. /* then the lines need not be cleared before redrawing. */
  303.  
  304. draw_info_text(side, x, y, len, buf)
  305. Side *side;
  306. int x, y, len;
  307. char *buf;
  308. {
  309.     int i;
  310.     char full[BUFSIZE];
  311.  
  312.     if (len < 0) len = BUFSIZE;
  313.     strcpy(full, buf);
  314.     for (i = strlen(buf); i < len; ++i) full[i] = ' ';
  315.     full[len-1] = '\0';
  316.     draw_fg_text(side, side->info,
  317.          side->margin + x * side->fw, y * side->fh, full);
  318. }
  319.  
  320. /* Erase the info window.  This is done frequently so worthless stuff isn't */
  321. /* hanging around, such as during someone else's turn. */
  322.  
  323. clear_info(side)
  324. Side *side;
  325. {
  326.     if (active_display(side)) {
  327.     clear_window(side, side->info);
  328.     }
  329. }
  330.  
  331. /* The prompt window consists of exactly one line, but we have to keep track */
  332. /* of where the blank space begins, for when people type into it. */
  333.  
  334. show_prompt(side)
  335. Side *side;
  336. {
  337.     if (active_display(side)) {
  338.     clear_window(side, side->prompt);
  339.     draw_fg_text(side, side->prompt, side->margin, 0, side->promptbuf);
  340.     }
  341. }
  342.  
  343. /* Spit a char onto the prompt line, hopefully after the previous one. */
  344.  
  345. echo_at_prompt(side, ch)
  346. Side *side;
  347. char ch;
  348. {
  349.     char tmp[2];
  350.  
  351.     if (active_display(side)) {
  352.     sprintf(tmp, "%c", ch);
  353.     draw_fg_text(side, side->prompt,
  354.              side->reqcurstr * side->fw + side->margin, 0, tmp);
  355.     flush_output(side);
  356.     }
  357. }
  358.  
  359. /* Spit a cursor onto the prompt line. */
  360.  
  361. write_str_cursor(side)
  362. Side *side;
  363. {
  364.     char tmp[3];
  365.  
  366.     if (active_display(side)) {
  367.     sprintf(tmp, "_ ");
  368.     draw_fg_text(side, side->prompt,
  369.              side->reqcurstr * side->fw + side->margin, 0, tmp);
  370.     flush_output(side);
  371.     }
  372. }
  373.  
  374. /* Clear the prompt line. */
  375.  
  376. clear_prompt(side)
  377. Side *side;
  378. {
  379.     if (active_display(side)) {
  380.     clear_window(side, side->prompt);
  381.     sprintf(side->promptbuf, " ");
  382.     }
  383. }
  384.  
  385. /* Show a list of all sides in action, drawing a line through any that have */
  386. /* lost out.  This has to be called for each side if everybody's list is */
  387. /* to be updated. */
  388.  
  389. /* Highlight the side whose turn it is, using reverse video for current */
  390. /* player's own display (to wake she/he/it up) and white instead of gray */
  391. /* for everybody else.  Also add a star for the benefit of monochrome. */
  392.  
  393. show_all_sides(side, clear)
  394. Side *side;
  395. int clear;
  396. {
  397.     int sx = side->margin + 2 * side->fw, sy = 0, i;
  398.     Side *side2;
  399.  
  400.     if (active_display(side)) {
  401.     if (clear)
  402.       clear_window(side, side->sides);
  403.     for_all_sides(side2) {
  404.         sprintf(spbuf, "%2d", side_number(side2));
  405.         draw_text(side, side->sides, side->margin, sy, spbuf,
  406.               side_color(side, side2));
  407.         sprintf(tmpbuf, "");
  408.         if (side2->host != NULL) sprintf(tmpbuf, "(%s)", side2->host);
  409.         /* Don't bother printing host information past first . */ 
  410.         for (i = 0; i < strlen(tmpbuf); i++) 
  411.           if (tmpbuf[i] == '.') 
  412.         {
  413.           strcpy(tmpbuf+i, ")");
  414.         }
  415.         sprintf(spbuf, ": The %s %s", plural_form(side2->name), tmpbuf);
  416.         draw_text(side, side->sides, sx, sy, spbuf,
  417.               (side == side2 ? side->fgcolor : side->graycolor));
  418.         if (side2->lost) draw_scratchout(side, sy + side->fh / 2);
  419.         sy += side->fh;
  420.     }
  421.     }
  422.     update_sides(side);
  423. }
  424.  
  425. /* The side color here reflects ally/neutral/enemy status. */
  426.  
  427. side_color(side, side2)
  428. Side *side, *side2;
  429. {
  430.     if (side == side2 || allied_side(side, side2)) return side->altcolor;
  431.     if (enemy_side(side, side2)) return side->enemycolor;
  432.     return side->neutcolor;
  433. }
  434.  
  435. /* Show which human players still have units to move this turn
  436.  * by displaying an asterisk in front of the side name in the sides list.
  437.  */
  438. update_sides (side)
  439. Side *side;
  440. {
  441.     int sx = side->margin + 3*side->fw, sy = 0;
  442.     Side *side2;
  443.  
  444.     if (active_display(side)) {
  445.     for_all_sides(side2) {
  446.         if (!side2->lost) {
  447.         draw_text(side, side->sides, sx, sy, 
  448.               (side2->more_units ? "*" : " "),
  449.               (side == side2 ? side->fgcolor : side->graycolor));
  450.         }
  451.         sy += side->fh;
  452.     }
  453.     flush_output(side);
  454.     }
  455. }
  456.  
  457. /* Update the turn number and game mode display.  The mode is inverted */
  458. /* so will stand out (it governs what player input will be accepted, so */
  459. /* quite important). */
  460.  
  461. show_timemode(side,clear)
  462. Side *side;
  463. int clear;
  464. {
  465.     if (active_display(side)) {
  466.     if (clear)
  467.       clear_window(side, side->timemode);
  468.     sprintf(spbuf, "Turn%4d", global.time);
  469.     draw_fg_text(side, side->timemode, side->margin, 0, spbuf);
  470.     sprintf(spbuf, "%s%s",
  471.         modenames[side->mode],
  472.         (side->teach ? "*" : (Build ? "B" : (side->followaction ? "L" : " "))));
  473.     draw_text(side, side->timemode, side->margin, side->fh, spbuf,
  474.           (side == curside ? side->bgcolor : side->fgcolor));
  475.     flush_output(side);
  476.     }
  477. }
  478.  
  479. /* The state display summarizes all the units and any other global info. */
  480.  
  481. show_state(side,clear)
  482. Side *side;
  483. int clear;
  484. {
  485.     int u;
  486.  
  487.     if (active_display(side)) {
  488.     if (clear)
  489.       clear_window(side, side->state);
  490.     draw_unit_list(side, side->bvec);
  491.     for_all_unit_types(u) update_state(side, u);
  492.     }
  493. }
  494.  
  495. /* Alter the numbers for a single type of unit.  Should be called right */
  496. /* after any changes.  Formatted to look nice, but kind of messy to set */
  497. /* up correctly - Cobol isn't all bad! */
  498.  
  499. update_state(side, u)
  500. Side *side;
  501. int u;
  502. {
  503.     int ypos;
  504.     static char    _15space[] = "               ";
  505.  
  506.     if (active_display(side)) {
  507.     sprintf(spbuf, "");
  508.     if (side->units[u] > 0)    
  509.         sprintf(tmpbuf, "%3d", side->units[u]);
  510.     else
  511.         sprintf(tmpbuf, "   ");
  512.     strcat(spbuf, tmpbuf);
  513.     if (side->building[u] > 0) {
  514.         sprintf(tmpbuf, "(%d)", side->building[u]);
  515.         strcat(spbuf, tmpbuf);
  516.     }
  517.     strcat(spbuf, _15space);
  518.     if (total_gain(side, u) > 0) {
  519.         sprintf(spbuf+8, "%4d", total_gain(side, u));
  520.     }
  521.     strcat(spbuf, _15space);
  522.     if (total_loss(side, u) > 0) {
  523.         sprintf(tmpbuf, "- %d", total_loss(side, u));
  524.         sprintf(spbuf+13, "%s", tmpbuf);
  525.     }
  526.     ypos = u * max(side->hh, side->fh) + (side->hh-side->fh) / 2;
  527.     draw_fg_text(side, side->state, side->hw+side->margin, ypos, spbuf);
  528.     }
  529. }
  530.  
  531. /* Would be faster to stash these, but enough difference to care? */
  532.  
  533. total_gain(side, u)
  534. Side *side;
  535. int u;
  536. {
  537.     int i, total = 0;
  538.  
  539.     for (i = 0; i < DUMMYREAS; ++i) total += side->balance[u][i];
  540.     return total;
  541. }
  542.  
  543. total_loss(side, u)
  544. Side *side;
  545. int u;
  546. {
  547.     int i, total = 0;
  548.  
  549.     for (i = DUMMYREAS+1; i < NUMREASONS; ++i) total += side->balance[u][i];
  550.     return total;
  551. }
  552.  
  553. /* To get the traditional digital clock display, we need fixed-format digit */
  554. /* printing.  There will *never* be an option for analog display... */
  555.  
  556. show_clock(side)
  557. Side *side;
  558. {
  559.     int time = ((global.giventime > 0) ? side->timeleft : side->timetaken);
  560.     int hour, minute, second;
  561.  
  562.     hour = time / 3600;  minute = (time / 60) % 60;  second = time % 60;
  563.     if (active_display(side)) {
  564.     clear_window(side, side->clock);
  565.     sprintf(spbuf, "%s%d:%s%d:%s%d",
  566.         (hour < 10 ? "0" : ""), hour,
  567.         (minute < 10 ? "0" : ""), minute,
  568.         (second < 10 ? "0" : ""), second);
  569.     draw_fg_text(side, side->clock, 0, 0, spbuf);
  570.     }
  571. }
  572.  
  573. /* Updates to clock need to be sure that display changes immediately. */
  574.  
  575. update_clock(side)
  576. Side *side;
  577. {
  578.     show_clock(side);
  579. /*    flush_output(side); */
  580. }
  581.  
  582. /* Dump a file into the help window.  This routine is neither sophisticated */
  583. /* nor robust - lines must be short enough and file must be one page. */
  584. /* Returns success or failure of file opening. */
  585.  
  586. show_file(side, fname)
  587. Side *side;
  588. char *fname;
  589. {
  590.     FILE *fp;
  591.  
  592.     if ((fp = fopen(fname, "r")) != NULL) {
  593.     while (fgets(spbuf, BUFSIZE, fp)) {
  594.         spbuf[strlen(spbuf)-1] = '\0';  /* cut off newline */
  595.         wprintf(side, spbuf);
  596.     }
  597.     fclose(fp);
  598.     return TRUE;
  599.     } else {
  600.     return FALSE;
  601.     }
  602. }
  603.  
  604. /* Init our counters or open a file. */
  605.  
  606. init_wprintf(side, fname)
  607. Side *side;
  608. char *fname;
  609. {
  610.     wline = 0;
  611.     if (fname != NULL) {
  612.     wprintmode = TRUE;
  613.     wfp = fopen(fname, "w");
  614.     if (wfp == NULL) {
  615.         notify(side, "Warning: open failed.");
  616.     }
  617.     } else {
  618.     wprintmode = FALSE;
  619.     clear_window(side, side->help);
  620.     }
  621. }
  622.  
  623. /* Make like printf, but to the help window.  This is pretty crude - has an */
  624. /* automatic newlining (mis)feature, and doesn't do anything about long */
  625. /* lines, but it's good enough. */
  626.  
  627. /*VARARGS*/
  628. wprintf(side, control, a1, a2, a3, a4, a5, a6)
  629. Side *side;
  630. char *control, *a1, *a2, *a3, *a4, *a5, *a6;
  631. {
  632.     if (active_display(side)) {
  633.     sprintf(wbuf, control, a1, a2, a3, a4, a5, a6);
  634.     if (wprintmode && wfp != NULL) {
  635.         fprintf(wfp, "%s\n", wbuf);
  636.     } else {
  637.         if (strlen(wbuf) > 0) {
  638.         draw_fg_text(side, side->help, side->margin, wline*side->hfh, wbuf);
  639.         }
  640.         wline++;
  641.     }
  642.     }
  643. }
  644.  
  645. /* If we were actually printing to a file, close it down. */
  646.  
  647. finish_wprintf()
  648. {
  649.     if (wprintmode && wfp != NULL) fclose(wfp);
  650. }
  651.  
  652. /* Frequently-called routine to draw text in the foreground color. */
  653.  
  654. draw_fg_text(side, win, x, y, str)
  655. Side *side;
  656. long win;
  657. int x, y;
  658. char *str;
  659. {
  660.     draw_text(side, win, x, y, str, side->fgcolor);
  661. }
  662.