//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
// software: you can redistribute it and/or modify it under the terms of 
// the GNU General Public License as published by the Free Software Foundation, 
// either version 3 of the License, or (at your option) any later version.

// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
// in the hope that it will be useful, but with permitted additional restrictions 
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
// distributed with this program. You should have received a copy of the 
// GNU General Public License along with permitted additional restrictions 
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection

/* $Header: /CounterStrike/HELP.CPP 1     3/03/97 10:24a Joe_bostic $ */
/***********************************************************************************************
 ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
 ***********************************************************************************************
 *                                                                                             *
 *                 Project Name : Command & Conquer                                            *
 *                                                                                             *
 *                    File Name : HELP.CPP                                                     *
 *                                                                                             *
 *                   Programmer : Joe L. Bostic                                                *
 *                                                                                             *
 *                   Start Date : 11/18/94                                                     *
 *                                                                                             *
 *                  Last Update : September 22, 1995 [JLB]                                     *
 *                                                                                             *
 *---------------------------------------------------------------------------------------------*
 * Functions:                                                                                  *
 *   HelpClass::Draw_Help -- Display the help message (if necessary).                          *
 *   HelpClass::HelpClass -- Default constructor for the help processor.                       *
 *   HelpClass::Help_AI -- Handles the help text logic.                                        *
 *   HelpClass::Help_Text -- Assigns text as the current help text.                            *
 *   HelpClass::Init_Clear -- Sets help system to a known state.                               *
 *   HelpClass::Overlap_List -- Returns with offset list for cells under help text.            *
 *   HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards.                  *
 *   HelpClass::Set_Cost -- Initiates the second line of help text showing item cost.          *
 *   HelpClass::Set_Tactical_Position -- Sets the position of the tactical map.                *
 *   HelpClass::Set_Tactical_Position -- Sets the tactical map position.                       *
 *   HelpClass::Set_Tactical_Position -- Sets the tactical map position.                       *
 *   HelpClass::Set_Text -- Determines the overlap list and draw coordinates.                  *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include	"function.h"

/*
**	This is the holding buffer for the text overlap list. This buffer must be in the near
**	data segment. It will be filled in by the Set_Text() function.
*/
//short const HelpClass::OverlapList[60] = {  // Can't be const - it's expected to be written to. ST - 2/7/2019 5:16PM		
short HelpClass::OverlapList[60] = {
	REFRESH_EOL
};

char const * HelpClass::HelpText;


/***********************************************************************************************
 * HelpClass::HelpClass -- Default constructor for the help processor.                         *
 *                                                                                             *
 *    The help processor is initialized by this routine. It merely sets up the help engine     *
 *    to the default state. The default state will not display any help text. Call the         *
 *    Help_Text() function to enable help processing.                                          *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   11/18/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
HelpClass::HelpClass(void) :
	HelpX(0),
	HelpY(0),
	HelpWidth(0),
	IsRight(false),
	Cost(0),
	X(0),
	Y(0),
	DrawX(0),
	DrawY(0),
	Width(0),
	Text(TXT_NONE),
	Color(LTGREY),
	CountDownTimer(0)
{
}


/***********************************************************************************************
 * HelpClass::Init_Clear -- Sets help system to a known state.                                 *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   12/24/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
void HelpClass::Init_Clear(void)
{
	TabClass::Init_Clear();

	Set_Text(TXT_NONE);
}


/***********************************************************************************************
 * HelpClass::Overlap_List -- Returns with offset list for cells under help text.              *
 *                                                                                             *
 *    Use this routine to fetch an offset list for the cells under the text displayed. If      *
 *    there is no text displayed, then the list will consist of just the terminator code.      *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  Returns with a pointer to the offset list for the help text overlap. The offset    *
 *          list is based on the tactical map upper left corner cell.                          *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   11/18/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
short const * HelpClass::Overlap_List(void) const
{
	if (Text == TXT_NONE || CountDownTimer) {
		((short &)(OverlapList[0])) = REFRESH_EOL;
	}
	return(OverlapList);
}


/***********************************************************************************************
 * HelpClass::Help_AI -- Handles the help text logic.                                          *
 *                                                                                             *
 *    This routine handles tracking the mouse position to see if the mouse remains stationary  *
 *    for the required amount of time. If the time requirement has been met, then it flags     *
 *    the help system to display the help text the next time the Draw_Help() function is       *
 *    called.                                                                                  *
 *                                                                                             *
 * INPUT:   key   -- Keyboard input code.                                                      *
 *                                                                                             *
 *          x,y   -- Mouse coordinates.                                                        *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   This routine must be called once and only once per game frame (15 times per     *
 *             second).                                                                        *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   11/18/1994 JLB : Created.                                                                 *
 *   12/31/1994 JLB : Uses mouse coordinates as passed in.                                     *
 *=============================================================================================*/
void HelpClass::AI(KeyNumType &key, int x, int y)
{
	if (!CountDownTimer && !IsRight && (x != X || y != Y)) {
		Help_Text(TXT_NONE);
	}

	/*
	**	Process the countdown timer only if it hasn't already expired and there is
	**	a real help text message to display.
	*/
	if (CountDownTimer && !HelpText && Text != TXT_NONE) {

		/*
		**	If the mouse has moved, then reset the timer since a moving mouse is not
		**	supposed to bring up the help text.
		*/
		if (!IsRight && (X != x || Y != y)) {
			X = x;
			Y = y;
			CountDownTimer = HELP_DELAY;
			Help_Text(TXT_NONE);
		} else {

			/*
			**	If the delay has expired, then the text must be drawn. Build the help text
			**	overlay list at this time. Better to do it now, when we KNOW it is needed, then
			**	to do it earlier when it might not be needed.
			*/
			Set_Text(Text);
		}
	}

	TabClass::AI(key, x, y);
}


/***********************************************************************************************
 * HelpClass::Help_Text -- Assigns text as the current help text.                              *
 *                                                                                             *
 *    Use this routine to change the help text that will pop up if the cursor isn't moved      *
 *    for the help delay duration. Call this routine as often as desired.                      *
 *                                                                                             *
 * INPUT:   text  -- The text number for the help text to use.                                 *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   11/18/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
void HelpClass::Help_Text(int text, int x, int y, int color, bool quick)
{
	if (text != Text) {

		/*
		**	If there is an existing text message, then flag the map to redraw the underlying
		**	icons so that the text message is erased.
		*/
		if (Text != TXT_NONE) {
			Refresh_Cells(Coord_Cell(TacticalCoord), &OverlapList[0]);
		}

		/*
		**	Record the position of the mouse. This recorded position will be used to determine
		**	if the mouse has moved. A moving mouse prevents the help text from popping up.
		*/
		X = x;
		if (x == -1) X = Get_Mouse_X();
		Y = y;
		if (y == -1) Y = Get_Mouse_Y();
		IsRight = (y != -1) || (x != -1);

		if (quick) {
			CountDownTimer = 1;
		} else {
			CountDownTimer = HELP_DELAY;
		}

		/*
		** All help text prints in the same color for E3
		*/
		//Color = color;
		color = color;
		Color = HELP_TEXT_COLOR;
		Text = text;
		Cost = 0;
	}
}


/***********************************************************************************************
 * HelpClass::Draw_Help -- Display the help message (if necessary).                            *
 *                                                                                             *
 *    This function will print the help text if it thinks it should. The timer and text        *
 *    message can control whether this occurs. If there is no help text or the countdown timer *
 *    has not expired, then no text will be printed.                                           *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   11/18/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
void HelpClass::Draw_It(bool forced)
{
	TabClass::Draw_It(forced);

	forced = false;		// TCTCTCTC
	if (Text != TXT_NONE && (forced || !CountDownTimer)) {

		if (LogicPage->Lock()) {
			Plain_Text_Print(Text, DrawX, DrawY, Color, BLACK, TPF_MAP|TPF_NOSHADOW);
			LogicPage->Draw_Rect(DrawX-1, DrawY-1, DrawX+Width+1, DrawY+FontHeight, Color);

			if (Cost) {
				char buffer[15];
				sprintf(buffer, "$%d", Cost);
				int width = String_Pixel_Width(buffer);

				Plain_Text_Print(buffer, DrawX, DrawY+FontHeight, Color, BLACK, TPF_MAP|TPF_NOSHADOW);
				LogicPage->Draw_Rect(DrawX-1, DrawY+FontHeight, DrawX+width+1, DrawY+FontHeight+FontHeight-1, Color);
				LogicPage->Draw_Line(DrawX, DrawY+FontHeight, DrawX+min(width+1, Width)-1, DrawY+FontHeight, BLACK);
			}
			LogicPage->Unlock();
		}
	}
}


/***********************************************************************************************
 * HelpClass::Set_Text -- Determines the overlap list and draw coordinates.                    *
 *                                                                                             *
 *    This routine is used to build the overlap list -- used for icon refreshing. It also      *
 *    determines if the text can fit on the screen and makes adjustments so that it will.      *
 *                                                                                             *
 * INPUT:   text  -- The text number to set the help system to use.                            *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   11/18/1994 JLB : Created.                                                                 *
 *   12/11/1994 JLB : Won't draw past tactical map edges.                                      *
 *=============================================================================================*/
void HelpClass::Set_Text(int text)
{
	if (text != TXT_NONE) {
		Text = text;
		Plain_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_MAP|TPF_NOSHADOW);
		Width = String_Pixel_Width(Text_String(Text));
		if (IsRight) {
			DrawX = X - Width;
			DrawY = Y;
		} else {
			int right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth) - 3*RESFACTOR;
			int bottom = TacPixelY + Lepton_To_Pixel(TacLeptonHeight) - 1*RESFACTOR;

			DrawX = X+X_OFFSET;
			DrawY = Y+Y_OFFSET;
			if (DrawX + Width > right) {
				DrawX -= (DrawX+Width) - right;
			}
			if (DrawY + 10*RESFACTOR > bottom) {
				DrawY -= (DrawY+10*RESFACTOR) - bottom;
			}
			if (DrawX < TacPixelX+1) DrawX = TacPixelX+1;
			if (DrawY < TacPixelY+1) DrawY = TacPixelY+1;
		}
		memcpy((void*)OverlapList, Text_Overlap_List(Text_String(Text), DrawX-1, DrawY), sizeof(OverlapList));
		*(short *)&OverlapList[ARRAY_SIZE(OverlapList)-1] = REFRESH_EOL;
	}
}


/***********************************************************************************************
 * HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards.                    *
 *                                                                                             *
 *    This routine intercepts the map scrolling request and then makes sure that if, in fact,  *
 *    the map is going to scroll, then reset and erase the help text so that it doesn't        *
 *    mess up the display.                                                                     *
 *                                                                                             *
 * INPUT:   facing   -- The direction to scroll (unused by this routine).                      *
 *                                                                                             *
 *          really   -- If the scroll is actually going to occur, rather than just be examined *
 *                      for legality, then this parameter will be true. If this parameter is   *
 *                      true, then the help text is reset.                                     *
 *                                                                                             *
 * OUTPUT:  Returns if it can, or did, scroll in the requested direction.                      *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   12/15/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
bool HelpClass::Scroll_Map(DirType facing, int & distance, bool really)
{
	if (really) {
		Help_Text(TXT_NONE);
	}
	return(TabClass::Scroll_Map(facing, distance, really));
}


/***********************************************************************************************
 * HelpClass::Set_Cost -- Initiates the second line of help text showing item cost.            *
 *                                                                                             *
 *    Use this routine after the Help_Text() function to activate the second line. The second  *
 *    line displays a cost. Typically, this is used by the sidebar to display the cost of the  *
 *    specified item.                                                                          *
 *                                                                                             *
 * INPUT:   cost  -- The cost to associate with this help text. If this value is zero, then    *
 *                   no second line is displayed, so don't pass in zero.                       *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   01/09/1995 JLB : Created.                                                                 *
 *=============================================================================================*/
void HelpClass::Set_Cost(int cost)
{
	Cost = cost;
}


/***********************************************************************************************
 * HelpClass::Set_Tactical_Position -- Sets the position of the tactical map.                  *
 *                                                                                             *
 *    This routine will set the position of the tactical map. At this class level, it merely   *
 *    makes sure that the help text disappears when this happens. The lower level classes      *
 *    actually change the map's position.                                                      *
 *                                                                                             *
 * INPUT:   coord -- The new coordinate to make the upper left corner of the visible display.  *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   09/22/1995 JLB : Created.                                                                 *
 *=============================================================================================*/
void HelpClass::Set_Tactical_Position(COORDINATE coord)
{
	if (TacticalCoord != coord) {
		Help_Text(TXT_NONE);
	}
	TabClass::Set_Tactical_Position(coord);
}