1 /****************************************************************************
2 * Copyright (c) 2006,2007 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28
29 /****************************************************************************
30 * Author: Thomas E. Dickey *
31 ****************************************************************************/
32
33 /*
34 * Iterators for terminal databases.
35 */
36
37 #include <curses.priv.h>
38
39 #include <tic.h>
40
41 MODULE_ID("$Id: db_iterator.c,v 1.6 2007/04/22 00:00:26 tom Exp $")
42
43 #define HaveTicDirectory _nc_globals.have_tic_directory
44 #define KeepTicDirectory _nc_globals.keep_tic_directory
45 #define TicDirectory _nc_globals.tic_directory
46
47 /*
48 * Record the "official" location of the terminfo directory, according to
49 * the place where we're writing to, or the normal default, if not.
50 */
NCURSES_EXPORT(const char *)51 NCURSES_EXPORT(const char *)
52 _nc_tic_dir(const char *path)
53 {
54 if (!KeepTicDirectory) {
55 if (path != 0) {
56 TicDirectory = path;
57 HaveTicDirectory = TRUE;
58 } else if (!HaveTicDirectory && use_terminfo_vars()) {
59 char *envp;
60 if ((envp = getenv("TERMINFO")) != 0)
61 return _nc_tic_dir(envp);
62 }
63 }
64 return TicDirectory;
65 }
66
67 /*
68 * Special fix to prevent the terminfo directory from being moved after tic
69 * has chdir'd to it. If we let it be changed, then if $TERMINFO has a
70 * relative path, we'll lose track of the actual directory.
71 */
72 NCURSES_EXPORT(void)
_nc_keep_tic_dir(const char * path)73 _nc_keep_tic_dir(const char *path)
74 {
75 _nc_tic_dir(path);
76 KeepTicDirectory = TRUE;
77 }
78
79 /*
80 * Process the list of :-separated directories, looking for the terminal type.
81 * We don't use strtok because it does not show us empty tokens.
82 */
83 #define ThisDbList _nc_globals.dbi_list
84 #define ThisDbSize _nc_globals.dbi_size
85
86 /*
87 * Cleanup.
88 */
89 NCURSES_EXPORT(void)
_nc_last_db(void)90 _nc_last_db(void)
91 {
92 if (ThisDbList != 0) {
93 FreeAndNull(ThisDbList);
94 }
95 ThisDbSize = 0;
96 }
97
98 /* The TERMINFO_DIRS value, if defined by the configure script, begins with a
99 * ":", which will be interpreted as TERMINFO.
100 */
101 static const char *
next_list_item(const char * source,int * offset)102 next_list_item(const char *source, int *offset)
103 {
104 if (source != 0) {
105 FreeIfNeeded(ThisDbList);
106 ThisDbList = strdup(source);
107 ThisDbSize = strlen(source);
108 }
109
110 if (ThisDbList != 0 && ThisDbSize && *offset < ThisDbSize) {
111 static char system_db[] = TERMINFO;
112 char *result = ThisDbList + *offset;
113 char *marker = strchr(result, NCURSES_PATHSEP);
114
115 /*
116 * Put a null on the marker if a separator was found. Set the offset
117 * to the next position after the marker so we can call this function
118 * again, using the data at the offset.
119 */
120 if (marker == 0) {
121 *offset += strlen(result) + 1;
122 marker = result + *offset;
123 } else {
124 *marker++ = 0;
125 *offset = marker - ThisDbList;
126 }
127 if (*result == 0 && result != (ThisDbList + ThisDbSize))
128 result = system_db;
129 return result;
130 }
131 return 0;
132 }
133
134 #define NEXT_DBD(var, offset) next_list_item((*offset == 0) ? var : 0, offset)
135
136 /*
137 * This is a simple iterator which allows the caller to step through the
138 * possible locations for a terminfo directory. ncurses uses this to find
139 * terminfo files to read.
140 */
141 NCURSES_EXPORT(const char *)
_nc_next_db(DBDIRS * state,int * offset)142 _nc_next_db(DBDIRS * state, int *offset)
143 {
144 const char *result;
145 char *envp;
146
147 while (*state < dbdLAST) {
148 DBDIRS next = (DBDIRS) ((int) (*state) + 1);
149
150 result = 0;
151
152 switch (*state) {
153 case dbdTIC:
154 if (HaveTicDirectory)
155 result = _nc_tic_dir(0);
156 break;
157 #if USE_DATABASE
158 case dbdEnvOnce:
159 if (use_terminfo_vars()) {
160 if ((envp = getenv("TERMINFO")) != 0)
161 result = _nc_tic_dir(envp);
162 }
163 break;
164 case dbdHome:
165 if (use_terminfo_vars()) {
166 result = _nc_home_terminfo();
167 }
168 break;
169 case dbdEnvList:
170 if (use_terminfo_vars()) {
171 if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0)
172 next = *state;
173 }
174 break;
175 case dbdCfgList:
176 #ifdef TERMINFO_DIRS
177 if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0)
178 next = *state;
179 #endif
180 break;
181 case dbdCfgOnce:
182 #ifndef TERMINFO_DIRS
183 result = TERMINFO;
184 #endif
185 break;
186 #endif /* USE_DATABASE */
187 #if USE_TERMCAP
188 case dbdEnvOnce2:
189 if (use_terminfo_vars()) {
190 if ((envp = getenv("TERMCAP")) != 0)
191 result = _nc_tic_dir(envp);
192 }
193 break;
194 case dbdEnvList2:
195 if (use_terminfo_vars()) {
196 if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0)
197 next = *state;
198 }
199 break;
200 case dbdCfgList2:
201 if ((result = NEXT_DBD(TERMPATH, offset)) != 0)
202 next = *state;
203 break;
204 #endif /* USE_TERMCAP */
205 case dbdLAST:
206 break;
207 }
208 if (*state != next) {
209 *state = next;
210 *offset = 0;
211 _nc_last_db();
212 }
213 if (result != 0) {
214 return result;
215 }
216 }
217 return 0;
218 }
219
220 NCURSES_EXPORT(void)
_nc_first_db(DBDIRS * state,int * offset)221 _nc_first_db(DBDIRS * state, int *offset)
222 {
223 *state = dbdTIC;
224 *offset = 0;
225 }
226