home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #2 / amigaacscoverdisc1998-021998.iso / games / doom / source / linuxdoom-1.10 / hu_stuff.c < prev    next >
C/C++ Source or Header  |  1997-12-22  |  15KB  |  760 lines

  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.