mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
300
Code/wwui/dialogparser.cpp
Normal file
300
Code/wwui/dialogparser.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program 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.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : Combat *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwui/dialogparser.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 10/25/01 3:54p $*
|
||||
* *
|
||||
* $Revision:: 12 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "dialogparser.h"
|
||||
#include "win.h"
|
||||
#include "translatedb.h"
|
||||
#include <commctrl.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Macros
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#define ALIGN_WORD_PTR(p) ((WORD *)(((DWORD)p + 1) & ~1))
|
||||
#define ALIGN_DWORD_PTR(p) ((DWORD *)(((DWORD)p + 3) & ~3))
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Local prototypes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
WORD *Skip_Dlg_Field (WORD *src, WCHAR *buffer = NULL, int buffer_len = 0, WORD *ctrl_type = NULL);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Skip_Dlg_Field
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
WORD *
|
||||
Skip_Dlg_Field (WORD *src, WCHAR *buffer, int buffer_len, WORD *ctrl_type)
|
||||
{
|
||||
//
|
||||
// These fields always start on the next word boundary, so align
|
||||
// the source pointer on this boundary.
|
||||
//
|
||||
WORD *retval = ALIGN_WORD_PTR(src);
|
||||
|
||||
//
|
||||
// Note: The field codes are as follows:
|
||||
//
|
||||
// 0xFFFF - The following WORD is an ordinal value of a system class.
|
||||
// 0x0000 - Empty field
|
||||
// Otherwise - The remaining data is a NULL terminated WCHAR string.
|
||||
//
|
||||
if (*retval == 0xFFFF) {
|
||||
|
||||
//
|
||||
// Move past the field designator
|
||||
//
|
||||
retval ++;
|
||||
|
||||
//
|
||||
// Does the user want information about the ctrl type?
|
||||
//
|
||||
if (ctrl_type != NULL) {
|
||||
*ctrl_type = *retval;
|
||||
}
|
||||
|
||||
//
|
||||
// Move past the ctrl type identifier
|
||||
//
|
||||
retval ++;
|
||||
} else if (*retval == 0x0000) {
|
||||
|
||||
//
|
||||
// Null terminate the string if the user is expecting data
|
||||
//
|
||||
if (buffer != NULL) {
|
||||
*buffer = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Move past the field designator
|
||||
//
|
||||
retval ++;
|
||||
} else {
|
||||
|
||||
//
|
||||
// The following data is a null-terminated string. Scan
|
||||
// as much data into our desination buffer as possible.
|
||||
// Note: The data is stored in wide character format.
|
||||
//
|
||||
while (*retval != 0x0000) {
|
||||
if (buffer != NULL && buffer_len > 1) {
|
||||
|
||||
//
|
||||
// Store this character in the supplied buffer
|
||||
// and decrement the remaining buffer length.
|
||||
//
|
||||
*buffer++ = *retval;
|
||||
buffer_len --;
|
||||
}
|
||||
retval ++;
|
||||
}
|
||||
|
||||
//
|
||||
// Ensure the supplied buffer is NULL terminated
|
||||
//
|
||||
if (buffer != NULL) {
|
||||
*buffer = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Advance to the next field
|
||||
//
|
||||
retval ++;
|
||||
}
|
||||
|
||||
//
|
||||
// Return the new buffer position to the caller
|
||||
//
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parse_Template
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DialogParserClass::Parse_Template
|
||||
(
|
||||
int res_id,
|
||||
int * dlg_width,
|
||||
int * dlg_height,
|
||||
WideStringClass * dlg_title,
|
||||
DynamicVectorClass<ControlDefinitionStruct> * control_list
|
||||
)
|
||||
{
|
||||
//
|
||||
// Load the resource file
|
||||
//
|
||||
HRSRC resource = ::FindResource (ProgramInstance, MAKEINTRESOURCE (res_id), RT_DIALOG);
|
||||
HGLOBAL hglobal = ::LoadResource (ProgramInstance, resource);
|
||||
LPVOID res_buffer = ::LockResource (hglobal);
|
||||
if(res_buffer != NULL) {
|
||||
|
||||
//
|
||||
// The first few bytes of the resource buffer are the DLGTEMPLATE structure
|
||||
//
|
||||
DLGTEMPLATE *dlg_template = (DLGTEMPLATE *)res_buffer;
|
||||
(*dlg_width) = (int)dlg_template->cx;
|
||||
(*dlg_height) = (int)dlg_template->cy;
|
||||
|
||||
//
|
||||
// Move past the DLGTEMPLATE header to the other fields
|
||||
//
|
||||
WORD *buffer = (WORD *)(((char *)res_buffer) + sizeof (DLGTEMPLATE));
|
||||
|
||||
//
|
||||
// Skip the menu, and window class
|
||||
//
|
||||
buffer = Skip_Dlg_Field (buffer);
|
||||
buffer = Skip_Dlg_Field (buffer);
|
||||
|
||||
//
|
||||
// Read the title
|
||||
//
|
||||
buffer = Skip_Dlg_Field (buffer, dlg_title->Get_Buffer (96), 96);
|
||||
|
||||
WCHAR *string_id = ::wcsstr (dlg_title->Peek_Buffer (), L"IDS_");
|
||||
if (string_id != NULL) {
|
||||
WideStringClass wide_string_id = string_id;
|
||||
StringClass ascii_string_id;
|
||||
wide_string_id.Convert_To (ascii_string_id);
|
||||
(*dlg_title) = TRANSLATE_BY_DESC(ascii_string_id);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Do we need to skip past the font settings?
|
||||
//
|
||||
if (dlg_template->style & DS_SETFONT) {
|
||||
buffer ++;
|
||||
while (*buffer != 0x0000) {
|
||||
buffer ++;
|
||||
}
|
||||
buffer ++;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop over each control and gather information about them
|
||||
//
|
||||
for (int index = 0; index < dlg_template->cdit; index ++) {
|
||||
DLGITEMTEMPLATE *dlg_item_template = (DLGITEMTEMPLATE *)ALIGN_DWORD_PTR((DWORD *)buffer);
|
||||
buffer = (WORD *)(((char *)dlg_item_template) + sizeof (DLGITEMTEMPLATE));
|
||||
|
||||
//
|
||||
// Read the ctrl type
|
||||
//
|
||||
WCHAR text_buffer[256] = { 0 };
|
||||
WORD ctrl_type = 0x0000;
|
||||
buffer = Skip_Dlg_Field (buffer, text_buffer, 256, &ctrl_type);
|
||||
|
||||
//
|
||||
// Wasn't one of the standard types, so see if we can determine
|
||||
// what it is by its class name.
|
||||
//
|
||||
if (ctrl_type == 0) {
|
||||
::_wcsupr (text_buffer);
|
||||
if (::wcsstr (text_buffer, L"TRACKBAR") != 0) {
|
||||
ctrl_type = SLIDER;
|
||||
} else if (::wcsstr (text_buffer, L"TABCONTROL") != 0) {
|
||||
ctrl_type = TAB;
|
||||
} else if (::wcsstr (text_buffer, L"LISTVIEW") != 0) {
|
||||
ctrl_type = LIST_CTRL;
|
||||
} else if (::wcsstr (text_buffer, L"MAP") != 0) {
|
||||
ctrl_type = MAP;
|
||||
} else if (::wcsstr (text_buffer, L"VIEWER") != 0) {
|
||||
ctrl_type = VIEWER;
|
||||
} else if (::wcsstr (text_buffer, L"HOTKEY") != 0) {
|
||||
ctrl_type = HOTKEY;
|
||||
} else if (::wcsstr (text_buffer, L"SHORTCUTBAR") != 0) {
|
||||
ctrl_type = SHORTCUT_BAR;
|
||||
} else if (::wcsstr (text_buffer, L"MERCHANDISE") != 0) {
|
||||
ctrl_type = MERCHANDISE_CTRL;
|
||||
} else if (::wcsstr (text_buffer, L"TREEVIEW") != 0) {
|
||||
ctrl_type = TREE_CTRL;
|
||||
} else if (::wcsicmp(text_buffer, PROGRESS_CLASSW) == 0) {
|
||||
ctrl_type = PROGRESS_BAR;
|
||||
} else if (::wcsstr (text_buffer, L"HEALTHBAR") != 0) {
|
||||
ctrl_type = HEALTH_BAR;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Read the window text
|
||||
//
|
||||
buffer = Skip_Dlg_Field (buffer, text_buffer, 256);
|
||||
|
||||
WCHAR *string_id = ::wcsstr (text_buffer, L"IDS_");
|
||||
if (string_id != NULL) {
|
||||
WideStringClass wide_string_id = string_id;
|
||||
StringClass ascii_string_id;
|
||||
wide_string_id.Convert_To (ascii_string_id);
|
||||
WideStringClass translation = TRANSLATE_BY_DESC(ascii_string_id);
|
||||
::wcscpy (string_id, translation);
|
||||
}
|
||||
|
||||
//
|
||||
// Add this control definition to the list
|
||||
//
|
||||
ControlDefinitionStruct definition;
|
||||
definition.id = (int)dlg_item_template->id;
|
||||
definition.style = dlg_item_template->style;
|
||||
definition.x = dlg_item_template->x;
|
||||
definition.y = dlg_item_template->y;
|
||||
definition.cx = dlg_item_template->cx;
|
||||
definition.cy = dlg_item_template->cy;
|
||||
definition.type = (CONTROL_TYPE)ctrl_type;
|
||||
definition.title = text_buffer;
|
||||
control_list->Add (definition);
|
||||
|
||||
//
|
||||
// Skip past the extra data
|
||||
//
|
||||
WORD extra_data_size = *buffer;
|
||||
buffer ++;
|
||||
if (extra_data_size > 0) {
|
||||
buffer = (WORD *)(((char *)ALIGN_WORD_PTR(buffer)) + extra_data_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user