home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / game / think / chaos / src / out.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-07  |  30.2 KB  |  1,234 lines

  1. /*  Chaos:            The Chess HAppening Organisation System    V5.1a
  2.     Copyright (C)   1993    Jochen Wiedmann
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.     $RCSfile: Out.c,v $
  20.     $Revision: 2.4 $
  21.     $Date: 1993/12/06 00:32:30 $
  22.  
  23.     This file contains most of the output-functions.
  24.  
  25.     Computer:    Amiga 1200            Compiler:    Dice 2.07.54 (3.0)
  26.  
  27.     Author:    Jochen Wiedmann
  28.         Am Eisteich 9
  29.       72555 Metzingen
  30.         Tel. 07123 / 14881
  31.         Internet: wiedmann@mailserv.zdv.uni-tuebingen.de
  32. */
  33.  
  34.  
  35. #ifndef CHAOS_H
  36. #include "chaos.h"
  37. #endif
  38.  
  39.  
  40.  
  41.  
  42. /*
  43.     PointsToA() creates a string holding the number of points from p.
  44.  
  45.     Inputs: s - the string where the result should be written
  46.         p - the number of points
  47. */
  48. void PointsToA(char *s, long p)
  49.  
  50. { sprintf(s, "%ld%s", p/2, (p%2)?".5":"  ");
  51. }
  52.  
  53.  
  54.  
  55.  
  56. /*
  57.     tdwz() returns the DW (German rating number) of a player as short.
  58. */
  59. int tdwz(struct Player *t)
  60.  
  61. { long dwz;
  62.  
  63. #ifdef AMIGA
  64.   if (StrToLong((STRPTR) t->DWZ, &dwz) < 0)
  65.   { dwz = 0;
  66.   }
  67. #else
  68.   dwz = atol(t->DWZ);
  69. #endif
  70.   return ((short) dwz);
  71. }
  72.  
  73.  
  74.  
  75.  
  76. /*
  77.     RatingToA() gets a string from a DWZ or ELO number.
  78.  
  79.     Inputs: s - the string, that should be written
  80.         w - the rating number (Note, that this must not be the
  81.         Player->DWZ field itself, because this is a string!)
  82. */
  83. static void RatingToA(char *s, int w)
  84.  
  85. { if(w == 0)
  86.   { *s = '\0';
  87.   }
  88.   else
  89.   { sprintf(s, "%d", w);
  90.   }
  91. }
  92.  
  93.  
  94.  
  95.  
  96. /*
  97.     lprint() is used to buffer the output which will be done later with
  98.     ProcessOutput(). It can work in two modes: The first is building a list
  99.     of lines, the second is collecting ALL lines in a single string.
  100.     The latter is needed on the Amiga for using a FloatText gadget while the
  101.     list is needed for output on the printer.
  102.  
  103.     Inputs: line - the string holding the line
  104.  
  105.     Result: TRUE, if successfull, FALSE otherwise
  106. */
  107. int lprint(char *line)
  108.  
  109. { extern struct MinList OutputList;
  110.   extern void *OutputMemList;
  111.   extern int OutputLineLen, OutputLineMaxLen;
  112.   extern char*OutputLine;
  113.   extern int OutputReturnCode;
  114.   struct MinNode *n;
  115.   char *ptr;
  116.   int i, len;
  117.  
  118.   /*
  119.       Get length of string, ignore trailing blanks.
  120.   */
  121.   for (i = 1, len = 0, ptr = line;  *ptr != '\0';  ptr++, i++)
  122.   { if (*ptr != ' ')
  123.     { len = i;
  124.     }
  125.   }
  126.  
  127.   if (OutputLineMaxLen == -1)
  128.   { if ((n = GetMem(&OutputMemList, sizeof(*n)+len+1))  ==  NULL)
  129.     { OutputReturnCode = RETURN_ERROR;
  130.       return(FALSE);
  131.     }
  132.  
  133.     strncpy((char *) (n+1), line, len);
  134.     ((char *) (n+1))[len] = '\0';
  135.     AddTail((struct List *) &OutputList, (struct Node *) n);
  136.   }
  137.   else
  138.   { while (OutputLineLen + len + 2  >  OutputLineMaxLen)
  139.     { if ((ptr = GetMem(&OutputMemList, OutputLineMaxLen += 16384))  ==  NULL)
  140.       { OutputReturnCode = RETURN_ERROR;
  141.     return(FALSE);
  142.       }
  143.       if (OutputLine != NULL)
  144.       { strcpy(ptr, OutputLine);
  145.     PutMem(OutputLine);
  146.       }
  147.       OutputLine = ptr;
  148.     }
  149.  
  150.     strncpy(OutputLine+OutputLineLen, line, len);
  151.     OutputLine[OutputLineLen += len] = '\n';
  152.     OutputLine[++OutputLineLen] = '\0';
  153.   }
  154.   return(TRUE);
  155. }
  156.  
  157.  
  158.  
  159.  
  160. /*
  161.     longlprint() does the same job as lprint(), but can process text with
  162.     more than one line. The lines are split and lprint is called for each
  163.     line.
  164.  
  165.     Inputs: txt - the string holding the text; note, that a single line must
  166.           not extend 512 characters!
  167.  
  168.     Result: TRUE, if successfull, FALSE otherwise
  169. */
  170. int longlprint(char *txt)
  171.  
  172. { char line[512];
  173.   char *lptr;
  174.   char c;
  175.  
  176.   while (*txt != '\0')
  177.   { lptr = line;
  178.     while ((c = *txt) != '\0'  &&  c != '\n')
  179.     { *(lptr++) = *(txt++);
  180.     }
  181.     *lptr = '\0';
  182.     if (!lprint(line))
  183.     { return(FALSE);
  184.     }
  185.     if (c == '\n')
  186.     { txt++;
  187.     }
  188.   }
  189.   return(TRUE);
  190. }
  191.  
  192.  
  193.  
  194.  
  195. /*
  196.     This function prints the list of players.
  197.  
  198.     Inputs: filename    - destination file; see InitOutput()
  199.         device    - device; see InitOutput()
  200.         longformat    - TRUE, if long format, FALSE otherwise
  201. */
  202. void OutPlayerList(char *filename, int device, int longformat)
  203.  
  204. { struct Player *t;
  205.   int i, lines;
  206.   char head[301];
  207.   char line1[121], line2[121], line3[121];
  208.   char dwz[6], elo[6];
  209.  
  210.   if (longformat == FALSE)
  211.   { lines = 1;
  212.     sprintf(head, "%-4s %-30s %6s %6s %s",
  213.         GetChaosString(MSG_NUMBER),
  214.         GetChaosString(MSG_NAME_OUTPUT),
  215.         GetChaosString(MSG_DWZ_OUTPUT),
  216.         GetChaosString(MSG_ELO_OUTPUT),
  217.         GetChaosString(MSG_CHESSCLUB_OUTPUT));
  218.   }
  219.   else
  220.   { lines = 4;
  221.     sprintf(head, "%-4s %-30s %-30s %s\n"
  222.           "     %-30s %-30s %s\n"
  223.           "     %-15s %s%s%s %s%s%s%s%s      %s\n",
  224.         GetChaosString(MSG_NUMBER),
  225.         GetChaosString(MSG_NAME_OUTPUT),
  226.         GetChaosString(MSG_STREET_OUTPUT),
  227.         GetChaosString(MSG_DWZ_OUTPUT),
  228.  
  229.         GetChaosString(MSG_CHESSCLUB_OUTPUT),
  230.         GetChaosString(MSG_VILLAGE_OUTPUT),
  231.         GetChaosString(MSG_ELO_OUTPUT),
  232.  
  233.         GetChaosString(MSG_BIRTHDAY_OUTPUT),
  234.         GetChaosString(MSG_SENIOR_SHORT),
  235.         GetChaosString(MSG_JUNIOR_SHORT),
  236.         GetChaosString(MSG_WOMAN_SHORT),
  237.         GetChaosString(MSG_JUNIORA_SHORT),
  238.         GetChaosString(MSG_JUNIORB_SHORT),
  239.         GetChaosString(MSG_JUNIORC_SHORT),
  240.         GetChaosString(MSG_JUNIORD_SHORT),
  241.         GetChaosString(MSG_JUNIORE_SHORT),
  242.         GetChaosString(MSG_PHONE_OUTPUT));
  243.   }
  244.   if (!InitOutput((char *) GetChaosString(MSG_PLAYER_LIST_TITLE),
  245.           head, head, filename, "#?.plst", device, lines, lines))
  246.   { TerminateOutput();
  247.     return;
  248.   }
  249.  
  250.   for (t = (struct Player *) PlayerList.lh_Head, i = 1;
  251.        t->Tn_Node.ln_Succ != NULL;
  252.        t = (struct Player *) t->Tn_Node.ln_Succ, i++)
  253.   { RatingToA(dwz, tdwz(t));
  254.     RatingToA(elo, (int) t->ELO);
  255.  
  256.     if (!longformat)
  257.     { sprintf(line1, "%-4d %-30s %6s %6s %-30s", i, t->Name, dwz, elo,
  258.           t->ChessClub);
  259.       if (!lprint(line1))
  260.       { TerminateOutput();
  261.     return;
  262.       }
  263.     }
  264.     else
  265.     { sprintf(line1, "%-4d %-30s %-30s %s", i, t->Name, t->Street, dwz);
  266.       sprintf(line2, "     %-30s %-30s %s", t->ChessClub, t->Village, elo);
  267.       sprintf(line3, "     %-15s %s%s%s %s%s%s%s%s      %s",
  268.           t->BirthDay,
  269.           (t->Flags & TNFLAGSF_SENIOR)   ?
  270.             (char *) GetChaosString(MSG_SENIOR_SHORT)  : " ",
  271.           (t->Flags & TNFLAGSF_JUNIOR)   ?
  272.             (char *) GetChaosString(MSG_JUNIOR_SHORT)  : " ",
  273.           (t->Flags & TNFLAGSF_WOMAN)     ?
  274.             (char *) GetChaosString(MSG_WOMAN_SHORT)   : " ",
  275.           (t->Flags & TNFLAGSF_JUNIORA)  ?
  276.             (char *) GetChaosString(MSG_JUNIORA_SHORT) : " ",
  277.           (t->Flags & TNFLAGSF_JUNIORB)  ?
  278.             (char *) GetChaosString(MSG_JUNIORB_SHORT) : " ",
  279.           (t->Flags & TNFLAGSF_JUNIORC)  ?
  280.             (char *) GetChaosString(MSG_JUNIORC_SHORT) : " ",
  281.           (t->Flags & TNFLAGSF_JUNIORD)  ?
  282.             (char *) GetChaosString(MSG_JUNIORD_SHORT) : " ",
  283.           (t->Flags & TNFLAGSF_JUNIORE)  ?
  284.             (char *) GetChaosString(MSG_JUNIORE_SHORT) : " ",
  285.           t->PhoneNr);
  286.  
  287.       if (!lprint(line1)  ||  !lprint(line2)  ||
  288.       !lprint(line3)  ||  !lprint(""))
  289.       { TerminateOutput();
  290.     return;
  291.       }
  292.     }
  293.   }
  294.  
  295.   ProcessOutput();
  296.   TerminateOutput();
  297. }
  298.  
  299.  
  300.  
  301.  
  302. /*
  303.     This function prints the results of one round.
  304.  
  305.     Inputs: filename    - destination file; see InitOutput()
  306.         device    - output device; see InitOutput()
  307.         Round    - number of the round, that should be printed
  308. */
  309. void OutRound(char *filename, int device, int Round)
  310.  
  311. { void *memlist;
  312.   struct MinList *rlist;
  313.   struct GameNode *gn;
  314.   char head[81];
  315.   char title[81];
  316.  
  317.   if ((rlist = GetRound(&memlist, Round, TRUE,
  318.             (device == DEVICE_Screen) ? 0 : 1))
  319.          ==  NULL)
  320.   { return;
  321.   }
  322.  
  323.   sprintf(head, "%4s %-30s:%-30s %s",
  324.       GetChaosString(MSG_NUMBER),
  325.       GetChaosString(MSG_WHITE_OUTPUT),
  326.       GetChaosString(MSG_BLACK_OUTPUT),
  327.       GetChaosString(MSG_RESULT_OUTPUT));
  328.   sprintf(title, (char *) GetChaosString(MSG_ROUND_TITLE), Round);
  329.   if (!InitOutput(title, head, head, filename, "#?.rslt", device, 1, 1))
  330.   { goto Terminate;
  331.   }
  332.  
  333.   for(gn = (struct GameNode *) rlist->mlh_Head;
  334.       gn->gn_Node.mln_Succ != NULL;
  335.       gn = (struct GameNode *) gn->gn_Node.mln_Succ)
  336.   { if (!lprint(gn->Text))
  337.     { goto Terminate;
  338.     }
  339.   }
  340.  
  341.   ProcessOutput();
  342.  
  343. Terminate:
  344.   TerminateOutput();
  345.   PutMemList(&memlist);
  346. }
  347.  
  348.  
  349.  
  350.  
  351. /*
  352.     This function creates the table. The players are connected via the
  353.     Player->Helpptr field.
  354.  
  355.     Inputs: sortmode    - sorting mode, either 0 (simple mode) or one of the
  356.               flags TNMODEF_BUCHHOLZ, TNMODEF_EXT_BUCHHOLZ or
  357.               TNMODEF_SONNEBORN_BERGER
  358.  
  359.     Result: pointer to the best player in the table
  360. */
  361. struct Player *MakeTable(int sortmode)
  362.  
  363. { struct Player *t, **tptr, *TabFirst;
  364.   struct Game *g;
  365.  
  366.   for (t = (struct Player *) PlayerList.lh_Head;
  367.        t->Tn_Node.ln_Succ != NULL;
  368.        t = (struct Player *) t->Tn_Node.ln_Succ)
  369.   { t->Buchholz = t->ExtBuchholz = 0;
  370.   }
  371.  
  372.   /*
  373.       Getting the Buchholz points
  374.   */
  375.   if (sortmode & (TNMODEF_BUCHHOLZ|TNMODEF_EXT_BUCHHOLZ))
  376.   { for (t = (struct Player *) PlayerList.lh_Head;
  377.      t->Tn_Node.ln_Succ != NULL;
  378.      t = (struct Player *) t->Tn_Node.ln_Succ)
  379.     { for (g = t->First_Game;  g != NULL;  g = g->Next)
  380.       { if ((g->Flags & GMFLAGSF_POINTFORFREE)  ==  0)
  381.     { t->Buchholz += g->Opponent->Points;
  382.     }
  383.       }
  384.     }
  385.  
  386.   /*
  387.       Getting the extended Buchholz points
  388.   */
  389.     if (sortmode & TNMODEF_EXT_BUCHHOLZ)
  390.     { for (t = (struct Player *) PlayerList.lh_Head;
  391.        t->Tn_Node.ln_Succ != NULL;
  392.        t = (struct Player *) t->Tn_Node.ln_Succ)
  393.       { for (g = t->First_Game;  g != NULL;  g = g->Next)
  394.     { if ((g->Flags & GMFLAGSF_POINTFORFREE)  ==  0)
  395.       { t->ExtBuchholz += g->Opponent->Buchholz;
  396.       }
  397.     }
  398.       }
  399.     }
  400.   }
  401.   /*
  402.       Getting the Sooneborn-Berger points
  403.   */
  404.   else if (sortmode & TNMODEF_SONNEBORN_BERGER)
  405.   { for (t = (struct Player *) PlayerList.lh_Head;
  406.      t->Tn_Node.ln_Succ != NULL;
  407.      t = (struct Player *) t->Tn_Node.ln_Succ)
  408.     { for (g = t->First_Game;  g != NULL;  g = g->Next)
  409.       { if ((g->Flags & GMFLAGSF_POINTFORFREE) == 0  &&
  410.         g->Result != -1)
  411.     { t->Buchholz += g->Opponent->Points * g->Result;
  412.     }
  413.       }
  414.     }
  415.   }
  416.  
  417.   /*
  418.       Sorting
  419.   */
  420.   TabFirst = NULL;
  421.   for (t = (struct Player *) PlayerList.lh_Head;
  422.        t->Tn_Node.ln_Succ != NULL;
  423.        t = (struct Player *) t->Tn_Node.ln_Succ)
  424.   { for (tptr = &TabFirst;  *tptr != NULL;
  425.      tptr = (struct Player **) &((*tptr)->Helpptr))
  426.     { if (t->Points > (*tptr)->Points  ||
  427.       (t->Points == (*tptr)->Points  &&
  428.        (t->Buchholz > (*tptr)->Buchholz  ||
  429.         (t->Buchholz == (*tptr)->Buchholz  &&
  430.          t->ExtBuchholz > (*tptr)->ExtBuchholz))))
  431.       { break;
  432.       }
  433.     }
  434.     t->Helpptr = *tptr;
  435.     *tptr = t;
  436.   }
  437.   return(TabFirst);
  438. }
  439.  
  440.  
  441.  
  442.  
  443. /*
  444.     The following function prints the table.
  445.  
  446.     Inputs: filename    - destination file; see InitOutput()
  447.         device    - output device; see InitOutput()
  448.         plrmode    - tells which players to include into the table:
  449.               Either 0 for all players or one of the flags
  450.               TNFLAGSF_SENIOR, TNFLAGSF_JUNIOR, TNFLAGSF_WOMAN,
  451.               TNFLAGSF_JUNIORA, TNFLAGSF_JUNIORB,
  452.               TNFLAGSF_JUNIORC, TNFLAGSF_JUNIORD or
  453.               TNFLAGSF_JUNIORE
  454.         sortmode    - tells how to sort the table; see MakeTable()
  455. */
  456. void OutTable(char *filename, int device, int plrmode, int sortmode)
  457.  
  458. { struct Player *t, *TabFirst;
  459.   int i, Place;
  460.   long pextbuchholz;
  461.   short ppoints, pbuchholz;
  462.   char head[81];
  463.   char line[81];
  464.   char title[81];
  465.   char subtitle[81];
  466.   char ppointsstrtr[10], pbuchholzstr[10], pextbuchholzstr[10];
  467.  
  468.   TabFirst = MakeTable(sortmode);
  469.  
  470.   switch (sortmode & TNMODE_TABMASK)
  471.   { case TNMODEF_BUCHHOLZ:
  472.       sprintf(head, "%-5s %-6s %-8s %-30s", GetChaosString(MSG_PLACE_OUTPUT),
  473.           GetChaosString(MSG_POINTS_OUTPUT),
  474.           GetChaosString(MSG_BUCHHOLZ_OUTPUT),
  475.           GetChaosString(MSG_NAME_OUTPUT));
  476.       break;
  477.     case TNMODEF_EXT_BUCHHOLZ:
  478.       sprintf(head, "%-5s %-6s %-8s %-9s %-30s",
  479.           GetChaosString(MSG_PLACE_OUTPUT),
  480.           GetChaosString(MSG_POINTS_OUTPUT),
  481.           GetChaosString(MSG_BUCHHOLZ_OUTPUT),
  482.           GetChaosString(MSG_EXT_BUCHHOLZ_OUTPUT),
  483.           GetChaosString(MSG_NAME_OUTPUT));
  484.       break;
  485.     case TNMODEF_SONNEBORN_BERGER:
  486.       sprintf(head, "%-5s %-6s %-8s %-30s", GetChaosString(MSG_PLACE_OUTPUT),
  487.           GetChaosString(MSG_POINTS_OUTPUT),
  488.           GetChaosString(MSG_SONNEBORN_BERGER_OUTPUT),
  489.           GetChaosString(MSG_NAME_OUTPUT));
  490.       break;
  491.     default:
  492.       sprintf(head, "%5s %6s %-30s", GetChaosString(MSG_PLACE_OUTPUT),
  493.           GetChaosString(MSG_POINTS_OUTPUT),
  494.           GetChaosString(MSG_NAME_OUTPUT));
  495.   }
  496.  
  497.   switch (plrmode)
  498.   { case TNFLAGSF_SENIOR:
  499.       sprintf(subtitle, "  -  %s",
  500.           GetChaosString(MSG_OUTPUT_TABLE_SENIORS_SUB));
  501.       break;
  502.     case TNFLAGSF_JUNIOR:
  503.       sprintf(subtitle, "  -  %s",
  504.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORS_SUB));
  505.       break;
  506.     case TNFLAGSF_WOMAN:
  507.       sprintf(subtitle, "  -  %s",
  508.           GetChaosString(MSG_OUTPUT_TABLE_WOMEN_SUB));
  509.       break;
  510.     case TNFLAGSF_JUNIORA:
  511.       sprintf(subtitle, "  -  %s",
  512.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSA_SUB));
  513.       break;
  514.     case TNFLAGSF_JUNIORB:
  515.       sprintf(subtitle, "  -  %s",
  516.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSB_SUB));
  517.       break;
  518.     case TNFLAGSF_JUNIORC:
  519.       sprintf(subtitle, "  -  %s",
  520.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSC_SUB));
  521.       break;
  522.     case TNFLAGSF_JUNIORD:
  523.       sprintf(subtitle, "  -  %s",
  524.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSD_SUB));
  525.       break;
  526.     case TNFLAGSF_JUNIORE:
  527.       sprintf(subtitle, "  -  %s",
  528.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSE_SUB));
  529.       break;
  530.     default:
  531.       sprintf(subtitle, "");
  532.       break;
  533.   }
  534.   if (sortmode & TNMODEF_SWISS_PAIRING)
  535.   { sprintf(title, (char *) GetChaosString(MSG_TABLE_TITLE),
  536.         (NumGamesMissing == 0) ? NumRounds : NumRounds-1,
  537.         subtitle);
  538.   }
  539.   else
  540.   { sprintf(title, (char *) GetChaosString(MSG_TABLE_TITLE2), subtitle);
  541.   }
  542.  
  543.  
  544.   if (!InitOutput(title, head, head, filename, "#?.tbl", device, 1, 1))
  545.   { TerminateOutput();
  546.     return;
  547.   }
  548.  
  549.   /*
  550.       Force initialization of ppoints, pbucholz and bextbuchholz in the
  551.       following loop.
  552.   */
  553.   ppoints = -1;
  554.  
  555.   for (i = 0, t = TabFirst;  t != NULL;  t = t->Helpptr)
  556.   { if (plrmode != 0  &&  (plrmode & t->Flags) == 0)
  557.     { continue;
  558.     }
  559.     i++;
  560.     if (ppoints != t->Points  ||  pbuchholz != t->Buchholz  ||
  561.     pextbuchholz != t->ExtBuchholz)
  562.     { Place = i;
  563.       ppoints = t->Points;
  564.       pbuchholz = t->Buchholz;
  565.       pextbuchholz = t->ExtBuchholz;
  566.     }
  567.  
  568.     PointsToA(ppointsstrtr, (long) ppoints);
  569.     PointsToA(pbuchholzstr, (long) pbuchholz);
  570.     PointsToA(pextbuchholzstr, pextbuchholz);
  571.     switch (sortmode & TNMODE_TABMASK)
  572.       { case TNMODEF_BUCHHOLZ:
  573.     case TNMODEF_SONNEBORN_BERGER:
  574.       sprintf(line, "%5d %6s %8s %s", Place, ppointsstrtr, pbuchholzstr,
  575.           t->Name);
  576.       break;
  577.     case TNMODEF_EXT_BUCHHOLZ:
  578.       sprintf(line, "%5d %6s %8s %8s  %s", Place, ppointsstrtr,
  579.           pbuchholzstr, pextbuchholzstr, t->Name);
  580.       break;
  581.     default:
  582.       sprintf(line, "%5d %6s %s", Place, ppointsstrtr, t->Name);
  583.       }
  584.  
  585.     if (!lprint(line))
  586.     { TerminateOutput();
  587.       return;
  588.     }
  589.   }
  590.  
  591.   ProcessOutput();
  592.   TerminateOutput();
  593. }
  594.  
  595.  
  596.  
  597.  
  598. /*
  599.     The following function prints the internal ranking list.
  600.  
  601.     Inputs: filename    - destination file; see InitOutput()
  602.         device    - output device; see InitOutput()
  603. */
  604. void OutInternalRankings(char *filename, int device)
  605.  
  606. { struct Player *t;
  607.   int i;
  608.   char head[81], line[81], title[81];
  609.   char pointsstr[10];
  610.   char dwz[6], elo[6];
  611.  
  612.   if (NumRounds == 0  ||  RoundRobinTournament)
  613.   { sprintf(title, (char *) GetChaosString(MSG_RANKINGS_TITLE));
  614.     sprintf(head, "%-4s %-6s %-6s %-30s", GetChaosString(MSG_NUMBER),
  615.         GetChaosString(MSG_DWZ_OUTPUT), GetChaosString(MSG_ELO_OUTPUT),
  616.         GetChaosString(MSG_NAME_OUTPUT));
  617.     CreateRankings();
  618.   }
  619.   else
  620.   { sprintf(title, (char *) GetChaosString(MSG_RANKINGS_TITLE2),
  621.         NumRounds);
  622.     sprintf(head, "%-4s %-6s %-6s %-6s %-30s", GetChaosString(MSG_NUMBER),
  623.         GetChaosString(MSG_DWZ_OUTPUT), GetChaosString(MSG_ELO_OUTPUT),
  624.         GetChaosString(MSG_POINTS_OUTPUT), GetChaosString(MSG_NAME_OUTPUT));
  625.   }
  626.  
  627.   if (!InitOutput(title, head, head, filename, "#?.rnk", device, 1, 1))
  628.   { TerminateOutput();
  629.     return;
  630.   }
  631.  
  632.   for (t = RankingFirst, i = 0;  t != NULL;  t = t->RankNext)
  633.   { RatingToA(dwz, tdwz(t));
  634.     RatingToA(elo, (int) t->ELO);
  635.     if (NumRounds != 0)
  636.     { PointsToA(pointsstr, (long) t->Points);
  637.       sprintf(line, "%-4d %-6s %-6s %-5s  %s", ++i, dwz, elo,
  638.           pointsstr, t->Name);
  639.     }
  640.     else
  641.     { sprintf(line, "%-4d %-6s %-6s %s", ++i, dwz, elo, t->Name);
  642.     }
  643.     if (!lprint(line))
  644.     { TerminateOutput();
  645.       return;
  646.     }
  647.   }
  648.  
  649.   ProcessOutput();
  650.   TerminateOutput();
  651. }
  652.  
  653.  
  654.  
  655.  
  656. /*
  657.     The following function prints the table of progress.
  658.  
  659.     Inputs: filename    - destination file; see InitOutput()
  660.         device    - output device; see InitOutput()
  661.         sortmode    - sorting mode of the table; see MakeTable()
  662. */
  663. void OutTableProgress(char *filename, int device, int sortmode)
  664.  
  665. { struct Player *TabFirst, *t;
  666.   struct Game *g;
  667.   int i, gperline, needprint;
  668.   int lines;
  669.   char head[81], title[81], line[81], pointsstr[10], helps[10];
  670.  
  671.   sprintf(title, (char *) GetChaosString(MSG_PROGRESS_TABLE_TITLE),
  672.       NumRounds);
  673.   sprintf(head, "%-4s %-6s %-33s %s", GetChaosString(MSG_NUMBER),
  674.       GetChaosString(MSG_POINTS_OUTPUT), GetChaosString(MSG_NAME_OUTPUT),
  675.       GetChaosString(MSG_GAME_OUTPUT));
  676.   TabFirst = MakeTable(sortmode);
  677.  
  678.   lines = (NumRounds+3)/8+1;
  679.   if (!InitOutput(title, head, head, filename, "#?.tblp", device, lines,
  680.           lines))
  681.   { TerminateOutput();
  682.     return;
  683.   }
  684.  
  685.   for (t = TabFirst, i = 0;  t != NULL;  t = t->Helpptr)
  686.   { t->Nr = ++i;
  687.   }
  688.  
  689.   for (t = TabFirst;  t != NULL;  t = t->Helpptr)
  690.   { PointsToA(pointsstr, (long) t->Points);
  691.     sprintf(line, "%4d %6s %-34s", t->Nr, pointsstr, t->Name);
  692.     gperline = 3;
  693.     for (i = 1;  i <= NumRounds;  i++)
  694.     { needprint = TRUE;
  695.       g = GameAddress(t, i);
  696.       if (g->Flags & GMFLAGSF_POINTFORFREE)
  697.       { sprintf(helps, (char *) GetChaosString(MSG_FREE_GAME_OUTPUT));
  698.       }
  699.       else if (g->Flags & GMFLAGSF_WITHDRAWN)
  700.       { sprintf(helps, (char *) GetChaosString(MSG_GONE_OUTPUT));
  701.       }
  702.       else
  703.       { static char *ergchars = "?-=+";
  704.     sprintf(helps, "  %4d%c%c%c", g->Opponent->Nr,
  705.         ergchars[g->Result+1],
  706.         (g->Flags&GMFLAGSF_WHITE) ? 'w' : 's',
  707.         (g->Flags&GMFLAGSF_NOFIGHT) ? 'k' : ' ');
  708.       }
  709.       strcat(line, helps);
  710.       if (--gperline == 0)
  711.       { if (!lprint(line))
  712.     { TerminateOutput();
  713.       return;
  714.     }
  715.     gperline = 7;
  716.     sprintf(line, "          ");
  717.     needprint = FALSE;
  718.       }
  719.     }
  720.     if (needprint)
  721.     { if (!lprint(line))
  722.       { TerminateOutput();
  723.     return;
  724.       }
  725.     }
  726.   }
  727.  
  728.   ProcessOutput();
  729.   TerminateOutput();
  730. }
  731.  
  732.  
  733.  
  734.  
  735. /*
  736.     The cross table can be printed on screen, on printer in ascii format
  737.     or in TeX format. Note, that this must not be called in a Swiss Pairing
  738.     tournament! Strange things might happen!
  739.  
  740.     Inputs: filename    - destination file; see InitOutput()
  741.         device    - output device; see InitOutput()
  742. */
  743. void OutCrossTable(char *filename, int device)
  744.  
  745. { struct Player *plr;
  746.   struct Player **plrlist;
  747.   void *PlrMem = NULL;
  748.   struct Game *gm;
  749.   char *title;
  750.   int i,j;
  751.   char line[512];
  752.   char subline[512];
  753.   int allflag;
  754.   int width;
  755.  
  756.   /*
  757.       Create the player table. (We deal with player numbers here and so its
  758.       easier to use the table instead of going through the list of players
  759.       each time.)
  760.   */
  761.   if ((plrlist = GetMem(&PlrMem, sizeof(struct Player *)*NumPlayers))
  762.            ==  NULL)
  763.   { return;
  764.   }
  765.   for (plr = (struct Player *) PlayerList.lh_Head;
  766.        plr->Tn_Node.ln_Succ != NULL;
  767.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  768.   { plrlist[plr->Nr-1] = plr;
  769.   }
  770.  
  771.  
  772.  
  773.   if (device == DEVICE_FileTeX)
  774.   { title = "";
  775.   }
  776.   else
  777.   { title = (char *) GetChaosString(MSG_OUTPUT_CROSSTABLE_ITEM);
  778.   }
  779.   if (!InitOutput(title, "", "", filename, "#?.crss", device, 0, 0))
  780.   { goto Terminate;
  781.   }
  782.  
  783.  
  784.   /*
  785.       Some guys (me!) like beautiful TeX printings...
  786.   */
  787.   if (device == DEVICE_FileTeX)
  788.   { sprintf(line, "\\documentstyle[german,a4,%s]{article}\n"
  789.           "\\newcommand{\\r}{$\\frac{1}{2}$}\n"
  790.           "\\renewcommand{\\arraystretch}{2.0}\n"
  791.           "\\parindent0em\n\n"
  792.           "\\begin{document}\n"
  793.           "  \\begin{tabular}{l|*{%d}{p{0.6cm}|}r}",
  794.           (NumPlayers < 25) ? "12pt" : "",
  795.           NumPlayers);
  796.     if (!longlprint(line))
  797.     { goto Terminate;
  798.     }
  799.  
  800.     strcpy(line, "    ");
  801.     for (i = 0;  i < NumPlayers;  i++)
  802.       { sprintf(line + strlen(line), "& %d ", i+1);
  803.       }
  804.     strcat(line, "& \\\\\\hline");
  805.     if (!lprint(line))
  806.     { goto Terminate;
  807.     }
  808.  
  809.  
  810.     for (i = 1;  i <= NumPlayers;  i++)
  811.     { plr = plrlist[i-1];
  812.       sprintf(line, "    %s", plr->Name);
  813.       allflag = TRUE;
  814.       for (j = 1;  j <= NumPlayers;  j++)
  815.       { if (j == i)
  816.     { strcat(line, "& x ");
  817.     }
  818.     else
  819.     { gm = plr->First_Game;
  820.       while(gm->Opponent == NULL  ||  gm->Opponent->Nr != j)
  821.       { gm = gm->Next;
  822.       }
  823.       switch (gm->Result)
  824.       { case 2:
  825.           strcat(line, "& 1 ");
  826.           break;
  827.         case 1:
  828.           strcat(line, "& \\r");
  829.           break;
  830.         case 0:
  831.           strcat(line, "& 0 ");
  832.           break;
  833.         default:
  834.           strcat(line, "&   ");
  835.           allflag = FALSE;
  836.       }
  837.     }
  838.       }
  839.       strcat(line, "& ");
  840.       if (allflag)
  841.       { PointsToA(line+strlen(line), (long) plr->Points);
  842.       }
  843.       if (i < NumPlayers)
  844.       { strcat(line, "\\\\\\hline");
  845.       }
  846.       if (!lprint(line))
  847.       { goto Terminate;
  848.       }
  849.     }
  850.  
  851.     if (!longlprint("  \\end{tabular}\n"
  852.             "\\end{document}"))
  853.     { goto Terminate;
  854.     }
  855.   }
  856.  
  857.   /*
  858.       other guys don't have or don't like TeX (really? :-( ) For those
  859.       poor creatures the Ascii output:
  860.   */
  861.   else
  862.   { CenterText(device);
  863.  
  864.     if (NumPlayers < 10)
  865.     { width = 40 + NumPlayers*4;
  866.     }
  867.     else
  868.     { width = 40 + NumPlayers*2;
  869.     }
  870.     for (i = 0;  i < width;  i++)
  871.     { subline[i] = '-';
  872.     }
  873.     subline[width] = '\0';
  874.  
  875.     if (NumPlayers > 99)
  876.     { sprintf(line, "%36s|", "");
  877.       for (i = 1;  i <= NumPlayers;  i++)
  878.       { plr = plrlist[i-1];
  879.     if (i > 99)
  880.     { sprintf(line + strlen(line), "%c|", i/100+'0');
  881.     }
  882.     else
  883.     {strcat(line, " |");
  884.     }
  885.       }
  886.       if (!lprint(line))
  887.       { goto Terminate;
  888.       }
  889.     }
  890.  
  891.  
  892.     if (NumPlayers > 9)
  893.     { sprintf(line, "%36s|", "");
  894.       for (i = 1;  i <= NumPlayers;  i++)
  895.       { plr = plrlist[i-1];
  896.     if (i > 9)
  897.     { sprintf(line + strlen(line), "%c|", (i%100)/10+'0');
  898.     }
  899.     else
  900.     { strcat(line, " |");
  901.     }
  902.       }
  903.       if (!lprint(line))
  904.       { goto Terminate;
  905.       }
  906.     }
  907.  
  908.  
  909.     sprintf(line, "%36s|", "");
  910.     for (i = 1;  i <= NumPlayers;  i++)
  911.     { plr = plrlist[i-1];
  912.       sprintf(line + strlen(line), (NumPlayers > 9) ? "%c|" : " %c |",
  913.           i%10+'0');
  914.     }
  915.     if (!lprint(line))
  916.     { goto Terminate;
  917.     }
  918.  
  919.  
  920.     for (i = 1;  i <= NumPlayers;  i++)
  921.     { plr = plrlist[i-1];
  922.  
  923.       sprintf(line, "|%3d %30s |", i, plr->Name);
  924.       allflag = TRUE;
  925.  
  926.       for (j = 1;  j <= NumPlayers;  j++)
  927.       { if (j == i)
  928.     { strcat(line, (NumPlayers > 9) ? "x|" : " x |");
  929.     }
  930.     else
  931.     { static const char *ergs = {" 0=1" };
  932.  
  933.       gm = plr->First_Game;
  934.       while(gm->Opponent == NULL  ||  gm->Opponent->Nr != j)
  935.       { gm = gm->Next;
  936.       }
  937.  
  938.       sprintf(line+strlen(line), (NumPlayers > 9) ? "%c|" : " %c |",
  939.           ergs[gm->Result+1]);
  940.       if (gm->Result == -1)
  941.       { allflag = FALSE;
  942.       }
  943.     }
  944.       }
  945.       if (allflag)
  946.       { PointsToA(line + strlen(line), (long) plr->Points);
  947.       }
  948.       if (!lprint(subline)  ||  !lprint(line))
  949.       { goto Terminate;
  950.       }
  951.     }
  952.   }
  953.  
  954.   ProcessOutput();
  955.  
  956. Terminate:
  957.   TerminateOutput();
  958.   PutMemList(&PlrMem);
  959. }
  960.  
  961.  
  962.  
  963.  
  964. /*
  965.     The following function prints the player cards.
  966.  
  967.     Inputs: filename - destination file; see InitOutput()
  968.         device   - output device; see InitOutput()
  969. */
  970. void OutPlayerCards(char *filename, int device)
  971.  
  972. { struct Player *plr, **plrlist;
  973.   void *PlrMem = NULL;
  974.   struct Game *gm;
  975.   int i, j;
  976.   int defrounds, numrounds;
  977.   int lines;
  978.   char line[512];
  979.   char subline[512];
  980.   char *title;
  981.  
  982.   /*
  983.       Create the player table. (We deal with player numbers here and so its
  984.       easier to use the table instead of going through the list of players
  985.       each time.)
  986.   */
  987.   if ((plrlist = GetMem(&PlrMem, sizeof(struct Player *)*NumPlayers))
  988.            ==  NULL)
  989.   { return;
  990.   }
  991.   for (i = 0, plr = (struct Player *) PlayerList.lh_Head;
  992.        plr->Tn_Node.ln_Succ != NULL;
  993.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  994.   { plrlist[i++] = plr;
  995.     plr->Nr = i;
  996.   }
  997.  
  998.  
  999.   /*
  1000.       Determine, how much rounds to print
  1001.   */
  1002.   defrounds = (device == DEVICE_FileTeX) ? 11 : 9;
  1003.   if (NumRounds < defrounds-1)
  1004.   { numrounds = defrounds;
  1005.   }
  1006.   else
  1007.   { numrounds = NumRounds+2;
  1008.   }
  1009.   if ((numrounds % 2) == 0)
  1010.   { numrounds++;
  1011.   }
  1012.  
  1013.   if (device == DEVICE_FileTeX)
  1014.   { title = "";
  1015.     lines = 0;
  1016.   }
  1017.   else
  1018.   { title = (char *) GetChaosString(MSG_OUTPUT_PLAYERCARDS_ITEM);
  1019.     lines = 11;
  1020.   }
  1021.   if (!InitOutput(title, "", "", filename, "#?.pcrd", device, lines, lines))
  1022.   { goto Terminate;
  1023.   }
  1024.  
  1025.   /*
  1026.       Some guys (me!) like beautiful TeX printings...
  1027.   */
  1028.   if (device == DEVICE_FileTeX)
  1029.   { sprintf(line, "\\documentstyle[german,a4,12pt]{article}\n"
  1030.           "\\renewcommand{\\arraystretch}{2.0}\n"
  1031.           "\\parindent0em\n\n"
  1032.           "\\begin{document}");
  1033.     if (!longlprint(line))
  1034.     { goto Terminate;
  1035.     }
  1036.  
  1037.     for (plr = (struct Player *) PlayerList.lh_Head;
  1038.      plr->Tn_Node.ln_Succ != NULL;
  1039.      plr = (struct Player *) plr->Tn_Node.ln_Succ)
  1040.     { sprintf(line, "\\begin{tabular}{|l*{%d}{|p{0.6cm}}|}\\hline\n"
  1041.             "%s %d&\\multicolumn{%d}{|l|}{%s}\\\\\\hline",
  1042.           numrounds, GetChaosString(MSG_NUMBER),
  1043.           plr->Nr, numrounds, plr->Name);
  1044.       if (!longlprint(line))
  1045.       { goto Terminate;
  1046.       }
  1047.  
  1048.       strcpy(line, (char *) GetChaosString(MSG_WHITE_OUTPUT));
  1049.       for (j = 0, gm = plr->First_Game;  j < numrounds;  j++)
  1050.       { if (gm != NULL)
  1051.     { if (gm->Flags & GMFLAGSF_WHITE)
  1052.       { sprintf(line + strlen(line), "&%d", gm->Opponent->Nr);
  1053.       }
  1054.       else
  1055.       { sprintf(line + strlen(line),
  1056.             (gm->Flags & GMFLAGSF_POINTFORFREE) ? "&%s" : "&",
  1057.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1058.       }
  1059.       gm = gm->Next;
  1060.     }
  1061.     else
  1062.     { strcat(line, "&");
  1063.     }
  1064.       }
  1065.       strcat(line, "\\\\\\hline");
  1066.       if (!lprint(line))
  1067.       { goto Terminate;
  1068.       }
  1069.  
  1070.       strcpy(line, (char *) GetChaosString(MSG_BLACK_OUTPUT));
  1071.       for (j = 0, gm = plr->First_Game;  j < numrounds;  j++)
  1072.       { if (gm != NULL)
  1073.     { if ((gm->Flags & (GMFLAGSF_WHITE|GMFLAGSF_POINTFORFREE))  ==  0)
  1074.       { sprintf(line + strlen(line), "&%d", gm->Opponent->Nr);
  1075.       }
  1076.       else
  1077.       { sprintf(line + strlen(line),
  1078.             (gm->Flags & GMFLAGSF_POINTFORFREE) ? "&%s" : "&",
  1079.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1080.       }
  1081.       gm = gm->Next;
  1082.     }
  1083.     else
  1084.     { strcat(line, "&");
  1085.     }
  1086.       }
  1087.       strcat(line, "\\\\\\hline");
  1088.       if (!lprint(line))
  1089.       { goto Terminate;
  1090.       }
  1091.  
  1092.       strcpy(line, (char *) GetChaosString(MSG_POINTS_OUTPUT));
  1093.       for (j = 0, i = 0, gm = plr->First_Game;  j < numrounds;  j++)
  1094.       { strcat(line, "&");
  1095.     if (gm != NULL)
  1096.     { i += gm->Result;
  1097.       gm = gm->Next;
  1098.       PointsToA(line + strlen(line), (long) i);
  1099.     }
  1100.       }
  1101.       strcat(line, "\\\\\\hline\n"
  1102.            "\\end{tabular}\n\n\\vspace{0.5cm}\n");
  1103.       if (!longlprint(line))
  1104.       { goto Terminate;
  1105.       }
  1106.     }
  1107.     if (!lprint("\\end{document}"))
  1108.     { goto Terminate;
  1109.     }
  1110.   }
  1111.  
  1112.   /*
  1113.       other guys don't have or don't like TeX (really? :-( ) For those
  1114.       poor creatures the Ascii output:
  1115.   */
  1116.   else
  1117.   { char *plrformatstr, *emptyformatstr, *onepbyeformatstr, *pointsformatstr;
  1118.     char ppointsstr[10];
  1119.     int width, plrwidth;
  1120.  
  1121.     CenterText(device);
  1122.  
  1123.     if (numrounds > 11)
  1124.     { plrformatstr = "%3d |";
  1125.       emptyformatstr = "    |";
  1126.       onepbyeformatstr = "  %s |";
  1127.       pointsformatstr = "%4s";
  1128.       plrwidth = 4;
  1129.     }
  1130.     else
  1131.     { plrformatstr = " %3d |";
  1132.       emptyformatstr = "     |";
  1133.       onepbyeformatstr = "  %s  |";
  1134.       pointsformatstr = "%4s |";
  1135.       plrwidth = 6;
  1136.     }
  1137.     width = 14 + (numrounds+1) * plrwidth;
  1138.     for (i = 0;  i < width;  i++)
  1139.     { subline[i] = '-';
  1140.     }
  1141.     subline[width] = '\0';
  1142.  
  1143.  
  1144.     for (plr = (struct Player *) PlayerList.lh_Head;
  1145.      plr->Tn_Node.ln_Succ != NULL;
  1146.      plr = (struct Player *) plr->Tn_Node.ln_Succ)
  1147.     { if (!lprint(subline))
  1148.       { goto Terminate;
  1149.       }
  1150.  
  1151.       sprintf(line, "| %4s  %4d | %30s",
  1152.           GetChaosString(MSG_NUMBER), plr->Nr, plr->Name);
  1153.       for (i = strlen(line);  i < width-1;  i++)
  1154.       { line[i] = ' ';
  1155.       }
  1156.       line[width-1] = '|';
  1157.       line[width] = '\0';
  1158.       if (!lprint(line))
  1159.       { goto Terminate;
  1160.       }
  1161.  
  1162.       if (!lprint(subline))
  1163.       { goto Terminate;
  1164.       }
  1165.  
  1166.       sprintf(line, "| %10s |", (char *) GetChaosString(MSG_WHITE_OUTPUT));
  1167.       for (j = 0, gm = plr->First_Game;  j < numrounds+1;  j++)
  1168.       { if (gm != NULL)
  1169.     { if (gm->Flags & GMFLAGSF_WHITE)
  1170.       { sprintf(line + strlen(line), plrformatstr, gm->Opponent->Nr);
  1171.       }
  1172.       else
  1173.       { sprintf(line + strlen(line),
  1174.             (gm->Flags & GMFLAGSF_POINTFORFREE) ?
  1175.                 onepbyeformatstr : emptyformatstr,
  1176.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1177.       }
  1178.       gm = gm->Next;
  1179.     }
  1180.     else
  1181.     { strcat(line, emptyformatstr);
  1182.     }
  1183.       }
  1184.       if (!lprint(line)  ||  !lprint(subline))
  1185.       { goto Terminate;
  1186.       }
  1187.  
  1188.       sprintf(line, "| %10s |", (char *) GetChaosString(MSG_BLACK_OUTPUT));
  1189.       for (j = 0, gm = plr->First_Game;  j < numrounds+1;  j++)
  1190.       { if (gm != NULL)
  1191.     { if ((gm->Flags & (GMFLAGSF_WHITE|GMFLAGSF_POINTFORFREE))  ==  0)
  1192.       { sprintf(line + strlen(line), plrformatstr, gm->Opponent->Nr);
  1193.       }
  1194.       else
  1195.       { sprintf(line + strlen(line),
  1196.             (gm->Flags & GMFLAGSF_POINTFORFREE) ?
  1197.                 onepbyeformatstr : emptyformatstr,
  1198.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1199.       }
  1200.       gm = gm->Next;
  1201.     }
  1202.     else
  1203.     { strcat(line, emptyformatstr);
  1204.     }
  1205.       }
  1206.       if (!lprint(line)  ||  !lprint(subline))
  1207.       { goto Terminate;
  1208.       }
  1209.  
  1210.       sprintf(line, "| %10s |", (char *) GetChaosString(MSG_POINTS_OUTPUT));
  1211.       for (j = 0, i = 0, gm = plr->First_Game;  j < numrounds+1;  j++)
  1212.       { if (gm != NULL)
  1213.     { i += gm->Result;
  1214.       gm = gm->Next;
  1215.       PointsToA(ppointsstr, (long) i);
  1216.       sprintf(line + strlen(line), pointsformatstr, ppointsstr);
  1217.     }
  1218.     else
  1219.     { strcat(line, emptyformatstr);
  1220.     }
  1221.       }
  1222.       if (!lprint(line) ||  !lprint(subline)  ||  !lprint("\n"))
  1223.       { goto Terminate;
  1224.       }
  1225.     }
  1226.   }
  1227.  
  1228.   ProcessOutput();
  1229.  
  1230. Terminate:
  1231.   TerminateOutput();
  1232.   PutMemList(&PlrMem);
  1233. }
  1234.