Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // Emacs style mode select   -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:  Heads-up displays
  20. //
  21. //-----------------------------------------------------------------------------
  22.  
  23. static const char
  24. rcsid[] = "$Id: hu_stuff.c,v 1.4 1997/02/03 16:47:52 b1 Exp $";
  25.  
  26. #include <ctype.h>
  27.  
  28. #include "doomdef.h"
  29.  
  30. #include "z_zone.h"
  31.  
  32. #include "m_swap.h"
  33.  
  34. #include "hu_stuff.h"
  35. #include "hu_lib.h"
  36. #include "w_wad.h"
  37.  
  38. #include "s_sound.h"
  39.  
  40. #include "doomstat.h"
  41.  
  42. // Data.
  43. #include "dstrings.h"
  44. #include "sounds.h"
  45.  
  46. //
  47. // Locally used constants, shortcuts.
  48. //
  49. #define HU_TITLE        (mapnames[(gameepisode-1)*9+gamemap-1])
  50. #define HU_TITLE2       (mapnames2[gamemap-1])
  51. #define HU_TITLEP       (mapnamesp[gamemap-1])
  52. #define HU_TITLET       (mapnamest[gamemap-1])
  53. #define HU_TITLEHEIGHT  1
  54. #define HU_TITLEX       0
  55. #define HU_TITLEY       (167 - SHORT(hu_font[0]->height))
  56.  
  57. #define HU_INPUTTOGGLE  't'
  58. #define HU_INPUTX       HU_MSGX
  59. #define HU_INPUTY       (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1))
  60. #define HU_INPUTWIDTH   64
  61. #define HU_INPUTHEIGHT  1
  62.  
  63.  
  64.  
  65. char*   chat_macros[] =
  66. {
  67.     HUSTR_CHATMACRO0,
  68.     HUSTR_CHATMACRO1,
  69.     HUSTR_CHATMACRO2,
  70.     HUSTR_CHATMACRO3,
  71.     HUSTR_CHATMACRO4,
  72.     HUSTR_CHATMACRO5,
  73.     HUSTR_CHATMACRO6,
  74.     HUSTR_CHATMACRO7,
  75.     HUSTR_CHATMACRO8,
  76.     HUSTR_CHATMACRO9
  77. };
  78.  
  79. char*   player_names[] =
  80. {
  81.     HUSTR_PLRGREEN,
  82.     HUSTR_PLRINDIGO,
  83.     HUSTR_PLRBROWN,
  84.     HUSTR_PLRRED
  85. };
  86.  
  87.  
  88. char                    chat_char; // remove later.
  89. static player_t*        plr;
  90. patch_t*                hu_font[HU_FONTSIZE];
  91. static hu_textline_t    w_title;
  92. boolean                 chat_on;
  93. static hu_itext_t       w_chat;
  94. static boolean          always_off = false;
  95. static char             chat_dest[MAXPLAYERS];
  96. static hu_itext_t w_inputbuffer[MAXPLAYERS];
  97.  
  98. static boolean          message_on;
  99. boolean                 message_dontfuckwithme;
  100. static boolean          message_nottobefuckedwith;
  101.  
  102. static hu_stext_t       w_message;
  103. static int              message_counter;
  104.  
  105. extern int              showMessages;
  106. extern boolean          automapactive;
  107.  
  108. static boolean          headsupactive = false;
  109.  
  110. //
  111. // Builtin map names.
  112. // The actual names can be found in DStrings.h.
  113. //
  114.  
  115. char*   mapnames[] =    // DOOM shareware/registered/retail (Ultimate) names.
  116. {
  117.  
  118.     HUSTR_E1M1,
  119.     HUSTR_E1M2,
  120.     HUSTR_E1M3,
  121.     HUSTR_E1M4,
  122.     HUSTR_E1M5,
  123.     HUSTR_E1M6,
  124.     HUSTR_E1M7,
  125.     HUSTR_E1M8,
  126.     HUSTR_E1M9,
  127.  
  128.     HUSTR_E2M1,
  129.     HUSTR_E2M2,
  130.     HUSTR_E2M3,
  131.     HUSTR_E2M4,
  132.     HUSTR_E2M5,
  133.     HUSTR_E2M6,
  134.     HUSTR_E2M7,
  135.     HUSTR_E2M8,
  136.     HUSTR_E2M9,
  137.  
  138.     HUSTR_E3M1,
  139.     HUSTR_E3M2,
  140.     HUSTR_E3M3,
  141.     HUSTR_E3M4,
  142.     HUSTR_E3M5,
  143.     HUSTR_E3M6,
  144.     HUSTR_E3M7,
  145.     HUSTR_E3M8,
  146.     HUSTR_E3M9,
  147.  
  148.     HUSTR_E4M1,
  149.     HUSTR_E4M2,
  150.     HUSTR_E4M3,
  151.     HUSTR_E4M4,
  152.     HUSTR_E4M5,
  153.     HUSTR_E4M6,
  154.     HUSTR_E4M7,
  155.     HUSTR_E4M8,
  156.     HUSTR_E4M9,
  157.  
  158.     "NEWLEVEL",
  159.     "NEWLEVEL",
  160.     "NEWLEVEL",
  161.     "NEWLEVEL",
  162.     "NEWLEVEL",
  163.     "NEWLEVEL",
  164.     "NEWLEVEL",
  165.     "NEWLEVEL",
  166.     "NEWLEVEL"
  167. };
  168.  
  169. char*   mapnames2[] =   // DOOM 2 map names.
  170. {
  171.     HUSTR_1,
  172.     HUSTR_2,
  173.     HUSTR_3,
  174.     HUSTR_4,
  175.     HUSTR_5,
  176.     HUSTR_6,
  177.     HUSTR_7,
  178.     HUSTR_8,
  179.     HUSTR_9,
  180.     HUSTR_10,
  181.     HUSTR_11,
  182.        
  183.     HUSTR_12,
  184.     HUSTR_13,
  185.     HUSTR_14,
  186.     HUSTR_15,
  187.     HUSTR_16,
  188.     HUSTR_17,
  189.     HUSTR_18,
  190.     HUSTR_19,
  191.     HUSTR_20,
  192.        
  193.     HUSTR_21,
  194.     HUSTR_22,
  195.     HUSTR_23,
  196.     HUSTR_24,
  197.     HUSTR_25,
  198.     HUSTR_26,
  199.     HUSTR_27,
  200.     HUSTR_28,
  201.     HUSTR_29,
  202.     HUSTR_30,
  203.     HUSTR_31,
  204.     HUSTR_32
  205. };
  206.  
  207.  
  208. char*   mapnamesp[] =   // Plutonia WAD map names.
  209. {
  210.     PHUSTR_1,
  211.     PHUSTR_2,
  212.     PHUSTR_3,
  213.     PHUSTR_4,
  214.     PHUSTR_5,
  215.     PHUSTR_6,
  216.     PHUSTR_7,
  217.     PHUSTR_8,
  218.     PHUSTR_9,
  219.     PHUSTR_10,
  220.     PHUSTR_11,
  221.        
  222.     PHUSTR_12,
  223.     PHUSTR_13,
  224.     PHUSTR_14,
  225.     PHUSTR_15,
  226.     PHUSTR_16,
  227.     PHUSTR_17,
  228.     PHUSTR_18,
  229.     PHUSTR_19,
  230.     PHUSTR_20,
  231.        
  232.     PHUSTR_21,
  233.     PHUSTR_22,
  234.     PHUSTR_23,
  235.     PHUSTR_24,
  236.     PHUSTR_25,
  237.     PHUSTR_26,
  238.     PHUSTR_27,
  239.     PHUSTR_28,
  240.     PHUSTR_29,
  241.     PHUSTR_30,
  242.     PHUSTR_31,
  243.     PHUSTR_32
  244. };
  245.  
  246.  
  247. char *mapnamest[] =     // TNT WAD map names.
  248. {
  249.     THUSTR_1,
  250.     THUSTR_2,
  251.     THUSTR_3,
  252.     THUSTR_4,
  253.     THUSTR_5,
  254.     THUSTR_6,
  255.     THUSTR_7,
  256.     THUSTR_8,
  257.     THUSTR_9,
  258.     THUSTR_10,
  259.     THUSTR_11,
  260.        
  261.     THUSTR_12,
  262.     THUSTR_13,
  263.     THUSTR_14,
  264.     THUSTR_15,
  265.     THUSTR_16,
  266.     THUSTR_17,
  267.     THUSTR_18,
  268.     THUSTR_19,
  269.     THUSTR_20,
  270.        
  271.     THUSTR_21,
  272.     THUSTR_22,
  273.     THUSTR_23,
  274.     THUSTR_24,
  275.     THUSTR_25,
  276.     THUSTR_26,
  277.     THUSTR_27,
  278.     THUSTR_28,
  279.     THUSTR_29,
  280.     THUSTR_30,
  281.     THUSTR_31,
  282.     THUSTR_32
  283. };
  284.  
  285.  
  286. const char*     shiftxform;
  287.  
  288. const char french_shiftxform[] =
  289. {
  290.     0,
  291.     1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  292.     11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  293.     21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
  294.     31,
  295.     ' ', '!', '"', '#', '$', '%', '&',
  296.     '"', // shift-'
  297.     '(', ')', '*', '+',
  298.     '?', // shift-,
  299.     '_', // shift--
  300.     '>', // shift-.
  301.     '?', // shift-/
  302.     '0', // shift-0
  303.     '1', // shift-1
  304.     '2', // shift-2
  305.     '3', // shift-3
  306.     '4', // shift-4
  307.     '5', // shift-5
  308.     '6', // shift-6
  309.     '7', // shift-7
  310.     '8', // shift-8
  311.     '9', // shift-9
  312.     '/',
  313.     '.', // shift-;
  314.     '<',
  315.     '+', // shift-=
  316.     '>', '?', '@',
  317.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  318.     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  319.     '[', // shift-[
  320.     '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
  321.     ']', // shift-]
  322.     '"', '_',
  323.     '\'', // shift-`
  324.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  325.     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  326.     '{', '|', '}', '~', 127
  327.  
  328. };
  329.  
  330. const char english_shiftxform[] =
  331. {
  332.  
  333.     0,
  334.     1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  335.     11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  336.     21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
  337.     31,
  338.     ' ', '!', '"', '#', '$', '%', '&',
  339.     '"', // shift-'
  340.     '(', ')', '*', '+',
  341.     '<', // shift-,
  342.     '_', // shift--
  343.     '>', // shift-.
  344.     '?', // shift-/
  345.     ')', // shift-0
  346.     '!', // shift-1
  347.     '@', // shift-2
  348.     '#', // shift-3
  349.     '$', // shift-4
  350.     '%', // shift-5
  351.     '^', // shift-6
  352.     '&', // shift-7
  353.     '*', // shift-8
  354.     '(', // shift-9
  355.     ':',
  356.     ':', // shift-;
  357.     '<',
  358.     '+', // shift-=
  359.     '>', '?', '@',
  360.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  361.     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  362.     '[', // shift-[
  363.     '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
  364.     ']', // shift-]
  365.     '"', '_',
  366.     '\'', // shift-`
  367.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  368.     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  369.     '{', '|', '}', '~', 127
  370. };
  371.  
  372. char frenchKeyMap[128]=
  373. {
  374.     0,
  375.     1,2,3,4,5,6,7,8,9,10,
  376.     11,12,13,14,15,16,17,18,19,20,
  377.     21,22,23,24,25,26,27,28,29,30,
  378.     31,
  379.     ' ','!','"','#','$','%','&','%','(',')','*','+',';','-',':','!',
  380.     '0','1','2','3','4','5','6','7','8','9',':','M','<','=','>','?',
  381.     '@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O',
  382.     'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^','_',
  383.     '@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O',
  384.     'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^',127
  385. };
  386.  
  387. char ForeignTranslation(unsigned char ch)
  388. {
  389.     return ch < 128 ? frenchKeyMap[ch] : ch;
  390. }
  391.  
  392. void HU_Init(void)
  393. {
  394.  
  395.     int         i;
  396.     int         j;
  397.     char        buffer[9];
  398.  
  399.     if (french)
  400.         shiftxform = french_shiftxform;
  401.     else
  402.         shiftxform = english_shiftxform;
  403.  
  404.     // load the heads-up font
  405.     j = HU_FONTSTART;
  406.     for (i=0;i<HU_FONTSIZE;i++)
  407.     {
  408.         sprintf(buffer, "STCFN%.3d", j++);
  409.         hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
  410.     }
  411.  
  412. }
  413.  
  414. void HU_Stop(void)
  415. {
  416.     headsupactive = false;
  417. }
  418.  
  419. void HU_Start(void)
  420. {
  421.  
  422.     int         i;
  423.     char*       s;
  424.  
  425.     if (headsupactive)
  426.         HU_Stop();
  427.  
  428.     plr = &players[consoleplayer];
  429.     message_on = false;
  430.     message_dontfuckwithme = false;
  431.     message_nottobefuckedwith = false;
  432.     chat_on = false;
  433.  
  434.     // create the message widget
  435.     HUlib_initSText(&w_message,
  436.                     HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
  437.                     hu_font,
  438.                     HU_FONTSTART, &message_on);
  439.  
  440.     // create the map title widget
  441.     HUlib_initTextLine(&w_title,
  442.                        HU_TITLEX, HU_TITLEY,
  443.                        hu_font,
  444.                        HU_FONTSTART);
  445.    
  446.     switch ( gamemode )
  447.     {
  448.       case shareware:
  449.       case registered:
  450.       case retail:
  451.         s = HU_TITLE;
  452.         break;
  453.  
  454. /* FIXME
  455.       case pack_plut:
  456.         s = HU_TITLEP;
  457.         break;
  458.       case pack_tnt:
  459.         s = HU_TITLET;
  460.         break;
  461. */
  462.        
  463.       case commercial:
  464.       default:
  465.          s = HU_TITLE2;
  466.          break;
  467.     }
  468.    
  469.     while (*s)
  470.         HUlib_addCharToTextLine(&w_title, *(s++));
  471.  
  472.     // create the chat widget
  473.     HUlib_initIText(&w_chat,
  474.                     HU_INPUTX, HU_INPUTY,
  475.                     hu_font,
  476.                     HU_FONTSTART, &chat_on);
  477.  
  478.     // create the inputbuffer widgets
  479.     for (i=0 ; i<MAXPLAYERS ; i++)
  480.         HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
  481.  
  482.     headsupactive = true;
  483.  
  484. }
  485.  
  486. void HU_Drawer(void)
  487. {
  488.  
  489.     HUlib_drawSText(&w_message);
  490.     HUlib_drawIText(&w_chat);
  491.     if (automapactive)
  492.         HUlib_drawTextLine(&w_title, false);
  493.  
  494. }
  495.  
  496. void HU_Erase(void)
  497. {
  498.  
  499.     HUlib_eraseSText(&w_message);
  500.     HUlib_eraseIText(&w_chat);
  501.     HUlib_eraseTextLine(&w_title);
  502.  
  503. }
  504.  
  505. void HU_Ticker(void)
  506. {
  507.  
  508.     int i, rc;
  509.     char c;
  510.  
  511.     // tick down message counter if message is up
  512.     if (message_counter && !--message_counter)
  513.     {
  514.         message_on = false;
  515.         message_nottobefuckedwith = false;
  516.     }
  517.  
  518.     if (showMessages || message_dontfuckwithme)
  519.     {
  520.  
  521.         // display message if necessary
  522.         if ((plr->message && !message_nottobefuckedwith)
  523.             || (plr->message && message_dontfuckwithme))
  524.         {
  525.             HUlib_addMessageToSText(&w_message, 0, plr->message);
  526.             plr->message = 0;
  527.             message_on = true;
  528.             message_counter = HU_MSGTIMEOUT;
  529.             message_nottobefuckedwith = message_dontfuckwithme;
  530.             message_dontfuckwithme = 0;
  531.         }
  532.  
  533.     } // else message_on = false;
  534.  
  535.     // check for incoming chat characters
  536.     if (netgame)
  537.     {
  538.         for (i=0 ; i<MAXPLAYERS; i++)
  539.         {
  540.             if (!playeringame[i])
  541.                 continue;
  542.             if (i != consoleplayer
  543.                 && (c = players[i].cmd.chatchar))
  544.             {
  545.                 if (c <= HU_BROADCAST)
  546.                     chat_dest[i] = c;
  547.                 else
  548.                 {
  549.                     if (c >= 'a' && c <= 'z')
  550.                         c = (char) shiftxform[(unsigned char) c];
  551.                     rc = HUlib_keyInIText(&w_inputbuffer[i], c);
  552.                     if (rc && c == KEY_ENTER)
  553.                     {
  554.                         if (w_inputbuffer[i].l.len
  555.                             && (chat_dest[i] == consoleplayer+1
  556.                                 || chat_dest[i] == HU_BROADCAST))
  557.                         {
  558.                             HUlib_addMessageToSText(&w_message,
  559.                                                     player_names[i],
  560.                                                     w_inputbuffer[i].l.l);
  561.                            
  562.                             message_nottobefuckedwith = true;
  563.                             message_on = true;
  564.                             message_counter = HU_MSGTIMEOUT;
  565.                             if ( gamemode == commercial )
  566.                               S_StartSound(0, sfx_radio);
  567.                             else
  568.                               S_StartSound(0, sfx_tink);
  569.                         }
  570.                         HUlib_resetIText(&w_inputbuffer[i]);
  571.                     }
  572.                 }
  573.                 players[i].cmd.chatchar = 0;
  574.             }
  575.         }
  576.     }
  577.  
  578. }
  579.  
  580. #define QUEUESIZE               128
  581.  
  582. static char     chatchars[QUEUESIZE];
  583. static int      head = 0;
  584. static int      tail = 0;
  585.  
  586.  
  587. void HU_queueChatChar(char c)
  588. {
  589.     if (((head + 1) & (QUEUESIZE-1)) == tail)
  590.     {
  591.         plr->message = HUSTR_MSGU;
  592.     }
  593.     else
  594.     {
  595.         chatchars[head] = c;
  596.         head = (head + 1) & (QUEUESIZE-1);
  597.     }
  598. }
  599.  
  600. char HU_dequeueChatChar(void)
  601. {
  602.     char c;
  603.  
  604.     if (head != tail)
  605.     {
  606.         c = chatchars[tail];
  607.         tail = (tail + 1) & (QUEUESIZE-1);
  608.     }
  609.     else
  610.     {
  611.         c = 0;
  612.     }
  613.  
  614.     return c;
  615. }
  616.  
  617. boolean HU_Responder(event_t *ev)
  618. {
  619.  
  620.     static char         lastmessage[HU_MAXLINELENGTH+1];
  621.     char*               macromessage;
  622.     boolean             eatkey = false;
  623.     static boolean      shiftdown = false;
  624.     static boolean      altdown = false;
  625.     unsigned char       c;
  626.     int                 i;
  627.     int                 numplayers;
  628.    
  629.     static char         destination_keys[MAXPLAYERS] =
  630.     {
  631.         HUSTR_KEYGREEN,
  632.         HUSTR_KEYINDIGO,
  633.         HUSTR_KEYBROWN,
  634.         HUSTR_KEYRED
  635.     };
  636.    
  637.     static int          num_nobrainers = 0;
  638.  
  639.     numplayers = 0;
  640.     for (i=0 ; i<MAXPLAYERS ; i++)
  641.         numplayers += playeringame[i];
  642.  
  643.     if (ev->data1 == KEY_RSHIFT)
  644.     {
  645.         shiftdown = ev->type == ev_keydown;
  646.         return false;
  647.     }
  648.     else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT)
  649.     {
  650.         altdown = ev->type == ev_keydown;
  651.         return false;
  652.     }
  653.  
  654.     if (ev->type != ev_keydown)
  655.         return false;
  656.  
  657.     if (!chat_on)
  658.     {
  659.         if (ev->data1 == HU_MSGREFRESH)
  660.         {
  661.             message_on = true;
  662.             message_counter = HU_MSGTIMEOUT;
  663.             eatkey = true;
  664.         }
  665.         else if (netgame && ev->data1 == HU_INPUTTOGGLE)
  666.         {
  667.             eatkey = chat_on = true;
  668.             HUlib_resetIText(&w_chat);
  669.             HU_queueChatChar(HU_BROADCAST);
  670.         }
  671.         else if (netgame && numplayers > 2)
  672.         {
  673.             for (i=0; i<MAXPLAYERS ; i++)
  674.             {
  675.                 if (ev->data1 == destination_keys[i])
  676.                 {
  677.                     if (playeringame[i] && i!=consoleplayer)
  678.                     {
  679.                         eatkey = chat_on = true;
  680.                         HUlib_resetIText(&w_chat);
  681.                         HU_queueChatChar(i+1);
  682.                         break;
  683.                     }
  684.                     else if (i == consoleplayer)
  685.                     {
  686.                         num_nobrainers++;
  687.                         if (num_nobrainers < 3)
  688.                             plr->message = HUSTR_TALKTOSELF1;
  689.                         else if (num_nobrainers < 6)
  690.                             plr->message = HUSTR_TALKTOSELF2;
  691.                         else if (num_nobrainers < 9)
  692.                             plr->message = HUSTR_TALKTOSELF3;
  693.                         else if (num_nobrainers < 32)
  694.                             plr->message = HUSTR_TALKTOSELF4;
  695.                         else
  696.                             plr->message = HUSTR_TALKTOSELF5;
  697.                     }
  698.                 }
  699.             }
  700.         }
  701.     }
  702.     else
  703.     {
  704.         c = ev->data1;
  705.         // send a macro
  706.         if (altdown)
  707.         {
  708.             c = c - '0';
  709.             if (c > 9)
  710.                 return false;
  711.             // fprintf(stderr, "got here\n");
  712.             macromessage = chat_macros[c];
  713.            
  714.             // kill last message with a '\n'
  715.             HU_queueChatChar(KEY_ENTER); // DEBUG!!!
  716.            
  717.             // send the macro message
  718.             while (*macromessage)
  719.                 HU_queueChatChar(*macromessage++);
  720.             HU_queueChatChar(KEY_ENTER);
  721.            
  722.             // leave chat mode and notify that it was sent
  723.             chat_on = false;
  724.             strcpy(lastmessage, chat_macros[c]);
  725.             plr->message = lastmessage;
  726.             eatkey = true;
  727.         }
  728.         else
  729.         {
  730.             if (french)
  731.                 c = ForeignTranslation(c);
  732.             if (shiftdown || (c >= 'a' && c <= 'z'))
  733.                 c = shiftxform[c];
  734.             eatkey = HUlib_keyInIText(&w_chat, c);
  735.             if (eatkey)
  736.             {
  737.                 // static unsigned char buf[20]; // DEBUG
  738.                 HU_queueChatChar(c);
  739.                
  740.                 // sprintf(buf, "KEY: %d => %d", ev->data1, c);
  741.                 //      plr->message = buf;
  742.             }
  743.             if (c == KEY_ENTER)
  744.             {
  745.                 chat_on = false;
  746.                 if (w_chat.l.len)
  747.                 {
  748.                     strcpy(lastmessage, w_chat.l.l);
  749.                     plr->message = lastmessage;
  750.                 }
  751.             }
  752.             else if (c == KEY_ESCAPE)
  753.                 chat_on = false;
  754.         }
  755.     }
  756.  
  757.     return eatkey;
  758.  
  759. }
  760.