1 /**********************************************************************
2  Freeciv - Copyright (C) 2005 The Freeciv Team
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 #ifdef HAVE_CONFIG_H
14 #include <fc_config.h>
15 #endif
16 
17 #include <unistd.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 
21 /* utility */
22 #include "log.h"
23 #include "mem.h"
24 #include "shared.h"
25 #include "string_vector.h"
26 #include "support.h"
27 
28 /* client/include */
29 #include "themes_g.h"
30 
31 /* client */
32 #include "themes_common.h"
33 
34 /***************************************************************************
35   A theme is a portion of client data, which for following reasons should
36   be separated from a tileset:
37   - Theme is not only graphic related
38   - Theme can be changed independently from tileset
39   - Theme implementation is gui specific and most themes can not be shared
40     between different guis.
41   Theme is recognized by its name.
42 
43   Theme is stored in a directory called like the theme. The directory contains
44   some data files. Each gui defines its own format in the
45   get_useable_themes_in_directory() function.
46 ****************************************************************************/
47 
48 /* A directory containing a list of usable themes */
49 struct theme_directory {
50   /* Path on the filesystem */
51   char *path;
52   /* Array of theme names */
53   char **themes;
54   /* Themes array length */
55   int num_themes;
56 };
57 
58 /* List of all directories with themes */
59 static int num_directories;
60 struct theme_directory *directories;
61 
62 /****************************************************************************
63   Initialized themes data
64 ****************************************************************************/
init_themes(void)65 void init_themes(void)
66 {
67   int i;
68 
69   /* get GUI-specific theme directories */
70   char **gui_directories =
71       get_gui_specific_themes_directories(&num_directories);
72 
73   directories =
74       fc_malloc(sizeof(struct theme_directory) * num_directories);
75 
76   for (i = 0; i < num_directories; i++) {
77     directories[i].path = gui_directories[i];
78 
79     /* get useable themes in this directory */
80     directories[i].themes =
81 	get_useable_themes_in_directory(directories[i].path,
82 					&(directories[i].num_themes));
83   }
84   free(gui_directories);
85 }
86 
87 /****************************************************************************
88   Return a static string vector of useable theme names.
89 ****************************************************************************/
get_themes_list(const struct option * poption)90 const struct strvec *get_themes_list(const struct option *poption)
91 {
92   static struct strvec *themes_list = NULL;
93 
94   if (NULL == themes_list) {
95     int i, j, k;
96 
97     themes_list = strvec_new();
98     for (i = 0; i < num_directories; i++) {
99       for (j = 0; j < directories[i].num_themes; j++) {
100         for (k = 0; k < strvec_size(themes_list); k++) {
101           if (strcmp(strvec_get(themes_list, k),
102                      directories[i].themes[j]) == 0) {
103             break;
104           }
105         }
106         if (k == strvec_size(themes_list)) {
107           strvec_append(themes_list, directories[i].themes[j]);
108         }
109       }
110     }
111   }
112 
113   return themes_list;
114 }
115 
116 /****************************************************************************
117   Loads a theme with the given name. First matching directory will be used.
118   If there's no such theme the function returns FALSE.
119 ****************************************************************************/
load_theme(const char * theme_name)120 bool load_theme(const char *theme_name)
121 {
122   int i, j;
123   for (i = 0; i < num_directories; i++) {
124     for (j = 0; j < directories[i].num_themes; j++) {
125       if (strcmp(theme_name, directories[i].themes[j]) == 0) {
126 	gui_load_theme(directories[i].path, directories[i].themes[j]);
127 	return TRUE;
128       }
129     }
130   }
131   return FALSE;
132 }
133 
134 /****************************************************************************
135   Wrapper for load_theme. It's is used by local options dialog
136 ****************************************************************************/
theme_reread_callback(struct option * poption)137 void theme_reread_callback(struct option *poption)
138 {
139   const char *theme_name = option_str_get(poption);
140 
141   fc_assert_ret(NULL != theme_name && theme_name[0] != '\0');
142   load_theme(theme_name);
143 }
144