ui_data.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "../client.h"
00026 #include "ui_main.h"
00027 #include "ui_internal.h"
00028 #include "ui_nodes.h"
00029 #include "node/ui_node_linechart.h"
00030 #include "node/ui_node_option.h"
00031 
00035 static const char *const ui_sharedDataIDNames[] = {
00036     "", 
00037     "TEXT_STANDARD",
00038     "TEXT_LIST",
00039     "TEXT_LIST2",
00040     "TEXT_UFOPEDIA",
00041     "TEXT_UFOPEDIA_REQUIREMENT",
00042     "TEXT_BUILDINGS",
00043     "TEXT_BUILDING_INFO",
00044     "TEXT_RESEARCH",
00045     "TEXT_POPUP",
00046     "TEXT_POPUP_INFO",
00047     "TEXT_AIRCRAFT_LIST",
00048     "TEXT_AIRCRAFT_INFO",
00049     "TEXT_CAMPAIGN_LIST",
00050     "TEXT_MULTISELECTION",
00051     "TEXT_PRODUCTION_LIST",
00052     "TEXT_PRODUCTION_AMOUNT",
00053     "TEXT_PRODUCTION_INFO",
00054     "TEXT_EMPLOYEE",
00055     "TEXT_MOUSECURSOR_RIGHT",
00056     "TEXT_PRODUCTION_QUEUED",
00057     "TEXT_STATS_BASESUMMARY",
00058     "TEXT_STATS_MISSION",
00059     "TEXT_STATS_BASES",
00060     "TEXT_STATS_NATIONS",
00061     "TEXT_STATS_EMPLOYEES",
00062     "TEXT_STATS_COSTS",
00063     "TEXT_STATS_INSTALLATIONS",
00064     "TEXT_STATS_7",
00065     "TEXT_BASE_LIST",
00066     "TEXT_BASE_INFO",
00067     "TEXT_TRANSFER_LIST",
00068     "TEXT_TRANSFER_LIST_AMOUNT",
00069     "TEXT_TRANSFER_LIST_TRANSFERED",
00070     "TEXT_MOUSECURSOR_PLAYERNAMES",
00071     "TEXT_CARGO_LIST",
00072     "TEXT_CARGO_LIST_AMOUNT",
00073     "TEXT_UFOPEDIA_MAILHEADER",
00074     "TEXT_UFOPEDIA_MAIL",
00075     "TEXT_MARKET_NAMES",
00076     "TEXT_MARKET_STORAGE",
00077     "TEXT_MARKET_MARKET",
00078     "TEXT_MARKET_PRICES",
00079     "TEXT_CHAT_WINDOW",
00080     "TEXT_AIREQUIP_1",
00081     "TEXT_AIREQUIP_2",
00082     "TEXT_BASEDEFENCE_LIST",
00083     "TEXT_TIPOFTHEDAY",
00084     "TEXT_GENERIC",
00085     "TEXT_XVI",
00086     "TEXT_MOUSECURSOR_TOP",
00087     "TEXT_MOUSECURSOR_BOTTOM",
00088     "TEXT_MOUSECURSOR_LEFT",
00089     "TEXT_MESSAGEOPTIONS",
00090     "TEXT_UFORECOVERY_NATIONS",
00091     "TEXT_UFORECOVERY_UFOYARDS",
00092     "TEXT_UFORECOVERY_CAPACITIES",
00093     "TEXT_MATERIAL_STAGES",
00094     "TEXT_IRCCONTENT",
00095     "TEXT_IRCUSERS",
00096     "TEXT_MULTIPLAYER_USERLIST",
00097     "TEXT_MULTIPLAYER_USERTEAM",
00098     "TEXT_ITEMDESCRIPTION",
00099 
00100     "OPTION_LANGUAGES",
00101     "OPTION_JOYSTICKS",
00102     "OPTION_VIDEO_RESOLUTIONS",
00103     "OPTION_SINGLEPLAYER_SKINS",
00104     "OPTION_MULTIPLAYER_SKINS",
00105     "OPTION_UFOPEDIA",
00106     "OPTION_UFOS",
00107     "OPTION_DROPSHIPS",
00108     "OPTION_BASELIST",
00109     "OPTION_TEAMDEFS",
00110 
00111     "LINESTRIP_FUNDING",
00112     "LINESTRIP_COLOR"
00113 };
00114 CASSERT(lengthof(ui_sharedDataIDNames) == UI_MAX_DATAID);
00115 
00120 int UI_GetDataIDByName (const char* name)
00121 {
00122     int num;
00123     for (num = 0; num < UI_MAX_DATAID; num++)
00124         if (!strcmp(name, ui_sharedDataIDNames[num]))
00125             return num;
00126 
00127     return -1;
00128 }
00129 
00134 void UI_RegisterText (int dataId, const char *text)
00135 {
00136     UI_ResetData(dataId);
00137 
00138     if (!text)
00139         return;
00140 
00141     ui_global.sharedData[dataId].type = UI_SHARED_TEXT;
00142     ui_global.sharedData[dataId].data.text = text;
00143     ui_global.sharedData[dataId].versionId++;
00144 }
00145 
00150 void UI_RegisterLinkedListText (int dataId, linkedList_t *text)
00151 {
00153     if (ui_global.sharedData[dataId].type == UI_SHARED_LINKEDLISTTEXT && ui_global.sharedData[dataId].data.linkedListText == text) {
00154         ui_global.sharedData[dataId].versionId++;
00155         return;
00156     }
00157     UI_ResetData(dataId);
00158     ui_global.sharedData[dataId].type = UI_SHARED_LINKEDLISTTEXT;
00159     ui_global.sharedData[dataId].data.linkedListText = text;
00160     ui_global.sharedData[dataId].versionId++;
00161 }
00162 
00163 const char *UI_GetText (int textId)
00164 {
00165     if (ui_global.sharedData[textId].type != UI_SHARED_TEXT)
00166         return NULL;
00167     return ui_global.sharedData[textId].data.text;
00168 }
00169 
00170 int UI_GetDataVersion (int textId)
00171 {
00172     return ui_global.sharedData[textId].versionId;
00173 }
00174 
00181 static void UI_InitOption (uiNode_t* option, const char* label, const char* value)
00182 {
00183     assert(option);
00184     assert(option->behaviour == ui_optionBehaviour);
00185     Q_strncpyz(OPTIONEXTRADATA(option).label, label, sizeof(OPTIONEXTRADATA(option).label));
00186     Q_strncpyz(OPTIONEXTRADATA(option).value, value, sizeof(OPTIONEXTRADATA(option).value));
00187 }
00188 
00197 uiNode_t* UI_AddOption (uiNode_t** tree, const char* name, const char* label, const char* value)
00198 {
00199     uiNode_t *last;
00200     uiNode_t *option;
00201     assert(tree != NULL);
00202 
00203     option = UI_AllocNode(name, "option", qtrue);
00204     UI_InitOption(option, label, value);
00205 
00206     /* append the option */
00207     last = *tree;
00208     if (last != NULL) {
00209         while (last->next)
00210             last = last->next;
00211     }
00212 
00213     if (last)
00214         last->next = option;
00215     else
00216         *tree = option;
00217 
00218     return option;
00219 }
00220 
00226 static void UI_DeleteOption (uiNode_t* tree)
00227 {
00228     while (tree) {
00229         uiNode_t* del = tree;
00230         tree = tree->next;
00231         UI_DeleteNode(del);
00232     }
00233 }
00234 
00238 void UI_ResetData (int dataId)
00239 {
00240     assert(dataId < UI_MAX_DATAID);
00241     assert(dataId >= 0);
00242 
00243     switch (ui_global.sharedData[dataId].type) {
00244     case UI_SHARED_LINKEDLISTTEXT:
00245         LIST_Delete(&ui_global.sharedData[dataId].data.linkedListText);
00246         break;
00247     case UI_SHARED_OPTION:
00248         if (_Mem_AllocatedInPool(com_genericPool, ui_global.sharedData[dataId].data.option)) {
00249             UI_DeleteOption(ui_global.sharedData[dataId].data.option);
00250         }
00251         break;
00252     default:
00253         break;
00254     }
00255 
00256     ui_global.sharedData[dataId].type = UI_SHARED_NONE;
00257     ui_global.sharedData[dataId].data.text = NULL;
00258     ui_global.sharedData[dataId].versionId++;
00259 }
00260 
00266 static uiNode_t *UI_OptionNodeRemoveHigherOption (uiNode_t **option)
00267 {
00268     uiNode_t *prev = *option;
00269     uiNode_t *prevfind = NULL;
00270     uiNode_t *search = (*option)->next;
00271     const char *label = OPTIONEXTRADATA(*option).label;
00272 
00273     if (label[0] == '_')
00274         label = _(label + 1);
00275 
00276     /* search the smaller element */
00277     while (search) {
00278         const char *searchlabel = OPTIONEXTRADATA(search).label;
00279 
00280         if (searchlabel[0] == '_')
00281             searchlabel = _(searchlabel + 1);
00282 
00283         if (strcmp(label, searchlabel) < 0) {
00284             prevfind = prev;
00285             label = searchlabel;
00286         }
00287         prev = search;
00288         search = search->next;
00289     }
00290 
00291     /* remove the first element */
00292     if (prevfind == NULL) {
00293         uiNode_t *tmp = *option;
00294         *option = (*option)->next;
00295         return tmp;
00296     } else {
00297         uiNode_t *tmp = prevfind->next;
00298         prevfind->next = tmp->next;
00299         return tmp;
00300     }
00301 }
00302 
00306 void UI_SortOptions (uiNode_t **first)
00307 {
00308     uiNode_t *option;
00309 
00310     /* unlink the unsorted list */
00311     option = *first;
00312     if (option == NULL)
00313         return;
00314     *first = NULL;
00315 
00316     /* construct a sorted list */
00317     while (option) {
00318         uiNode_t *element;
00319         element = UI_OptionNodeRemoveHigherOption(&option);
00320         element->next = *first;
00321         *first = element;
00322     }
00323 }
00324 
00330 void UI_UpdateInvisOptions (uiNode_t *option, const linkedList_t *stringList)
00331 {
00332     if (option == NULL || stringList == NULL)
00333         return;
00334 
00335     while (option) {
00336         if (LIST_ContainsString(stringList, option->name))
00337             option->invis = qfalse;
00338         else
00339             option->invis = qtrue;
00340         option = option->next;
00341     }
00342 }
00343 
00344 void UI_RegisterOption (int dataId, uiNode_t *option)
00345 {
00347     if (ui_global.sharedData[dataId].type == UI_SHARED_OPTION && ui_global.sharedData[dataId].data.option == option) {
00348         ui_global.sharedData[dataId].versionId++;
00349         return;
00350     }
00351     UI_ResetData(dataId);
00352     ui_global.sharedData[dataId].type = UI_SHARED_OPTION;
00353     ui_global.sharedData[dataId].data.option = option;
00354     ui_global.sharedData[dataId].versionId++;
00355 }
00356 
00357 void UI_RegisterLineStrip (int dataId, lineStrip_t *lineStrip)
00358 {
00359     UI_ResetData(dataId);
00360     ui_global.sharedData[dataId].type = UI_SHARED_LINESTRIP;
00361     ui_global.sharedData[dataId].data.lineStrip = lineStrip;
00362     ui_global.sharedData[dataId].versionId++;
00363 }
00364 
00365 uiNode_t *UI_GetOption (int dataId)
00366 {
00367     if (ui_global.sharedData[dataId].type == UI_SHARED_OPTION) {
00368         return ui_global.sharedData[dataId].data.option;
00369     }
00370     return NULL;
00371 }
00372 
00379 static uiNode_t* UI_FindOptionAtIndex (int index, uiNode_t* option, uiOptionIterator_t* iterator)
00380 {
00381     while (option) {
00382         assert(option->behaviour == ui_optionBehaviour);
00383         if (option->invis) {
00384             option = option->next;
00385             continue;
00386         }
00387 
00388         /* we are on the right element */
00389         if (index == 0) {
00390             iterator->option = option;
00391             return option;
00392         }
00393 
00394         /* not the parent */
00395         index--;
00396 
00397         if (OPTIONEXTRADATA(option).collapsed) {
00398             option = option->next;
00399             continue;
00400         }
00401 
00402         /* its a child */
00403         if (index < OPTIONEXTRADATA(option).childCount) {
00404             if (iterator->depthPos >= MAX_DEPTH_OPTIONITERATORCACHE)
00405                 assert(qfalse);
00406             iterator->depthCache[iterator->depthPos] = option;
00407             iterator->depthPos++;
00408             return UI_FindOptionAtIndex(index, option->firstChild, iterator);
00409         }
00410         index -= OPTIONEXTRADATA(option).childCount;
00411         option = option->next;
00412     }
00413 
00414     iterator->option = NULL;
00415     return NULL;
00416 }
00417 
00435 uiNode_t* UI_InitOptionIteratorAtIndex (int index, uiNode_t* option, uiOptionIterator_t* iterator)
00436 {
00437     assert(option == NULL || option->behaviour == ui_optionBehaviour);
00438     memset(iterator, 0, sizeof(*iterator));
00439     iterator->skipCollapsed = qtrue;
00440     iterator->skipInvisible = qtrue;
00441     return UI_FindOptionAtIndex(index, option, iterator);
00442 }
00443 
00448 uiNode_t* UI_OptionIteratorNextOption (uiOptionIterator_t* iterator)
00449 {
00450     uiNode_t* option;
00451 
00452     option = iterator->option;
00453     assert(iterator->depthPos < MAX_DEPTH_OPTIONITERATORCACHE);
00454     iterator->depthCache[iterator->depthPos] = option;
00455     iterator->depthPos++;
00456 
00457     if (OPTIONEXTRADATA(option).collapsed && iterator->skipCollapsed)
00458         option = NULL;
00459     else
00460         option = option->firstChild;
00461 
00462     while (qtrue) {
00463         while (option) {
00464             if (!option->invis || !iterator->skipInvisible) {
00465                 iterator->option = option;
00466                 return option;
00467             }
00468             option = option->next;
00469         }
00470         if (iterator->depthPos == 0)
00471             break;
00472         iterator->depthPos--;
00473         option = iterator->depthCache[iterator->depthPos]->next;
00474     }
00475 
00476     iterator->option = NULL;
00477     return NULL;
00478 }
00479 
00486 uiNode_t* UI_FindOptionByValue (uiOptionIterator_t* iterator, const char* value)
00487 {
00488     while (iterator->option) {
00489         assert(iterator->option->behaviour == ui_optionBehaviour);
00490         if (!strcmp(OPTIONEXTRADATA(iterator->option).value, value))
00491             return iterator->option;
00492         UI_OptionIteratorNextOption(iterator);
00493     }
00494     return NULL;
00495 }
00496 
00503 int UI_FindOptionPosition (uiOptionIterator_t* iterator, const uiNode_t* option)
00504 {
00505     int i = 0;
00506     while (iterator->option) {
00507         if (iterator->option == option)
00508             return i;
00509         i++;
00510         UI_OptionIteratorNextOption(iterator);
00511     }
00512     return -1;
00513 }
00514 
00520 static void UI_ResetData_f (void)
00521 {
00522     if (Cmd_Argc() == 2) {
00523         const char *dataId = Cmd_Argv(1);
00524         const int id = UI_GetDataIDByName(dataId);
00525         if (id == -1)
00526             Com_Printf("%s: invalid data ID: %s\n", Cmd_Argv(0), dataId);
00527         else
00528             UI_ResetData(id);
00529     } else {
00530         int i;
00531         for (i = 0; i < UI_MAX_DATAID; i++)
00532             UI_ResetData(i);
00533     }
00534 }
00535 
00540 void UI_InitData (void)
00541 {
00542     Cmd_AddCommand("mn_datareset", UI_ResetData_f, "Resets memory and data used by a UI data id");
00543 }

Generated by  doxygen 1.6.2