1 #include "Directories.h"
2 #include "Font.h"
3 #include "HImage.h"
4 #include "Local.h"
5 #include "MercTextBox.h"
6 #include "PODObj.h"
7 #include "VObject.h"
8 #include "VSurface.h"
9 #include "Font_Control.h"
10 #include "WordWrap.h"
11 #include "Render_Dirty.h"
12 #include "Video.h"
13 #include "MemMan.h"
14 #include "UILayout.h"
15 
16 #include <string_theory/string>
17 
18 #include <stdexcept>
19 
20 
21 #define TEXT_POPUP_GAP_BN_LINES		10
22 #define TEXT_POPUP_FONT			FONT12ARIAL
23 #define TEXT_POPUP_COLOR			FONT_MCOLOR_WHITE
24 
25 #define MERC_TEXT_FONT				FONT12ARIAL
26 #define MERC_TEXT_COLOR			FONT_MCOLOR_WHITE
27 
28 #define MERC_TEXT_MIN_WIDTH			10
29 #define MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_X	10
30 #define MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_Y	10
31 
32 #define MERC_BACKGROUND_WIDTH			350
33 #define MERC_BACKGROUND_HEIGHT			200
34 
35 
36 // both of the below are index by the enum for thier types - background and border in
37 // MercTextBox.h
38 
39 // filenames for border popup .sti's
40 static char const* const zMercBorderPopupFilenames[] =
41 {
42 	INTERFACEDIR "/tactpopup.sti",
43 	INTERFACEDIR "/tactredpopup.sti",
44 	INTERFACEDIR "/tactbluepopup.sti",
45 	INTERFACEDIR "/tactpopupmain.sti",
46 	INTERFACEDIR "/laptoppopup.sti"
47 };
48 
49 // filenames for background popup .pcx's
50 static char const* const zMercBackgroundPopupFilenames[] =
51 {
52 	INTERFACEDIR "/tactpopupbackground.pcx",
53 	INTERFACEDIR "/tactpopupwhitebackground.pcx",
54 	INTERFACEDIR "/tactpopupgreybackground.pcx",
55 	INTERFACEDIR "/tactpopupbackgroundmain.pcx",
56 	INTERFACEDIR "/laptoppopupbackground.pcx",
57 	INTERFACEDIR "/imp_popup_background.pcx"
58 };
59 
60 
61 struct MercPopUpBox
62 {
63 	SGPVSurface* uiSourceBufferIndex;
64 	UINT8        ubBackgroundIndex;
65 	UINT8        ubBorderIndex;
66 	SGPVSurface* uiMercTextPopUpBackground;
67 	SGPVObject*  uiMercTextPopUpBorder;
68 };
69 
70 
71 // the flags
72 static SGPVObject* guiBoxIcons;
73 static SGPVObject* guiSkullIcons;
74 
75 
InitMercPopupBox()76 void InitMercPopupBox()
77 {
78 	guiBoxIcons   = AddVideoObjectFromFile(INTERFACEDIR "/msgboxicons.sti");     // stop icon
79 	guiSkullIcons = AddVideoObjectFromFile(INTERFACEDIR "/msgboxiconskull.sti"); // skull icon
80 }
81 
82 
83 // Tactical Popup
LoadTextMercPopupImages(MercPopUpBox * const box,MercPopUpBackground const ubBackgroundIndex,MercPopUpBorder const ubBorderIndex)84 static void LoadTextMercPopupImages(MercPopUpBox* const box, MercPopUpBackground const ubBackgroundIndex, MercPopUpBorder const ubBorderIndex)
85 {
86 	// this function will load the graphics associated with the background and border index values
87 	box->uiMercTextPopUpBackground = AddVideoSurfaceFromFile(zMercBackgroundPopupFilenames[ubBackgroundIndex]);
88 	box->uiMercTextPopUpBorder     = AddVideoObjectFromFile(zMercBorderPopupFilenames[ubBorderIndex]);
89 
90 	// so far so good, return successful
91 	box->ubBackgroundIndex = ubBackgroundIndex;
92 	box->ubBorderIndex     = ubBorderIndex;
93 }
94 
95 
RemoveTextMercPopupImages(MercPopUpBox * const box)96 static void RemoveTextMercPopupImages(MercPopUpBox* const box)
97 {
98 	DeleteVideoSurface(box->uiMercTextPopUpBackground);
99 	DeleteVideoObject(box->uiMercTextPopUpBorder);
100 }
101 
102 
RenderMercPopUpBox(MercPopUpBox const * const box,INT16 const sDestX,INT16 const sDestY,SGPVSurface * const buffer)103 void RenderMercPopUpBox(MercPopUpBox const* const box, INT16 const sDestX, INT16 const sDestY, SGPVSurface* const buffer)
104 {
105 	if (!box) return;
106 
107 	// will render/transfer the image from the buffer in the data structure to the buffer specified by user
108 	SGPVSurface* const vs = box->uiSourceBufferIndex;
109 	BltVideoSurface(buffer, vs, sDestX, sDestY, NULL);
110 
111 	//Invalidate!
112 	if (buffer == FRAME_BUFFER)
113 	{
114 		InvalidateRegion(sDestX, sDestY, sDestX + vs->Width(), sDestY + vs->Height());
115 	}
116 }
117 
118 
119 static void GetMercPopupBoxFontColor(UINT8 ubBackgroundIndex, UINT8* pubFontColor, UINT8* pubFontShadowColor);
120 
121 
PrepareMercPopupBox(MercPopUpBox * box,MercPopUpBackground ubBackgroundIndex,MercPopUpBorder ubBorderIndex,const ST::utf32_buffer & codepoints,UINT16 usWidth,UINT16 usMarginX,UINT16 usMarginTopY,UINT16 usMarginBottomY,UINT16 * pActualWidth,UINT16 * pActualHeight,MercPopupBoxFlags flags)122 MercPopUpBox* PrepareMercPopupBox(MercPopUpBox* box, MercPopUpBackground ubBackgroundIndex, MercPopUpBorder ubBorderIndex, const ST::utf32_buffer& codepoints, UINT16 usWidth, UINT16 usMarginX, UINT16 usMarginTopY, UINT16 usMarginBottomY, UINT16* pActualWidth, UINT16* pActualHeight, MercPopupBoxFlags flags)
123 {
124 	if (usWidth >= SCREEN_WIDTH)
125 	{
126 		throw std::logic_error("Tried to create too wide merc popup box");
127 	}
128 
129 	if (usWidth <= MERC_TEXT_MIN_WIDTH) usWidth = MERC_TEXT_MIN_WIDTH;
130 
131 	SGP::PODObj<MercPopUpBox> new_box(0);
132 	// check id value, if -1, box has not been inited yet
133 	if (!box)
134 	{
135 		// no box yet
136 		box = new_box.Allocate();
137 		LoadTextMercPopupImages(box, ubBackgroundIndex, ubBorderIndex);
138 	}
139 	else
140 	{
141 		// has been created already,
142 		// Check if these images are different
143 		if (ubBackgroundIndex != box->ubBackgroundIndex ||
144 				ubBorderIndex     != box->ubBorderIndex)
145 		{
146 			//Remove old, set new
147 			RemoveTextMercPopupImages(box);
148 			LoadTextMercPopupImages(box, ubBackgroundIndex, ubBorderIndex);
149 		}
150 	}
151 
152 	UINT16 const usStringPixLength = StringPixLength(codepoints, TEXT_POPUP_FONT);
153 	UINT16       usTextWidth;
154 	if (usStringPixLength < usWidth - MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_X * 2)
155 	{
156 		usWidth     = usStringPixLength + MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_X * 2;
157 		usTextWidth = usWidth           - MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_X * 2 + 1;
158 	}
159 	else
160 	{
161 		usTextWidth = usWidth - MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_X * 2 + 1 - usMarginX;
162 	}
163 
164 	UINT16 const usNumberVerticalPixels = IanWrappedStringHeight(usTextWidth, 2, TEXT_POPUP_FONT, codepoints);
165 	UINT16       usHeight               = usNumberVerticalPixels + MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_Y * 2;
166 
167 	// Add height for margins
168 	usHeight += usMarginTopY + usMarginBottomY;
169 
170 	// Add width for margins
171 	usWidth += usMarginX * 2;
172 
173 	// Add width for iconic...
174 	if (flags & (MERC_POPUP_PREPARE_FLAGS_STOPICON | MERC_POPUP_PREPARE_FLAGS_SKULLICON))
175 	{
176 		// Make minimun height for box...
177 		if (usHeight < 45) usHeight = 45;
178 		usWidth += 35;
179 	}
180 
181 	if (usWidth >= MERC_BACKGROUND_WIDTH) usWidth = MERC_BACKGROUND_WIDTH - 1;
182 
183 	// make sure the area isnt bigger than the background texture
184 	if (usHeight >= MERC_BACKGROUND_HEIGHT)
185 	{
186 		throw std::logic_error("Tried to create too high merc popup box");
187 	}
188 
189 	// Create a background video surface to blt the face onto
190 	SGPVSurface* const vs = AddVideoSurface(usWidth, usHeight, PIXEL_DEPTH);
191 	box->uiSourceBufferIndex = vs;
192 
193 	*pActualWidth  = usWidth;
194 	*pActualHeight = usHeight;
195 
196 	if (flags & MERC_POPUP_PREPARE_FLAGS_TRANS_BACK)
197 	{
198 		// Zero with yellow,
199 		// Set source transparcenty
200 		vs->SetTransparency(FROMRGB(255, 255, 0));
201 		vs->Fill(Get16BPPColor(FROMRGB(255, 255, 0)));
202 	}
203 	else
204 	{
205 		SGPBox const DestRect = { 0, 0, usWidth, usHeight };
206 		BltVideoSurface(vs, box->uiMercTextPopUpBackground, 0, 0, &DestRect);
207 	}
208 
209 	const SGPVObject* const hImageHandle = box->uiMercTextPopUpBorder;
210 
211 	UINT16 usPosY = 0;
212 	//blit top row of images
213 	for (UINT16 i = TEXT_POPUP_GAP_BN_LINES; i < usWidth - TEXT_POPUP_GAP_BN_LINES; i += TEXT_POPUP_GAP_BN_LINES)
214 	{
215 		//TOP ROW
216 		BltVideoObject(vs, hImageHandle, 1, i, usPosY);
217 		//BOTTOM ROW
218 		BltVideoObject(vs, hImageHandle, 6, i, usHeight - TEXT_POPUP_GAP_BN_LINES + 6);
219 	}
220 
221 	//blit the left and right row of images
222 	UINT16 usPosX = 0;
223 	for (UINT16 i= TEXT_POPUP_GAP_BN_LINES; i < usHeight - TEXT_POPUP_GAP_BN_LINES; i += TEXT_POPUP_GAP_BN_LINES)
224 	{
225 		BltVideoObject(vs, hImageHandle, 3, usPosX,               i);
226 		BltVideoObject(vs, hImageHandle, 4, usPosX + usWidth - 4, i);
227 	}
228 
229 	//blt the corner images for the row
230 	//top left
231 	BltVideoObject(vs, hImageHandle, 0, 0,                                 usPosY);
232 	//top right
233 	BltVideoObject(vs, hImageHandle, 2, usWidth - TEXT_POPUP_GAP_BN_LINES, usPosY);
234 	//bottom left
235 	BltVideoObject(vs, hImageHandle, 5, 0,                                 usHeight - TEXT_POPUP_GAP_BN_LINES);
236 	//bottom right
237 	BltVideoObject(vs, hImageHandle, 7, usWidth - TEXT_POPUP_GAP_BN_LINES, usHeight - TEXT_POPUP_GAP_BN_LINES);
238 
239 	// Icon if ness....
240 	if (flags & MERC_POPUP_PREPARE_FLAGS_STOPICON)
241 	{
242 		BltVideoObject(vs, guiBoxIcons, 0, 5, 4);
243 	}
244 	if (flags & MERC_POPUP_PREPARE_FLAGS_SKULLICON)
245 	{
246 		BltVideoObject(vs, guiSkullIcons, 0, 9, 4);
247 	}
248 
249 	//Get the font and shadow colors
250 	UINT8 ubFontColor;
251 	UINT8 ubFontShadowColor;
252 	GetMercPopupBoxFontColor(ubBackgroundIndex, &ubFontColor, &ubFontShadowColor);
253 
254 	SetFontShadow(ubFontShadowColor);
255 	SetFontDestBuffer(vs);
256 
257 	//Display the text
258 	INT16 sDispTextXPos = MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_X + usMarginX;
259 
260 	if (flags & (MERC_POPUP_PREPARE_FLAGS_STOPICON | MERC_POPUP_PREPARE_FLAGS_SKULLICON))
261 	{
262 		sDispTextXPos += 30;
263 	}
264 
265 	DisplayWrappedString(sDispTextXPos, MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_Y + usMarginTopY, usTextWidth, 2, MERC_TEXT_FONT, ubFontColor, codepoints, FONT_MCOLOR_BLACK, LEFT_JUSTIFIED);
266 
267 	SetFontDestBuffer(FRAME_BUFFER);
268 	SetFontShadow(DEFAULT_SHADOW);
269 
270 	new_box.Release();
271 	return box;
272 }
273 
274 
275 //Deletes the surface thats contains the border, background and the text.
RemoveMercPopupBox(MercPopUpBox * const box)276 void RemoveMercPopupBox(MercPopUpBox* const box)
277 {
278 	if (!box) return;
279 
280 	DeleteVideoSurface(box->uiSourceBufferIndex);
281 
282 	//DEF Added 5/26
283 	//Delete the background and the border
284 	RemoveTextMercPopupImages(box);
285 
286 	delete box;
287 }
288 
289 
290 //Pass in the background index, and pointers to the font and shadow color
GetMercPopupBoxFontColor(UINT8 ubBackgroundIndex,UINT8 * pubFontColor,UINT8 * pubFontShadowColor)291 static void GetMercPopupBoxFontColor(UINT8 ubBackgroundIndex, UINT8* pubFontColor, UINT8* pubFontShadowColor)
292 {
293 	switch( ubBackgroundIndex )
294 	{
295 		case BASIC_MERC_POPUP_BACKGROUND:
296 			*pubFontColor = TEXT_POPUP_COLOR;
297 			*pubFontShadowColor = DEFAULT_SHADOW;
298 			break;
299 
300 		case WHITE_MERC_POPUP_BACKGROUND:
301 			*pubFontColor = 2;
302 			*pubFontShadowColor = FONT_MCOLOR_WHITE;
303 			break;
304 
305 		case GREY_MERC_POPUP_BACKGROUND:
306 			*pubFontColor = 2;
307 			*pubFontShadowColor = NO_SHADOW;
308 			break;
309 
310 		case LAPTOP_POPUP_BACKGROUND:
311 			*pubFontColor = TEXT_POPUP_COLOR;
312 			*pubFontShadowColor = DEFAULT_SHADOW;
313 			break;
314 
315 		default:
316 			*pubFontColor = TEXT_POPUP_COLOR;
317 			*pubFontShadowColor = DEFAULT_SHADOW;
318 			break;
319 	}
320 }
321