1166124Srafan/**************************************************************************** 2174993Srafan * Copyright (c) 2006,2007 Free Software Foundation, Inc. * 3166124Srafan * * 4166124Srafan * Permission is hereby granted, free of charge, to any person obtaining a * 5166124Srafan * copy of this software and associated documentation files (the * 6166124Srafan * "Software"), to deal in the Software without restriction, including * 7166124Srafan * without limitation the rights to use, copy, modify, merge, publish, * 8166124Srafan * distribute, distribute with modifications, sublicense, and/or sell * 9166124Srafan * copies of the Software, and to permit persons to whom the Software is * 10166124Srafan * furnished to do so, subject to the following conditions: * 11166124Srafan * * 12166124Srafan * The above copyright notice and this permission notice shall be included * 13166124Srafan * in all copies or substantial portions of the Software. * 14166124Srafan * * 15166124Srafan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16166124Srafan * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17166124Srafan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18166124Srafan * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19166124Srafan * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20166124Srafan * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21166124Srafan * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22166124Srafan * * 23166124Srafan * Except as contained in this notice, the name(s) of the above copyright * 24166124Srafan * holders shall not be used in advertising or otherwise to promote the * 25166124Srafan * sale, use or other dealings in this Software without prior written * 26166124Srafan * authorization. * 27166124Srafan ****************************************************************************/ 28166124Srafan 29166124Srafan/**************************************************************************** 30174993Srafan * Author: Thomas E. Dickey * 31166124Srafan ****************************************************************************/ 32166124Srafan 33166124Srafan/* 34166124Srafan * Iterators for terminal databases. 35166124Srafan */ 36166124Srafan 37166124Srafan#include <curses.priv.h> 38166124Srafan 39166124Srafan#include <tic.h> 40166124Srafan 41174993SrafanMODULE_ID("$Id: db_iterator.c,v 1.6 2007/04/22 00:00:26 tom Exp $") 42166124Srafan 43174993Srafan#define HaveTicDirectory _nc_globals.have_tic_directory 44174993Srafan#define KeepTicDirectory _nc_globals.keep_tic_directory 45174993Srafan#define TicDirectory _nc_globals.tic_directory 46166124Srafan 47166124Srafan/* 48166124Srafan * Record the "official" location of the terminfo directory, according to 49166124Srafan * the place where we're writing to, or the normal default, if not. 50166124Srafan */ 51166124SrafanNCURSES_EXPORT(const char *) 52166124Srafan_nc_tic_dir(const char *path) 53166124Srafan{ 54174993Srafan if (!KeepTicDirectory) { 55166124Srafan if (path != 0) { 56174993Srafan TicDirectory = path; 57174993Srafan HaveTicDirectory = TRUE; 58174993Srafan } else if (!HaveTicDirectory && use_terminfo_vars()) { 59166124Srafan char *envp; 60166124Srafan if ((envp = getenv("TERMINFO")) != 0) 61166124Srafan return _nc_tic_dir(envp); 62166124Srafan } 63166124Srafan } 64174993Srafan return TicDirectory; 65166124Srafan} 66166124Srafan 67166124Srafan/* 68166124Srafan * Special fix to prevent the terminfo directory from being moved after tic 69166124Srafan * has chdir'd to it. If we let it be changed, then if $TERMINFO has a 70166124Srafan * relative path, we'll lose track of the actual directory. 71166124Srafan */ 72166124SrafanNCURSES_EXPORT(void) 73166124Srafan_nc_keep_tic_dir(const char *path) 74166124Srafan{ 75166124Srafan _nc_tic_dir(path); 76174993Srafan KeepTicDirectory = TRUE; 77166124Srafan} 78166124Srafan 79166124Srafan/* 80166124Srafan * Process the list of :-separated directories, looking for the terminal type. 81166124Srafan * We don't use strtok because it does not show us empty tokens. 82166124Srafan */ 83174993Srafan#define ThisDbList _nc_globals.dbi_list 84174993Srafan#define ThisDbSize _nc_globals.dbi_size 85166124Srafan 86166124Srafan/* 87166124Srafan * Cleanup. 88166124Srafan */ 89166124SrafanNCURSES_EXPORT(void) 90166124Srafan_nc_last_db(void) 91166124Srafan{ 92174993Srafan if (ThisDbList != 0) { 93174993Srafan FreeAndNull(ThisDbList); 94166124Srafan } 95174993Srafan ThisDbSize = 0; 96166124Srafan} 97166124Srafan 98166124Srafan/* The TERMINFO_DIRS value, if defined by the configure script, begins with a 99166124Srafan * ":", which will be interpreted as TERMINFO. 100166124Srafan */ 101166124Srafanstatic const char * 102166124Srafannext_list_item(const char *source, int *offset) 103166124Srafan{ 104166124Srafan if (source != 0) { 105174993Srafan FreeIfNeeded(ThisDbList); 106174993Srafan ThisDbList = strdup(source); 107174993Srafan ThisDbSize = strlen(source); 108166124Srafan } 109166124Srafan 110174993Srafan if (ThisDbList != 0 && ThisDbSize && *offset < ThisDbSize) { 111166124Srafan static char system_db[] = TERMINFO; 112174993Srafan char *result = ThisDbList + *offset; 113166124Srafan char *marker = strchr(result, NCURSES_PATHSEP); 114166124Srafan 115166124Srafan /* 116166124Srafan * Put a null on the marker if a separator was found. Set the offset 117166124Srafan * to the next position after the marker so we can call this function 118166124Srafan * again, using the data at the offset. 119166124Srafan */ 120166124Srafan if (marker == 0) { 121166124Srafan *offset += strlen(result) + 1; 122166124Srafan marker = result + *offset; 123166124Srafan } else { 124166124Srafan *marker++ = 0; 125174993Srafan *offset = marker - ThisDbList; 126166124Srafan } 127174993Srafan if (*result == 0 && result != (ThisDbList + ThisDbSize)) 128166124Srafan result = system_db; 129166124Srafan return result; 130166124Srafan } 131166124Srafan return 0; 132166124Srafan} 133166124Srafan 134166124Srafan#define NEXT_DBD(var, offset) next_list_item((*offset == 0) ? var : 0, offset) 135166124Srafan 136166124Srafan/* 137166124Srafan * This is a simple iterator which allows the caller to step through the 138166124Srafan * possible locations for a terminfo directory. ncurses uses this to find 139166124Srafan * terminfo files to read. 140166124Srafan */ 141166124SrafanNCURSES_EXPORT(const char *) 142166124Srafan_nc_next_db(DBDIRS * state, int *offset) 143166124Srafan{ 144166124Srafan const char *result; 145166124Srafan char *envp; 146166124Srafan 147166124Srafan while (*state < dbdLAST) { 148166124Srafan DBDIRS next = (DBDIRS) ((int) (*state) + 1); 149166124Srafan 150166124Srafan result = 0; 151166124Srafan 152166124Srafan switch (*state) { 153166124Srafan case dbdTIC: 154174993Srafan if (HaveTicDirectory) 155166124Srafan result = _nc_tic_dir(0); 156166124Srafan break; 157166124Srafan#if USE_DATABASE 158166124Srafan case dbdEnvOnce: 159166124Srafan if (use_terminfo_vars()) { 160166124Srafan if ((envp = getenv("TERMINFO")) != 0) 161166124Srafan result = _nc_tic_dir(envp); 162166124Srafan } 163166124Srafan break; 164166124Srafan case dbdHome: 165166124Srafan if (use_terminfo_vars()) { 166166124Srafan result = _nc_home_terminfo(); 167166124Srafan } 168166124Srafan break; 169166124Srafan case dbdEnvList: 170166124Srafan if (use_terminfo_vars()) { 171166124Srafan if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0) 172166124Srafan next = *state; 173166124Srafan } 174166124Srafan break; 175166124Srafan case dbdCfgList: 176166124Srafan#ifdef TERMINFO_DIRS 177166124Srafan if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0) 178166124Srafan next = *state; 179166124Srafan#endif 180166124Srafan break; 181166124Srafan case dbdCfgOnce: 182166124Srafan#ifndef TERMINFO_DIRS 183166124Srafan result = TERMINFO; 184166124Srafan#endif 185166124Srafan break; 186166124Srafan#endif /* USE_DATABASE */ 187166124Srafan#if USE_TERMCAP 188166124Srafan case dbdEnvOnce2: 189166124Srafan if (use_terminfo_vars()) { 190166124Srafan if ((envp = getenv("TERMCAP")) != 0) 191166124Srafan result = _nc_tic_dir(envp); 192166124Srafan } 193166124Srafan break; 194166124Srafan case dbdEnvList2: 195166124Srafan if (use_terminfo_vars()) { 196166124Srafan if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0) 197166124Srafan next = *state; 198166124Srafan } 199166124Srafan break; 200166124Srafan case dbdCfgList2: 201166124Srafan if ((result = NEXT_DBD(TERMPATH, offset)) != 0) 202166124Srafan next = *state; 203166124Srafan break; 204166124Srafan#endif /* USE_TERMCAP */ 205166124Srafan case dbdLAST: 206166124Srafan break; 207166124Srafan } 208166124Srafan if (*state != next) { 209166124Srafan *state = next; 210166124Srafan *offset = 0; 211166124Srafan _nc_last_db(); 212166124Srafan } 213166124Srafan if (result != 0) { 214166124Srafan return result; 215166124Srafan } 216166124Srafan } 217166124Srafan return 0; 218166124Srafan} 219166124Srafan 220166124SrafanNCURSES_EXPORT(void) 221166124Srafan_nc_first_db(DBDIRS * state, int *offset) 222166124Srafan{ 223166124Srafan *state = dbdTIC; 224166124Srafan *offset = 0; 225166124Srafan} 226