2015-05-19 21:54:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
|
|
|
|
Shadow Warrior 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 2
|
|
|
|
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, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-10-09 16:09:05 +00:00
|
|
|
#include "ns.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#undef MAIN
|
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
#include "names2.h"
|
|
|
|
#include "panel.h"
|
|
|
|
#include "lists.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "pal.h"
|
2020-08-05 22:18:45 +00:00
|
|
|
#include "misc.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "menus.h"
|
|
|
|
|
2019-03-21 02:24:19 +00:00
|
|
|
#include "network.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#define PANEL_FONT_G 3636
|
|
|
|
#define PANEL_FONT_Y 3646
|
|
|
|
#define PANEL_FONT_R 3656
|
|
|
|
|
|
|
|
#define PANEL_SM_FONT_G 3601
|
|
|
|
#define PANEL_SM_FONT_Y 3613
|
|
|
|
#define PANEL_SM_FONT_R 3625
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
PANEL_SPRITEp pClearTextLineID(PLAYERp pp, short id, int y, short pri)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PANEL_SPRITEp psp=NULL, next;
|
|
|
|
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
|
|
{
|
|
|
|
// early out
|
|
|
|
if (psp->priority > pri)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (psp->ID == id && psp->y == y && psp->priority == pri)
|
|
|
|
{
|
|
|
|
pSetSuicide(psp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only call this from menu code - it does a pKillSprite
|
2019-11-17 17:02:17 +00:00
|
|
|
PANEL_SPRITEp pMenuClearTextLineID(PLAYERp pp, short id, int y, short pri)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PANEL_SPRITEp psp=NULL, next;
|
|
|
|
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
|
|
{
|
|
|
|
// early out
|
|
|
|
if (psp->priority > pri)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (psp->ID == id && psp->y == y && psp->priority == pri)
|
|
|
|
{
|
|
|
|
pKillSprite(psp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
void pClearTextLine(PLAYERp pp, int y)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
pClearTextLineID(pp, ID_TEXT, y, PRI_FRONT_MAX);
|
|
|
|
}
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
void StringTimer(PANEL_SPRITEp psp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if ((psp->kill_tics -= synctics) <= 0)
|
|
|
|
{
|
|
|
|
pKillSprite(psp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
void PutStringTimer(PLAYERp pp, short x, short y, const char *string, short seconds)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int ndx, offset;
|
|
|
|
char c;
|
|
|
|
PANEL_SPRITEp nsp;
|
|
|
|
long kill_tics;
|
|
|
|
short id, ac;
|
2019-04-08 06:27:31 +00:00
|
|
|
PANEL_SPRITE_FUNCp func;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
offset = x;
|
|
|
|
|
|
|
|
if (seconds == 999)
|
|
|
|
{
|
|
|
|
pClearTextLineID(pp, ID_TEXT, y, PRI_FRONT_MAX);
|
|
|
|
func = NULL;
|
|
|
|
kill_tics = 0;
|
|
|
|
id = ID_TEXT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pClearTextLineID(pp, ID_TEXT, y, PRI_FRONT_MAX);
|
|
|
|
func = StringTimer;
|
|
|
|
kill_tics = seconds * 120;
|
|
|
|
id = ID_TEXT;
|
|
|
|
}
|
|
|
|
|
2020-08-14 19:01:27 +00:00
|
|
|
// Temporarily disabled because this uses a feature of the panel system that needs to be removed before this can be refactored.
|
|
|
|
#if 0
|
2015-05-19 21:54:34 +00:00
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
ac = c - '!' + STARTALPHANUM;
|
|
|
|
if ((ac < STARTALPHANUM || ac > ENDALPHANUM) && c != asc_Space)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c > asc_Space && c < 127)
|
|
|
|
{
|
|
|
|
nsp = pSpawnFullViewSprite(pp, ac, PRI_FRONT_MAX, offset, y);
|
2019-04-08 06:27:31 +00:00
|
|
|
nsp->PanelSpriteFunc = func;
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->kill_tics = kill_tics;
|
|
|
|
nsp->ID = id;
|
2015-05-19 22:02:25 +00:00
|
|
|
offset += tilesiz[ac].x;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else if (c == asc_Space)
|
|
|
|
offset += 4; // Special case for space char
|
|
|
|
}
|
2020-08-14 19:01:27 +00:00
|
|
|
#endif
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
void KillString(PLAYERp pp, short y)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
pClearTextLineID(pp, ID_TEXT, y, PRI_FRONT_MAX);
|
|
|
|
}
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
PANEL_SPRITEp pClearSpriteXY(PLAYERp pp, short x, short y)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PANEL_SPRITEp psp=NULL, next;
|
|
|
|
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
|
|
{
|
|
|
|
if (psp->x == x && psp->y == y)
|
|
|
|
pSetSuicide(psp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
PANEL_SPRITEp pClearSpriteID(PLAYERp pp, short id)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PANEL_SPRITEp psp=NULL, next;
|
|
|
|
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
|
|
{
|
|
|
|
if (psp->ID == id)
|
|
|
|
pSetSuicide(psp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-07 13:51:53 +00:00
|
|
|
void
|
2020-08-15 13:29:47 +00:00
|
|
|
DisplayMiniBarSmString(short xs, short ys, short pal, const char *buffer)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short size=4,x;
|
|
|
|
const char *ptr;
|
|
|
|
short pic;
|
|
|
|
|
|
|
|
#define FRAG_FIRST_ASCII ('!') //exclamation point
|
|
|
|
#define FRAG_FIRST_TILE 2930 //exclamation point
|
|
|
|
|
|
|
|
for (ptr = buffer, x = xs; *ptr; ptr++, x += size)
|
|
|
|
{
|
|
|
|
if (*ptr == ' ')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ASSERT(*ptr >= '!' && *ptr <= '}');
|
|
|
|
|
|
|
|
pic = FRAG_FIRST_TILE + (*ptr - FRAG_FIRST_ASCII);
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
rotatesprite((int)x << 16, (int)ys << 16, (1 << 16), 0, pic, 0, pal,
|
2020-08-14 19:12:32 +00:00
|
|
|
ROTATE_SPRITE_SCREEN_CLIP | RS_TOPLEFT | RS_ALIGN_L,
|
2019-12-05 05:40:30 +00:00
|
|
|
0, 0, xdim - 1, ydim - 1);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-15 13:29:47 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Measure the pixel width of a graphic string
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
static char lg_xlat_num[] = { 0,1,2,3,4,5,6,7,8,9 };
|
|
|
|
#define FONT_LARGE_ALPHA 3706
|
|
|
|
#define FONT_LARGE_DIGIT 3732
|
|
|
|
#define MenuDrawFlags (ROTATE_SPRITE_SCREEN_CLIP)
|
|
|
|
#define MZ 65536
|
|
|
|
#define MENU_SHADE_DEFAULT 0
|
|
|
|
#define MENU_SHADE_INACTIVE 20
|
|
|
|
|
|
|
|
void MNU_MeasureStringLarge(const char* string, short* w, short* h)
|
|
|
|
{
|
|
|
|
short ndx, width, height;
|
|
|
|
char c;
|
|
|
|
short pic;
|
|
|
|
|
|
|
|
width = 0;
|
|
|
|
height = *h;
|
|
|
|
|
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
if (isalpha(c))
|
|
|
|
{
|
|
|
|
c = toupper(c);
|
|
|
|
pic = FONT_LARGE_ALPHA + (c - 'A');
|
|
|
|
}
|
|
|
|
else if (isdigit(c))
|
|
|
|
{
|
|
|
|
pic = FONT_LARGE_DIGIT + lg_xlat_num[(c - '0')];
|
|
|
|
}
|
|
|
|
else if (c == ' ')
|
|
|
|
{
|
|
|
|
width += 10; // Special case for space char
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
width += tilesiz[pic].x + 1;
|
|
|
|
if (height < tilesiz[pic].y)
|
|
|
|
height = tilesiz[pic].y;
|
|
|
|
}
|
|
|
|
|
|
|
|
*w = width;
|
|
|
|
*h = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Draw a string using a graphic font
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
void MNU_DrawStringLarge(short x, short y, const char* string, int shade)
|
|
|
|
{
|
|
|
|
int ndx, offset;
|
|
|
|
char c;
|
|
|
|
short pic;
|
|
|
|
|
|
|
|
offset = x;
|
|
|
|
|
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
if (isalpha(c))
|
|
|
|
{
|
|
|
|
c = toupper(c);
|
|
|
|
pic = FONT_LARGE_ALPHA + (c - 'A');
|
|
|
|
}
|
|
|
|
else if (isdigit(c))
|
|
|
|
{
|
|
|
|
pic = FONT_LARGE_DIGIT + lg_xlat_num[(c - '0')];
|
|
|
|
}
|
|
|
|
else if (c == ' ')
|
|
|
|
{
|
|
|
|
offset += 10;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
rotatesprite(offset << 16, y << 16, MZ, 0, pic, shade, 0, MenuDrawFlags | RS_TOPLEFT, 0, 0, xdim - 1, ydim - 1);
|
|
|
|
offset += tilesiz[pic].x + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Measure the pixel width of a graphic string
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
void MNU_MeasureString(const char* string, short* w, short* h)
|
|
|
|
{
|
|
|
|
short ndx, width, height;
|
|
|
|
char c;
|
|
|
|
short ac;
|
|
|
|
|
|
|
|
if (string[0] == '^')
|
|
|
|
{
|
|
|
|
MNU_MeasureStringLarge(&string[1], w, h);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
width = 0;
|
|
|
|
height = *h;
|
|
|
|
|
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
ac = c - '!' + STARTALPHANUM;
|
|
|
|
if ((ac < STARTALPHANUM || ac > ENDALPHANUM) && c != asc_Space)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c > asc_Space && c < 127)
|
|
|
|
{
|
|
|
|
width += tilesiz[ac].x;
|
|
|
|
if (height < tilesiz[ac].y)
|
|
|
|
height = tilesiz[ac].y;
|
|
|
|
}
|
|
|
|
else if (c == asc_Space)
|
|
|
|
width += 4; // Special case for space char
|
|
|
|
}
|
|
|
|
|
|
|
|
*w = width;
|
|
|
|
*h = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Draw a string using a graphic font
|
|
|
|
//
|
|
|
|
// MenuTextShade and MenuDrawFlags
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
void MNU_DrawString(short x, short y, const char* string, short shade, short pal, int align)
|
|
|
|
{
|
|
|
|
int ndx, offset;
|
|
|
|
char c;
|
|
|
|
short ac;
|
|
|
|
|
|
|
|
if (string[0] == '^')
|
|
|
|
{
|
|
|
|
MNU_DrawStringLarge(x, y, &string[1]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (align > -1)
|
|
|
|
{
|
|
|
|
short w, h;
|
|
|
|
MNU_MeasureString(string, &w, &h);
|
|
|
|
if (align == 0) x -= w / 2;
|
|
|
|
else x -= w;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = x;
|
|
|
|
|
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
ac = c - '!' + STARTALPHANUM;
|
|
|
|
if ((ac < STARTALPHANUM || ac > ENDALPHANUM) && c != asc_Space)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c > asc_Space && c < 127)
|
|
|
|
{
|
|
|
|
rotatesprite(offset << 16, y << 16, MZ, 0, ac, shade, pal, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
|
|
|
|
offset += tilesiz[ac].x;
|
|
|
|
}
|
|
|
|
else if (c == asc_Space)
|
|
|
|
offset += 4; // Special case for space char
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Measure the pixel width of a small font string
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
void MNU_MeasureSmallString(const char* string, short* w, short* h)
|
|
|
|
{
|
|
|
|
short ndx, width, height;
|
|
|
|
char c;
|
|
|
|
short ac;
|
|
|
|
|
|
|
|
width = 0;
|
|
|
|
height = *h;
|
|
|
|
|
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
ac = (c - '!') + 2930;
|
|
|
|
if ((ac < 2930 || ac > 3023) && c != asc_Space)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c > asc_Space && c < 127)
|
|
|
|
{
|
|
|
|
width += tilesiz[ac].x;
|
|
|
|
if (height < tilesiz[ac].y)
|
|
|
|
height = tilesiz[ac].y;
|
|
|
|
}
|
|
|
|
else if (c == asc_Space)
|
|
|
|
width += 4; // Special case for space char
|
|
|
|
}
|
|
|
|
|
|
|
|
*w = width;
|
|
|
|
*h = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Draw a string using a small graphic font
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
void MNU_DrawSmallString(short x, short y, const char* string, short shade, short pal)
|
|
|
|
{
|
|
|
|
int ndx;
|
|
|
|
char c;
|
|
|
|
short ac, offset;
|
|
|
|
|
|
|
|
|
|
|
|
offset = x;
|
|
|
|
|
|
|
|
for (ndx = 0; (c = string[ndx]) != 0; ndx++)
|
|
|
|
{
|
|
|
|
ac = c - '!' + 2930;
|
|
|
|
if ((ac < 2930 || ac > 3023) && c != asc_Space)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c > asc_Space && c < 127)
|
|
|
|
{
|
|
|
|
rotatesprite(offset << 16, y << 16, MZ, 0, ac, shade, pal, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
|
|
|
|
|
|
|
|
offset += tilesiz[ac].x;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (c == asc_Space)
|
|
|
|
{
|
|
|
|
offset += 4; // Special case for space char
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
short GlobInfoStringTime = TEXT_INFO_TIME;
|
2015-05-19 21:58:29 +00:00
|
|
|
void PutStringInfo(PLAYERp pp, const char *string)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (pp-Player != myconnectindex)
|
|
|
|
return;
|
|
|
|
|
2019-10-27 15:53:00 +00:00
|
|
|
if (!hud_messages)
|
2015-05-19 21:54:34 +00:00
|
|
|
return;
|
|
|
|
|
2020-01-23 18:05:09 +00:00
|
|
|
Printf(PRINT_MEDIUM|PRINT_NOTIFY, "%s\n", string); // Put it in the console too
|
2019-12-04 20:35:35 +00:00
|
|
|
if (hud_messages == 1) PutStringInfoLine(pp, string);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void PutStringInfoLine(PLAYERp pp, const char *string)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short x,y;
|
|
|
|
short w,h;
|
|
|
|
|
|
|
|
if (pp-Player != myconnectindex)
|
|
|
|
return;
|
|
|
|
|
|
|
|
MNU_MeasureString(string, &w, &h);
|
|
|
|
|
|
|
|
x = TEXT_XCENTER(w);
|
|
|
|
y = TEXT_INFO_LINE(0);
|
|
|
|
|
|
|
|
// Move lower on this level because of boss meters
|
|
|
|
//if ((Level == 20 && numplayers > 1) || numplayers > 4)
|
|
|
|
// y += 20;
|
|
|
|
//if (numplayers > 1 && numplayers <= 4)
|
|
|
|
// y+= 10;
|
|
|
|
|
|
|
|
PutStringTimer(pp, x, y, string, GlobInfoStringTime);
|
|
|
|
// when printing info line clear the second line
|
|
|
|
//PutStringInfoLine2(pp, "");
|
|
|
|
}
|
|
|
|
|
2019-11-17 17:02:17 +00:00
|
|
|
void pMenuClearTextLine(PLAYERp pp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
pMenuClearTextLineID(pp, ID_TEXT, TEXT_INFO_LINE(0), PRI_FRONT_MAX);
|
|
|
|
pMenuClearTextLineID(pp, ID_TEXT, TEXT_INFO_LINE(1), PRI_FRONT_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TEXT_PLAYER_INFO_TIME (3)
|
|
|
|
#define TEXT_PLAYER_INFO_Y (200 - 40)
|
|
|
|
|
2020-01-22 21:49:51 +00:00
|
|
|
#include "saveable.h"
|
|
|
|
|
|
|
|
static saveable_code saveable_text_code[] =
|
|
|
|
{
|
|
|
|
SAVE_CODE(StringTimer),
|
|
|
|
};
|
|
|
|
|
|
|
|
saveable_module saveable_text =
|
|
|
|
{
|
|
|
|
// code
|
|
|
|
saveable_text_code,
|
|
|
|
SIZ(saveable_text_code),
|
|
|
|
|
|
|
|
// data
|
|
|
|
NULL,0
|
|
|
|
};
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|