diff --git a/include/cl_slist.h b/include/cl_slist.h new file mode 100644 index 0000000..8ffd4a7 --- /dev/null +++ b/include/cl_slist.h @@ -0,0 +1,53 @@ +/* + cl_slist.h + + serverlist addressbook interface + + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + Author: Brian Koropoff + Date: 03 May 2000 + + 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 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ +#include +#define MAX_SERVER_LIST 256 + +typedef struct { + char *server; + char *description; + int ping; +} server_entry_t; + +extern server_entry_t slist[MAX_SERVER_LIST]; + +void Server_List_Init(void); +void Server_List_Shutdown(void); +int Server_List_Set(int i,char *addr,char *desc); +int Server_List_Reset_NoFree(int i); +int Server_List_Reset(int i); +void Server_List_Switch(int a,int b); +int Server_List_Len(void); +int Server_List_Load(FILE *f); +int Server_List_Save(FILE *f); +char *gettokstart (char *str, int req, char delim); +int gettoklen(char *str, int req, char delim); diff --git a/source/Makefile.am b/source/Makefile.am index dd88ee5..ab8d942 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -16,7 +16,7 @@ client_SOURCES= cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c cl_main.c \ cl_math.S cl_misc.c cl_parse.c cl_pred.c cl_tent.c cl_cam.c \ snd_oss.c sys_linux.c cd_linux.c r_view.c wad.c snd_dma.c \ snd_mem.c snd_mix.c snd_mixa.S skin.c sbar.c nonintel.c \ - menu.c keys.c console.c sys_x86.S + menu.c keys.c console.c sys_x86.S cl_slist.c soft_SOURCES= cl_model.c cl_trans.c d_edge.c d_fill.c d_init.c d_modech.c \ d_part.c d_polyse.c d_scan.c d_sky.c d_sprite.c d_surf.c \ d_vars.c d_zpoint.c draw.c r_aclip.c r_alias.c r_bsp.c \ diff --git a/source/cl_main.c b/source/cl_main.c index 358869f..9c31942 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -39,6 +39,7 @@ #else #include #endif +#include #include "sys.h" #include "quakedef.h" @@ -1160,6 +1161,7 @@ CL_Init */ void CL_Init (void) { + FILE *servlist; /* extern cvar_t baseskin; CVAR_FIXME */ extern cvar_t *baseskin; @@ -1184,6 +1186,13 @@ void CL_Init (void) CL_InitPrediction (); CL_InitCam (); Pmove_Init (); + Server_List_Init (); //Init server list + + if ((servlist = fopen("./servers.txt","r"))) { + Server_List_Load(servlist); + fclose(servlist); + } + // // register our commands @@ -1744,6 +1753,8 @@ void Host_Shutdown(void) } isdown = true; + Server_List_Shutdown (); + Host_WriteConfiguration (); CDAudio_Shutdown (); diff --git a/source/cl_slist.c b/source/cl_slist.c new file mode 100644 index 0000000..5e030b3 --- /dev/null +++ b/source/cl_slist.c @@ -0,0 +1,217 @@ +/* + cl_slist.c + + serverlist addressbook + + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + Author: Brian Koropoff + Date: 03 May 2000 + + 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 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include + +//Better watch out for buffer overflows +server_entry_t slist[MAX_SERVER_LIST]; + +void Server_List_Init(void) { // Do this or everything else will sig11 + int i; + for(i=0;i < MAX_SERVER_LIST;i++) { + slist[i].server = '\0'; + slist[i].description = '\0'; + slist[i].ping = 0; + } +} + + +void Server_List_Shutdown(void) { // I am the liberator of memory. + int i; + FILE *f; + if (!(f = fopen("./servers.txt","w"))) { + Con_Printf("Couldn't open servers.txt.\n"); + return; + } + Server_List_Save(f); + fclose(f); + for(i=0;i < MAX_SERVER_LIST;i++) { + if (slist[i].server) + free(slist[i].server); + if (slist[i].description) + free(slist[i].description); + } +} + + +int Server_List_Set(int i,char *addr,char *desc) { + int len; + if (i < MAX_SERVER_LIST && i >= 0) { + if (slist[i].server) // (Re)allocate memory first + free(slist[i].server); + if (slist[i].description) + free(slist[i].description); + len = strlen(desc); + slist[i].server = malloc(strlen(addr) + 1); + slist[i].description = malloc(len + 1); + strcpy(slist[i].server,addr); + strcpy(slist[i].description,desc); + return 0; // Yay, we haven't segfaulted yet. + } + return 1; // Out of range +} +int Server_List_Reset_NoFree (int i) { //NEVER USE THIS UNLESS REALLY NEEDED + if (i < MAX_SERVER_LIST && i >= 0) { + slist[i].server = '\0'; + slist[i].description = '\0'; + slist[i].ping = 0; + return 0; + } + return 1; +} + +int Server_List_Reset (int i) { + if (i < MAX_SERVER_LIST && i >= 0) { + if (slist[i].server) + free(slist[i].server); + if (slist[i].description) + free(slist[i].description); + slist[i].server = '\0'; + slist[i].description = '\0'; + slist[i].ping = 0; + return 0; + } + return 1; +} + +void Server_List_Switch(int a,int b) { + server_entry_t temp; + memcpy(&temp,&slist[a],sizeof(temp)); + memcpy(&slist[a],&slist[b],sizeof(temp)); + memcpy(&slist[b],&temp,sizeof(temp)); +} + +int Server_List_Len (void) { + int i; + for (i = 0; i < MAX_SERVER_LIST && slist[i].server;i++) + ; + return i; +} + +int Server_List_Load (FILE *f) { // This could get messy + int serv = 0; + char line[256]; /* Long lines get truncated. */ + int c = ' '; /* int so it can be compared to EOF properly*/ + char *start; + int len; + int i; + char *addr; + + // Init again to clear the list +// Server_List_Shutdown(); +// Server_List_Init(); + while (serv < MAX_SERVER_LIST) { + //First, get a line + i = 0; + c = ' '; + while (c != '\n' && c != EOF) { + c = getc(f); + if (i < 255) { + line[i] = c; + i++; + } + } + line[i - 1] = '\0'; // Now we can parse it + if ((start = gettokstart(line,1,' ')) != NULL) { + len = gettoklen(line,1,' '); + addr = malloc(len + 1); + strncpy(addr,&line[0],len); + addr[len] = '\0'; + if ((start = gettokstart(line,2,' '))) { + Server_List_Set(serv,addr,start); + } + else { + Server_List_Set(serv,addr,"Unknown"); + } + serv++; + } + if (c == EOF) // We're done + return 0; + } + return 0; +} + +int Server_List_Save(FILE *f) { + int i; + for(i=0;i < MAX_SERVER_LIST;i++) { + if (slist[i].server) + fprintf(f,"%s %s\n", + slist[i].server, + slist[i].description); + } + return 0; +} +char *gettokstart (char *str, int req, char delim) { + char *start = str; + + int tok = 1; + + while (*start == delim) { + start++; + } + if (*start == '\0') + return '\0'; + while (tok < req) { //Stop when we get to the requested token + if (*++start == delim) { //Increment pointer and test + while (*start == delim) { //Get to next token + start++; + } + tok++; + } + if (*start == '\0') { + return '\0'; + } + } + return start; +} + +int gettoklen (char *str, int req, char delim) { + char *start = 0; + + int len = 0; + + start = gettokstart(str,req,delim); + if (start == '\0') { + return 0; + } + while (*start != delim && *start != '\0') { + start++; + len++; + } + return len; +} diff --git a/source/menu.c b/source/menu.c index c9a09a6..0152734 100644 --- a/source/menu.c +++ b/source/menu.c @@ -34,19 +34,19 @@ #ifdef _WIN32 #include "winquake.h" #endif +#include void (*vid_menudrawfn)(void); void (*vid_menukeyfn)(int key); -enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state; +enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_sedit} m_state; void M_Menu_Main_f (void); void M_Menu_SinglePlayer_f (void); void M_Menu_Load_f (void); void M_Menu_Save_f (void); void M_Menu_MultiPlayer_f (void); - void M_Menu_Setup_f (void); - void M_Menu_Net_f (void); + void M_Menu_SEdit_f (void); void M_Menu_Options_f (void); void M_Menu_Keys_f (void); void M_Menu_Video_f (void); @@ -275,6 +275,8 @@ void M_ToggleMenu_f (void) if (key_dest == key_console) { Con_ToggleConsole_f (); + if (key_dest == key_console) //Still suck on console? + M_Menu_Main_f (); } else { @@ -1133,32 +1135,293 @@ void M_SinglePlayer_Key (key) { m_state = m_main; } +#define MENU_X 50 +#define MENU_Y 30 +#define STAT_X 50 +#define STAT_Y 122 + +int m_multip_cursor=0; +int m_multip_mins=0; +int m_multip_maxs=10; +int m_multip_horiz; + void M_Menu_MultiPlayer_f (void) { + key_dest = key_menu; + m_entersound = true; m_state = m_multiplayer; + m_multip_horiz = 0; } void M_MultiPlayer_Draw (void) { - qpic_t *p; + int serv; + int line = 1; + qpic_t *p; + //int f; - M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); -// M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); - p = Draw_CachePic ("gfx/p_multi.lmp"); - M_DrawPic ( (320-p->width)/2, 4, p); -// M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") ); - - M_DrawTextBox (46, 8*8, 27, 9); - M_PrintWhite (72, 10*8, "If you want to find QW "); - M_PrintWhite (72, 11*8, "games, head on over to: "); - M_Print (72, 12*8, " www.quakeworld.net "); - M_PrintWhite (72, 13*8, " or "); - M_Print (72, 14*8, " www.quakespy.com "); - M_PrintWhite (72, 15*8, "For pointers on getting "); - M_PrintWhite (72, 16*8, " started! "); + M_DrawTransPic(16,4,Draw_CachePic("gfx/qplaque.lmp")); + p = Draw_CachePic("gfx/p_multi.lmp"); + M_DrawPic((320-p->width)/2,4,p); + + if (!(slist[0].server)) { + M_DrawTextBox(60,80,23,4); + M_PrintWhite(110,12*8,"No server list"); + M_PrintWhite(140,13*8,"found."); + return; + } + M_DrawTextBox(STAT_X,STAT_Y,23,4); + //M_DrawTextBox(STAT_X+96,STAT_Y+38,12,3); + M_DrawTextBox(STAT_X,STAT_Y+38,23,3); + M_DrawTextBox(MENU_X,MENU_Y,23,(m_multip_maxs - m_multip_mins)+1); + for (serv = m_multip_mins; serv <= m_multip_maxs; serv++) { + if (slist[serv].server) { + M_Print(MENU_X+18,line*8+MENU_Y, + va("%1.21s", + strlen(slist[serv].description) <= m_multip_horiz ? "" : slist[serv].description+m_multip_horiz)); + line++; + } + } + M_PrintWhite(STAT_X+18,STAT_Y+16,"IP/Hostname:"); + M_Print(STAT_X+18,STAT_Y+24,slist[m_multip_cursor].server); + M_DrawCharacter(MENU_X+8,(m_multip_cursor - m_multip_mins + 1) * 8+MENU_Y, + 12+((int)(realtime*4)&1)); + //f = (int)(realtime * 10) % 6; + //M_PrintWhite(STAT_X+118,STAT_Y+58,"uakeforge!"); + //M_DrawTransPic(STAT_X+105,STAT_Y+48,Draw_CachePic(va("gfx/menudot%i.lmp",f+1))); } void M_MultiPlayer_Key (key) { - if (key == K_ESCAPE || key==K_ENTER) +// server_entry_t *pt; + if (!(slist[0].server) && key != K_ESCAPE && key != K_INS) + return; + switch(key) { + case K_ESCAPE: + M_Menu_Main_f(); + break; + case KP_DOWNARROW: + case K_DOWNARROW: + S_LocalSound("misc/menu1.wav"); + if (m_multip_cursor < (MAX_SERVER_LIST-1) && slist[m_multip_cursor+1].server) { + m_multip_cursor++; + } + break; + case KP_UPARROW: + case K_UPARROW: + S_LocalSound("misc/menu1.wav"); + if (m_multip_cursor > 0) { + m_multip_cursor--; + } + break; + case K_PGUP: + S_LocalSound("misc/menu1.wav"); + m_multip_cursor -= (m_multip_maxs - m_multip_mins); + if (m_multip_cursor < 0) + m_multip_cursor = 0; + break; + case K_PGDN: + S_LocalSound("misc/menu1.wav"); + m_multip_cursor += (m_multip_maxs - m_multip_mins); + if (m_multip_cursor >= MAX_SERVER_LIST) + m_multip_cursor = MAX_SERVER_LIST - 1; + while (!(slist[m_multip_cursor].server)) + m_multip_cursor--; + break; + case K_RIGHTARROW: + S_LocalSound("misc/menu1.wav"); + if (m_multip_horiz < 256) + m_multip_horiz++; + break; + case K_LEFTARROW: + S_LocalSound("misc/menu1.wav"); + if (m_multip_horiz > 0 ) + m_multip_horiz--; + break; + case K_ENTER: m_state = m_main; + M_ToggleMenu_f(); + CL_Disconnect(); + strncpy(cls.servername,slist[m_multip_cursor].server,sizeof(cls.servername)-1); + CL_BeginServerConnect(); + break; + case 'e': + case 'E': + M_Menu_SEdit_f(); + break; + case K_INS: + S_LocalSound("misc/menu2.wav"); + if (Server_List_Len() < (MAX_SERVER_LIST-1)) { + memmove(&slist[m_multip_cursor+1], + &slist[m_multip_cursor], + (Server_List_Len() - m_multip_cursor)*sizeof(slist[0])); + Server_List_Reset_NoFree(m_multip_cursor); + Server_List_Set(m_multip_cursor,"127.0.0.1",""); + } + break; + case K_DEL: + S_LocalSound("misc/menu2.wav"); + if (Server_List_Len() > 0) { + free(slist[m_multip_cursor].server); + free(slist[m_multip_cursor].description); + if (Server_List_Len()-1 == m_multip_cursor) { + Server_List_Reset_NoFree(m_multip_cursor); + m_multip_cursor = !m_multip_cursor ? 0 : m_multip_cursor-1; + + } + else { + memmove(&slist[m_multip_cursor], + &slist[m_multip_cursor+1], + (Server_List_Len()-m_multip_cursor-1) * sizeof(slist[0])); + Server_List_Reset_NoFree(Server_List_Len()-1); + } + } + break; + case ']': + case '}': + S_LocalSound("misc/menu1.wav"); + if (m_multip_cursor != Server_List_Len() - 1) { + Server_List_Switch(m_multip_cursor,m_multip_cursor+1); + m_multip_cursor++; + } + break; + case '[': + case '{': + S_LocalSound("misc/menu1.wav"); + if (m_multip_cursor) { + Server_List_Switch(m_multip_cursor,m_multip_cursor-1); + m_multip_cursor--; + } + break; + default: + break; + } + if (m_multip_cursor < m_multip_mins) { + m_multip_maxs -= (m_multip_mins - m_multip_cursor); + m_multip_mins = m_multip_cursor; + } + if (m_multip_cursor > m_multip_maxs) { + m_multip_mins += (m_multip_cursor - m_multip_maxs); + m_multip_maxs = m_multip_cursor; + } +} +#define SERV_X 60 +#define SERV_Y 64 +#define DESC_X 60 +#define DESC_Y 40 +#define SERV_L 22 +#define DESC_L 22 + +char serv[256]; +char desc[256]; +int serv_max; +int serv_min; +int desc_max; +int desc_min; +int sedit_state; + +void M_Menu_SEdit_f (void) { + key_dest = key_menu; + m_entersound = true; + m_state = m_sedit; + sedit_state = 0; + strncpy(serv,slist[m_multip_cursor].server,255); + serv[strlen(slist[m_multip_cursor].server) + 1] = 0; + strncpy(desc,slist[m_multip_cursor].description,255); + desc[strlen(slist[m_multip_cursor].description) + 1] = 0; + serv_max = strlen(serv) > SERV_L ? strlen(serv) : SERV_L; + serv_min = serv_max - (SERV_L); + desc_max = strlen(desc) > DESC_L ? strlen(desc) : DESC_L; + desc_min = desc_max - (DESC_L); +} + +void M_SEdit_Draw (void) { + qpic_t *p; + + M_DrawTransPic(16,4,Draw_CachePic("gfx/qplaque.lmp")); + p = Draw_CachePic("gfx/p_multi.lmp"); + M_DrawPic((320-p->width)/2,4,p); + + M_DrawTextBox(SERV_X,SERV_Y,23,1); + M_DrawTextBox(DESC_X,DESC_Y,23,1); + M_PrintWhite(SERV_X,SERV_Y-4,"Hostname/IP:"); + M_PrintWhite(DESC_X,DESC_Y-4,"Description:"); + M_Print(SERV_X+9,SERV_Y+8,va("%1.22s",serv+serv_min)); + M_Print(DESC_X+9,DESC_Y+8,va("%1.22s",desc+desc_min)); + if (sedit_state == 0) + M_DrawCharacter(SERV_X+9+8*(strlen(serv)-serv_min), + SERV_Y+8,10+((int)(realtime*4)&1)); + if (sedit_state == 1) + M_DrawCharacter(DESC_X+9+8*(strlen(desc)-desc_min), + DESC_Y+8,10+((int)(realtime*4)&1)); +} + +void M_SEdit_Key (int key) { + int l; + switch (key) { + case K_ESCAPE: + M_Menu_MultiPlayer_f (); + break; + case K_ENTER: + Server_List_Set(m_multip_cursor,serv,desc); + M_Menu_MultiPlayer_f (); + break; + case K_UPARROW: + S_LocalSound("misc/menu1.wav"); + sedit_state = sedit_state == 0 ? 1 : 0; + break; + case K_DOWNARROW: + S_LocalSound("misc/menu1.wav"); + sedit_state = sedit_state == 1 ? 0 : 1; + break; + case K_BACKSPACE: + switch (sedit_state) { + case 0: + if ((l = strlen(serv))) + serv[--l] = 0; + if (strlen(serv)-6 < serv_min && serv_min) { + serv_min--; + serv_max--; + } + break; + case 1: + if ((l = strlen(desc))) + desc[--l] = 0; + if (strlen(desc)-6 < desc_min && desc_min) { + desc_min--; + desc_max--; + } + break; + default: + break; + } + break; + default: + if (key < 32 || key > 127) + break; + switch(sedit_state) { + case 0: + l = strlen(serv); + if (l < 254) { + serv[l+1] = 0; + serv[l] = key; + } + if (strlen(serv) > serv_max) { + serv_min++; + serv_max++; + } + break; + case 1: + l = strlen(desc); + if (l < 254) { + desc[l+1] = 0; + desc[l] = key; + } + if (strlen(desc) > desc_max) { + desc_min++; + desc_max++; + } + break; + } + break; + } } void M_Quit_Draw (void) @@ -1336,8 +1599,11 @@ void M_Draw (void) // M_Search_Draw (); break; - case m_slist: +// case m_slist: // M_ServerList_Draw (); +// break; + case m_sedit: + M_SEdit_Draw (); break; } @@ -1428,9 +1694,12 @@ void M_Keydown (int key) // M_Search_Key (key); break; - case m_slist: +// case m_slist: // M_ServerList_Key (key); - return; +// return; + case m_sedit: + M_SEdit_Key (key); + break; } }