mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 18:31:26 -10:00
If you press a key such as Ctrl the code gets a bitfield with a high bit set so when the key code is used as an index it produces an out of range error. Thank you AddressSanitizer!
286 lines
6.5 KiB
C++
286 lines
6.5 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "cfile/cfile.h"
|
|
#include "freespace.h"
|
|
#include "gamesnd/gamesnd.h"
|
|
#include "globalincs/alphacolors.h"
|
|
#include "graphics/font.h"
|
|
#include "io/key.h"
|
|
#include "io/mouse.h"
|
|
#include "localization/localize.h"
|
|
#include "menuui/snazzyui.h"
|
|
|
|
|
|
extern int ascii_table[];
|
|
extern int shifted_ascii_table[];
|
|
|
|
static int Snazzy_mouse_left_was_down;
|
|
|
|
void snazzy_flush()
|
|
{
|
|
Snazzy_mouse_left_was_down = 0;
|
|
}
|
|
|
|
void snazzy_menu_init()
|
|
{
|
|
game_flush();
|
|
}
|
|
|
|
// snazzy_menu_do()
|
|
//
|
|
// This function will return an identifier that matches the region of the
|
|
// image the mouse pointer is currently over. The function works by working
|
|
// with two images
|
|
//
|
|
// 1. An image that is displayed to the player
|
|
// 2. A second image, not seen, which has masks for certain areas of image 1
|
|
//
|
|
// The idea is to read the mouse, and determine if the mouse pointer is currently
|
|
// over one of these regions. Since these regions may be many different colors,
|
|
// the mask is checked instead, since the regions are always a uniform color
|
|
//
|
|
// The action parameter is used to return whether the region is clicked on or simply
|
|
// has the mouse over it. The #defines SNAZZY_OVER and SNAZZY_CLICKED are used.
|
|
//
|
|
// The purpose of the key_in parameter is to allow the caller to determine if any
|
|
// keys are pressed while within the snazzy_menu_do(). It is an optional parameter.
|
|
//
|
|
|
|
int snazzy_menu_do(ubyte *data, int mask_w, int mask_h, int num_regions, MENU_REGION *regions, int *action, int poll_key, int *key)
|
|
{
|
|
GR_DEBUG_SCOPE("Snazzy Menu");
|
|
|
|
int i, k, x, y, offset;
|
|
int choice = -1, mouse_on_choice = -1;
|
|
ubyte pixel_value = 0;
|
|
|
|
Assert(data != NULL);
|
|
Assert(num_regions > 0);
|
|
Assert(regions != NULL);
|
|
|
|
gr_reset_clip(); // don't remove
|
|
mouse_get_pos_unscaled( &x, &y );
|
|
|
|
// boundary conditions
|
|
if((y < 0) || (y > mask_h - 1) || (x < 0) || (x > mask_w - 1)){
|
|
pixel_value = 255;
|
|
} else {
|
|
// check the pixel value under the mouse
|
|
offset = y * mask_w + x;
|
|
pixel_value = *(data + (offset));
|
|
}
|
|
|
|
*action = -1;
|
|
|
|
k = 0;
|
|
if ( poll_key ) {
|
|
k = game_check_key();
|
|
if (key)
|
|
*key = k; // pass keypress back to caller
|
|
}
|
|
|
|
// if (mouse_down_count(MOUSE_LEFT_BUTTON) ) {
|
|
if ( !mouse_down(MOUSE_LEFT_BUTTON) && Snazzy_mouse_left_was_down ) {
|
|
//nprintf(("Alan", "pixel val: %d\n", pixel_value));
|
|
for (i=0; i < num_regions; i++) {
|
|
if (pixel_value == regions[i].mask) {
|
|
choice = regions[i].mask;
|
|
if ( regions[i].click_sound.isValid() ) {
|
|
snd_play( gamesnd_get_interface_sound(regions[i].click_sound), 0.0f );
|
|
}
|
|
}
|
|
} // end for
|
|
}
|
|
|
|
switch ( k ) {
|
|
case KEY_ESC:
|
|
choice = ESC_PRESSED;
|
|
break;
|
|
|
|
default:
|
|
if (k && k >= 0 && static_cast<size_t>(k) < SIZE_OF_ASCII_TABLE) {
|
|
for (i = 0; i < num_regions; i++) {
|
|
if (!regions[i].key)
|
|
continue;
|
|
if (ascii_table[k] == regions[i].key || shifted_ascii_table[k] == regions[i].key) {
|
|
choice = regions[i].mask;
|
|
if (regions[i].click_sound.isValid()) {
|
|
snd_play(gamesnd_get_interface_sound(regions[i].click_sound), 0.0f);
|
|
}
|
|
}
|
|
} // end for
|
|
}
|
|
|
|
break;
|
|
|
|
} // end switch
|
|
|
|
for (i=0; i<num_regions; i++) {
|
|
if (pixel_value == regions[i].mask) {
|
|
mouse_on_choice = regions[i].mask;
|
|
break;
|
|
}
|
|
} // end for
|
|
|
|
gr_set_color_fast(&Color_white);
|
|
font::set_font(font::FONT1);
|
|
|
|
if ((mouse_on_choice >= 0) && (mouse_on_choice <= (num_regions)) && (i >=0)) {
|
|
int w;
|
|
gr_get_string_size(&w, NULL, regions[i].text);
|
|
|
|
gr_printf_menu( (gr_screen.clip_width_unscaled - w) / 2, 450, "%s", regions[i].text );
|
|
}
|
|
|
|
if ( mouse_down(MOUSE_LEFT_BUTTON) ){
|
|
Snazzy_mouse_left_was_down = 1;
|
|
} else {
|
|
Snazzy_mouse_left_was_down = 0;
|
|
}
|
|
|
|
if ( choice > -1 || choice == ESC_PRESSED ) {
|
|
*action = SNAZZY_CLICKED;
|
|
return choice;
|
|
}
|
|
|
|
if ( mouse_on_choice > -1 ) {
|
|
*action = SNAZZY_OVER;
|
|
return mouse_on_choice;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// add_region() will set up a menu region
|
|
//
|
|
//
|
|
//
|
|
|
|
void snazzy_menu_add_region(MENU_REGION* region, const char* text, int mask, int key, interface_snd_id click_sound)
|
|
{
|
|
region->mask = mask;
|
|
region->key = key;
|
|
strcpy_s(region->text, text);
|
|
region->click_sound = click_sound;
|
|
}
|
|
|
|
|
|
|
|
// read_menu_tbl() will parse through menu.tbl and store the different menu region data
|
|
//
|
|
//
|
|
//
|
|
|
|
void read_menu_tbl(const char* menu_name, char* bkg_filename, char* mask_filename, MENU_REGION* regions, int* num_regions, int play_sound)
|
|
{
|
|
CFILE* fp;
|
|
int state=0;
|
|
char* p1, *p2, *p3;
|
|
//char music_filename[128];
|
|
|
|
char seps[] = NOX(" ,\t");
|
|
char *token;
|
|
char tmp_line[132];
|
|
|
|
*num_regions=0;
|
|
|
|
fp = cfopen( NOX("menu.tbl"), "rt" );
|
|
if (fp == NULL) {
|
|
Error(LOCATION, "menu.tbl could not be opened\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
while (cfgets(tmp_line, 132, fp)) {
|
|
p1 = strchr(tmp_line,'\n'); if (p1) *p1 = '\0';
|
|
p1 = strchr(tmp_line,';'); if (p1) *p1 = '\0';
|
|
p1 = p3 = strchr( tmp_line, '[' );
|
|
|
|
if (p3 && state == 1) {
|
|
cfclose(fp);
|
|
return;
|
|
}
|
|
|
|
if ( p1 || p3) {
|
|
if (!state) {
|
|
p2 = strchr( tmp_line, ']' );
|
|
if (p2) *p2 = 0;
|
|
if (!stricmp( ++p1, menu_name )) state = 1;
|
|
} else {
|
|
cfclose(fp);
|
|
break;
|
|
}
|
|
} else if (state) {
|
|
|
|
|
|
// parse a region line
|
|
p1 = strchr( tmp_line, '\"' );
|
|
if (p1) {
|
|
p2 = strchr( tmp_line+1, '\"' );
|
|
if (!p2) {
|
|
nprintf(("Warning","Error parsing menu file\n"));
|
|
|
|
return;
|
|
}
|
|
*p2 = 0;
|
|
strcpy_s(regions[*num_regions].text,++p1);
|
|
p2++;
|
|
|
|
// get the tokens mask number
|
|
token = strtok( p2, seps );
|
|
regions[*num_regions].mask = atoi(token);
|
|
|
|
// get the hot key character
|
|
token = strtok( NULL, seps );
|
|
regions[*num_regions].key = token[0];
|
|
|
|
// stuff default click sound (not in menu.tbl)
|
|
if ( play_sound ) {
|
|
regions[*num_regions].click_sound = InterfaceSounds::IFACE_MOUSE_CLICK;
|
|
} else {
|
|
regions[*num_regions].click_sound = interface_snd_id();
|
|
}
|
|
|
|
*num_regions = *num_regions + 1;
|
|
|
|
}
|
|
else {
|
|
// get the menu filenames
|
|
|
|
// Establish string and get the first token
|
|
token = strtok( tmp_line, seps );
|
|
if ( token != NULL )
|
|
{
|
|
// store the background filename
|
|
strcpy(bkg_filename, token);
|
|
|
|
// get the mask filename
|
|
token = strtok( NULL, seps );
|
|
strcpy(mask_filename, token);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cfclose(fp);
|
|
}
|
|
|
|
// snazzy_menu_close() is called when the menu using a snazzy interface is exited
|
|
//
|
|
//
|
|
|
|
void snazzy_menu_close()
|
|
{
|
|
game_flush();
|
|
}
|