From 5d2c2b27a6323e2666378b986129b2a7c2c39e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 6 Feb 2022 16:04:24 +0100 Subject: New upstream version 5.2.2GA --- app/bin/include/dirent.h | 4 +- app/bin/include/levenshtein.h | 24 + app/bin/include/paramfile.h | 9 + app/bin/include/paramfilelist.h | 11 +- app/bin/include/partcatalog.h | 83 ++- app/bin/include/svgformat.h | 55 ++ app/bin/include/utlist.h | 1073 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 1230 insertions(+), 29 deletions(-) create mode 100644 app/bin/include/levenshtein.h create mode 100644 app/bin/include/svgformat.h create mode 100644 app/bin/include/utlist.h (limited to 'app/bin/include') diff --git a/app/bin/include/dirent.h b/app/bin/include/dirent.h index fdfbe5b..2ebf703 100644 --- a/app/bin/include/dirent.h +++ b/app/bin/include/dirent.h @@ -1125,7 +1125,7 @@ extern "C" { /* Pointer to string to convert */ mbstr, /* Size of multi-byte string */ (int)len, /* Pointer to output buffer */ wcstr, - /* Size of output buffer */ sizeInWords - 1 + /* Size of output buffer */ (int)sizeInWords - 1 ); /* Ensure that output buffer is zero-terminated */ @@ -1208,7 +1208,7 @@ extern "C" { /* Pointer to unicode string */ wcstr, /* Length of unicode string */ (int)len, /* Pointer to output buffer */ mbstr, - /* Size of output buffer */ sizeInBytes - 1, + /* Size of output buffer */ (int)sizeInBytes - 1, /* Default character */ NULL, /* Whether default character was used or not */ pflag ); diff --git a/app/bin/include/levenshtein.h b/app/bin/include/levenshtein.h new file mode 100644 index 0000000..b3e0111 --- /dev/null +++ b/app/bin/include/levenshtein.h @@ -0,0 +1,24 @@ +#ifndef LEVENSHTEIN_H +#define LEVENSHTEIN_H + +// `levenshtein.h` - levenshtein +// MIT licensed. +// Copyright (c) 2015 Titus Wormer + +// Returns a size_t, depicting the difference between `a` and `b`. +// See for more information. +#ifdef __cplusplus +extern "C" { +#endif + +size_t +levenshtein(const char *a, const char *b); + +size_t +levenshtein_n (const char *a, const size_t length, const char *b, const size_t bLength); + +#ifdef __cplusplus +} +#endif + +#endif // LEVENSHTEIN_H diff --git a/app/bin/include/paramfile.h b/app/bin/include/paramfile.h index b177b15..97f635a 100644 --- a/app/bin/include/paramfile.h +++ b/app/bin/include/paramfile.h @@ -23,4 +23,13 @@ #define CONTENTSCOMMAND "CONTENTS" char *GetParameterFileContent(char *file); + + #define TURNOUTCOMMAND "TURNOUT" + #define STRUCTURECOMMAND "STRUCTURE" + #define CARCOMMAND "CARPART" + #define CARPROTOCOMMAND "CARPROTO" + + char * GetParameterFileScale(char *file); + + #endif // !HAVE_PARAMFILE_H diff --git a/app/bin/include/paramfilelist.h b/app/bin/include/paramfilelist.h index a1c081d..0ad7523 100644 --- a/app/bin/include/paramfilelist.h +++ b/app/bin/include/paramfilelist.h @@ -6,10 +6,12 @@ typedef struct { char * name; /** < name of parameter file */ char * contents; - bool deleted; - bool valid; /** < FALSE for dropped file */ + int deleted; + int deletedShadow; + int valid; /** < FALSE for dropped file */ bool favorite; enum paramFileState trackState; + enum paramFileState structureState; } paramFileInfo_t; typedef paramFileInfo_t * paramFileInfo_p; @@ -18,12 +20,15 @@ char *GetParamFileDir(void); void SetParamFileDir(char *fullPath); void LoadParamFileList(void); - BOOL_T ReadDefaultParams(const char * dirName); + //BOOL_T ReadDefaultParams(const char * dirName); void SaveParamFileList(void); int GetParamFileCount(); void UpdateParamFileList(void); void ParamFilesChange(long changes); int LoadParamFile(int files, char ** fileName, void * data); +// void InitializeParamDir(void); + void ParamFileListConfirmChange(void); + void ParamFileListCancelChange(void); BOOL_T ParamFileListInit(void); void SearchUiOk(void * junk); diff --git a/app/bin/include/partcatalog.h b/app/bin/include/partcatalog.h index eec9d1e..e1ea110 100644 --- a/app/bin/include/partcatalog.h +++ b/app/bin/include/partcatalog.h @@ -1,7 +1,7 @@ /** \file partcatalog.h * Manage the catalog of track parameter files */ -/* XTrkCad - Model Railroad CAD +/* XTrackCad - Model Railroad CAD * Copyright (C) 2019 Martin Fischer * * This program is free software; you can redistribute it and/or modify @@ -23,48 +23,83 @@ #define HAVE_TRACKCATALOG_H #include +#include "include/utlist.h" #define MAXFILESPERCONTENT 10 /**< count of files with the same content header */ -#define ESTIMATED_CONTENTS_WORDS 10 /**< average count of words in CONTENTS header */ struct sCatalogEntry { - struct sCatalogEntry *next; + struct sCatalogEntry *next, *prev; unsigned files; /**< current count of files */ char *fullFileName[MAXFILESPERCONTENT]; /**< fully qualified file name */ char *contents; /**< content field of parameter file */ - struct sCatalogEntry *indirect; /**< pointer to another catalog entry */ + char *tag; /**< data about the file */ }; - typedef struct sCatalogEntry CatalogEntry; +struct sCatalog { + CatalogEntry *head; /**< The entries */ +}; +typedef struct sCatalog Catalog; + + +/** +An index entry. This struct holds a keyword pointer and an array of pointers to +CatalogEntry +It is managed as a linked list +*/ struct sIndexEntry { - CatalogEntry *value; /**< catalog entry having the key word in contents */ + struct sIndexEntry *next; + struct sIndexEntry *prev; char *keyWord; /**< keyword */ + dynArr_t *references; /**< references to the CatalogEntry */ }; - typedef struct sIndexEntry IndexEntry; -struct sTrackLibrary { - CatalogEntry *catalog; /**< list of files cataloged */ + +struct sParameterLib { + Catalog *catalog; /**< list of files cataloged */ IndexEntry *index; /**< Index for lookup */ unsigned wordCount; /**< How many words indexed */ - void * words_array; /**< The array of words */ - unsigned trackTypeCount; /**< */ + unsigned parameterFileCount; /**< */ + char *words; }; +typedef struct sParameterLib + ParameterLib; /**< core data structure for the catalog */ -typedef struct sTrackLibrary - TrackLibrary; /**< core data structure for the catalog */ +enum WORDSTATE { + SEARCHED, + DISCARDED, + NOTFOUND, + CLOSE, + STATE_COUNT +}; + +struct sSearchResult { + Catalog subCatalog; + unsigned totalFound; + unsigned words; /**< no of words in search string */ + struct sSingleResult { + char *keyWord; + unsigned count; + enum WORDSTATE state; + } *kw; +}; +typedef struct sSearchResult SearchResult; -CatalogEntry *InitCatalog(void); -TrackLibrary *InitLibrary(void); -TrackLibrary *CreateLibrary(char *directory); -void DeleteLibrary(TrackLibrary *tracklib); -bool GetTrackFiles(TrackLibrary *trackLib, char *directory); -int GetParameterFileInfo(int files, char ** fileName, void * data); -unsigned CreateLibraryIndex(TrackLibrary *trackLib); -unsigned SearchLibrary(TrackLibrary *library, char *searchExpression, CatalogEntry *resultEntries); -unsigned CountCatalogEntries(CatalogEntry *listHeader); -void EmptyCatalog(CatalogEntry *listHeader); -unsigned SearchLibrary(TrackLibrary *library, char *searchExpression, CatalogEntry *resultEntries); +Catalog *InitCatalog(void); +void DestroyCatalog(Catalog *catalog); +CatalogEntry * InsertInOrder(Catalog *catalog, const char *contents, const char *tag); +void UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents, char *tag); +ParameterLib *InitLibrary(void); +ParameterLib *CreateLibrary(char *directory); +void DestroyLibrary(ParameterLib *tracklib); +bool CreateCatalogFromDir(ParameterLib *trackLib, char *directory); +unsigned CreateLibraryIndex(ParameterLib *trackLib); +unsigned SearchLibrary(ParameterLib *library, char *searchExpression, SearchResult *totalResult); +char *SearchStatistics(SearchResult *result); +void SearchDiscardResult(SearchResult *res); +unsigned CountCatalogEntries(Catalog *catalog); +void DiscardCatalog(ParameterLib *library); +EXPORT void CatalogDiscard(Catalog *catalog); bool FilterKeyword(char *word); #endif // !HAVE_TRACKCATALOG_H diff --git a/app/bin/include/svgformat.h b/app/bin/include/svgformat.h new file mode 100644 index 0000000..7cf5c85 --- /dev/null +++ b/app/bin/include/svgformat.h @@ -0,0 +1,55 @@ +/** \file svgformat.h + * Definitions and prototypes for SVG export + */ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2005 Dave Bullis + * + * 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 the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef HAVE_SVGFORMAT_H +#define HAVE_SVGFORMAT_H +#include +#include + +#define MININMUMLINEWIDTH 3.0 + +typedef mxml_node_t SVGParent; +typedef mxml_node_t SVGDocument; + +void SvgAddCSSStyle(SVGParent *svg); +void SvgLineCommand(SVGParent *svg, double x0, double y0, double x1, double y1, + double w, long c, unsigned lineOpt); +void SvgPolyLineCommand(SVGParent *svg, int cnt, double *points, int color, + double width, bool fill, unsigned lineStyle); +void SvgRectCommand(SVGParent *svg, double x0, double y0, double x1, double y1, + int color, unsigned linestyle); +void SvgCircleCommand(SVGParent *svg, double x, double y, double r, double w, + long c, bool fill, unsigned lineStyle); +void SvgArcCommand(SVGParent *svg, double x, double y, double r, double a0, + double a1, bool center, double w, long c, unsigned lineStyle); +void SvgTextCommand(SVGParent *svg, double x, double y, double size, long c, + char *text); +void SvgAddTitle(SVGParent *svg, char *title); + +SVGDocument *SvgCreateDocument(void); +SVGParent *SvgPrologue(SVGDocument *result, char *id, int layerCount, double x0, + double y0, double x1, double y1); + +bool SvgSaveFile(SVGDocument *svg, char *filename); +void SvgDestroyDocument(SVGDocument *svg); +#endif // !HAVE_SVGFORMAT_H + diff --git a/app/bin/include/utlist.h b/app/bin/include/utlist.h new file mode 100644 index 0000000..5bb1ac9 --- /dev/null +++ b/app/bin/include/utlist.h @@ -0,0 +1,1073 @@ +/* +Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 2.1.0 + +#include + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define IF_NO_DECLTYPE(x) x +#define LDECLTYPE(x) char* +#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) +#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define IF_NO_DECLTYPE(x) +#define UTLIST_SV(elt,list) +#define UTLIST_NEXT(elt,list,next) ((elt)->next) +#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ +#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_RS(list) +#define UTLIST_CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) + +#define LL_SORT2(list, cmp, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + + +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) + +#define DL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) + +#define CDL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + UTLIST_CASTASGN(_ls_oldhead,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); \ + if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = UTLIST_NEXT(_ls_q,list,next); \ + } \ + UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev,_ls_tail); \ + UTLIST_CASTASGN(_tmp,list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ + LL_PREPEND2(head,add,next) + +#define LL_PREPEND2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define LL_CONCAT(head1,head2) \ + LL_CONCAT2(head1,head2,next) + +#define LL_CONCAT2(head1,head2,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head1) { \ + _tmp = (head1); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(head2); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#define LL_APPEND(head,add) \ + LL_APPEND2(head,add,next) + +#define LL_APPEND2(head,add,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = (head); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_INSERT_INORDER(head,add,cmp) \ + LL_INSERT_INORDER2(head,add,cmp,next) + +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + LL_APPEND_ELEM2(head, _tmp, add, next); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define LL_LOWER_BOUND(head,elt,like,cmp) \ + LL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) + +#define LL_DELETE(head,del) \ + LL_DELETE2(head,del,next) + +#define LL_DELETE2(head,del,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (del)->next; \ + } \ + } \ +} while (0) + +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ + +#define LL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + LL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) + +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) + +#define LL_APPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef LL_CONCAT2 +#define LL_CONCAT2(head1,head2,next) \ +do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char*)(head1); \ + while ((head1)->next) { (head1) = (head1)->next; } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#undef LL_APPEND2 +#define LL_APPEND2(head,add,next) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#undef LL_INSERT_INORDER2 +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_DELETE2 +#define LL_DELETE2(head,del,next) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && ((head)->next != (del))) { \ + (head) = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_REPLACE_ELEM2 +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el)->next; \ +} while (0) + +#undef LL_PREPEND_ELEM2 +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ + DL_PREPEND2(head,add,prev,next) + +#define DL_PREPEND2(head,add,prev,next) \ +do { \ + (add)->next = (head); \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ + DL_APPEND2(head,add,prev,next) + +#define DL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_INSERT_INORDER(head,add,cmp) \ + DL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_LOWER_BOUND(head,elt,like,cmp) \ + DL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define DL_CONCAT(head1,head2) \ + DL_CONCAT2(head1,head2,prev,next) + +#define DL_CONCAT2(head1,head2,prev,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head2) { \ + if (head1) { \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ + } else { \ + (head1)=(head2); \ + } \ + } \ +} while (0) + +#define DL_DELETE(head,del) \ + DL_DELETE2(head,del,prev,next) + +#define DL_DELETE2(head,del,prev,next) \ +do { \ + assert((head) != NULL); \ + assert((del)->prev != NULL); \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del)==(head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0) + +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + DL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define DL_FOREACH(head,el) \ + DL_FOREACH2(head,el,next) + +#define DL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + DL_FOREACH_SAFE2(head,el,tmp,next) + +#define DL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH +#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 +#define DL_SEARCH2 LL_SEARCH2 + +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ +} while (0) + +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) + +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ + } else { \ + DL_APPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) + +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef DL_INSERT_INORDER2 +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_APPEND(head,add) \ + CDL_APPEND2(head,add,prev,next) + +#define CDL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } \ +} while (0) + +#define CDL_PREPEND(head,add) \ + CDL_PREPEND2(head,add,prev,next) + +#define CDL_PREPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define CDL_INSERT_INORDER(head,add,cmp) \ + CDL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ +} while (0) + +#define CDL_LOWER_BOUND(head,elt,like,cmp) \ + CDL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define CDL_DELETE(head,del) \ + CDL_DELETE2(head,del,prev,next) + +#define CDL_DELETE2(head,del,prev,next) \ +do { \ + if (((head)==(del)) && ((head)->next == (head))) { \ + (head) = NULL; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +do { \ + (counter) = 0; \ + CDL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define CDL_FOREACH(head,el) \ + CDL_FOREACH2(head,el,next) + +#define CDL_FOREACH2(head,el,next) \ + for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) + +#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ + CDL_SEARCH_SCALAR2(head,out,field,val,next) + +#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define CDL_SEARCH(head,out,elt,cmp) \ + CDL_SEARCH2(head,out,elt,cmp,next) + +#define CDL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) + +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) + +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef CDL_INSERT_INORDER2 +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +#endif /* UTLIST_H */ -- cgit v1.2.3 From a14a7a0ccc9de76aeab0b2e4bbf58f1a79deedc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 3 Jul 2024 10:19:30 +0200 Subject: New upstream version 5.3.0GA --- app/bin/include/dirent.h | 1655 +++++++++++++++++++-------------------- app/bin/include/levenshtein.h | 3 +- app/bin/include/paramfile.h | 52 +- app/bin/include/paramfilelist.h | 62 +- app/bin/include/partcatalog.h | 67 +- app/bin/include/problemrep.h | 37 + app/bin/include/stringxtc.h | 9 +- app/bin/include/svgformat.h | 4 +- app/bin/include/utf8convert.h | 2 +- 9 files changed, 951 insertions(+), 940 deletions(-) create mode 100644 app/bin/include/problemrep.h (limited to 'app/bin/include') diff --git a/app/bin/include/dirent.h b/app/bin/include/dirent.h index 2ebf703..31e31e3 100644 --- a/app/bin/include/dirent.h +++ b/app/bin/include/dirent.h @@ -9,10 +9,10 @@ #ifndef DIRENT_H #define DIRENT_H - /* - * Include windows.h without Windows Sockets 1.1 to prevent conflicts with - * Windows Sockets 2.0. - */ +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif @@ -23,12 +23,11 @@ #include #include #include -#include #include #include #include - /* Indicates that d_type field is available in dirent structure */ +/* Indicates that d_type field is available in dirent structure */ #define _DIRENT_HAVE_D_TYPE /* Indicates that d_namlen field is available in dirent structure */ @@ -197,7 +196,7 @@ # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) #endif - /* Return the exact length of the file name without zero terminator */ +/* Return the exact length of the file name without zero terminator */ #define _D_EXACT_NAMLEN(p) ((p)->d_namlen) /* Return the maximum size of a file name */ @@ -209,103 +208,103 @@ extern "C" { #endif - /* Wide-character version */ - struct _wdirent { - /* Always zero */ - long d_ino; +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; - /* File position within stream */ - long d_off; + /* File position within stream */ + long d_off; - /* Structure size */ - unsigned short d_reclen; + /* Structure size */ + unsigned short d_reclen; - /* Length of name without \0 */ - size_t d_namlen; + /* Length of name without \0 */ + size_t d_namlen; - /* File type */ - int d_type; + /* File type */ + int d_type; - /* File name */ - wchar_t d_name[PATH_MAX + 1]; - }; - typedef struct _wdirent _wdirent; + /* File name */ + wchar_t d_name[PATH_MAX + 1]; +}; +typedef struct _wdirent _wdirent; - struct _WDIR { - /* Current directory entry */ - struct _wdirent ent; +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; - /* Private file data */ - WIN32_FIND_DATAW data; + /* Private file data */ + WIN32_FIND_DATAW data; - /* True if data is valid */ - int cached; + /* True if data is valid */ + int cached; - /* Win32 search handle */ - HANDLE handle; + /* Win32 search handle */ + HANDLE handle; - /* Initial directory name */ - wchar_t *patt; - }; - typedef struct _WDIR _WDIR; + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; - /* Multi-byte character version */ - struct dirent { - /* Always zero */ - long d_ino; +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; - /* File position within stream */ - long d_off; + /* File position within stream */ + long d_off; - /* Structure size */ - unsigned short d_reclen; + /* Structure size */ + unsigned short d_reclen; - /* Length of name without \0 */ - size_t d_namlen; + /* Length of name without \0 */ + size_t d_namlen; - /* File type */ - int d_type; + /* File type */ + int d_type; - /* File name */ - char d_name[PATH_MAX + 1]; - }; - typedef struct dirent dirent; + /* File name */ + char d_name[PATH_MAX + 1]; +}; +typedef struct dirent dirent; - struct DIR { - struct dirent ent; - struct _WDIR *wdirp; - }; - typedef struct DIR DIR; +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; - /* Dirent functions */ - static DIR *opendir(const char *dirname); - static _WDIR *_wopendir(const wchar_t *dirname); +/* Dirent functions */ +static DIR *opendir(const char *dirname); +static _WDIR *_wopendir(const wchar_t *dirname); - static struct dirent *readdir(DIR *dirp); - static struct _wdirent *_wreaddir(_WDIR *dirp); +static struct dirent *readdir(DIR *dirp); +static struct _wdirent *_wreaddir(_WDIR *dirp); - static int readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result); - static int _wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); - static int closedir(DIR *dirp); - static int _wclosedir(_WDIR *dirp); +static int closedir(DIR *dirp); +static int _wclosedir(_WDIR *dirp); - static void rewinddir(DIR* dirp); - static void _wrewinddir(_WDIR* dirp); +static void rewinddir(DIR* dirp); +static void _wrewinddir(_WDIR* dirp); - static int scandir(const char *dirname, struct dirent ***namelist, - int(*filter)(const struct dirent*), - int(*compare)(const struct dirent**, const struct dirent**)); +static int scandir(const char *dirname, struct dirent ***namelist, + int(*filter)(const struct dirent*), + int(*compare)(const struct dirent**, const struct dirent**)); - static int alphasort(const struct dirent **a, const struct dirent **b); +static int alphasort(const struct dirent **a, const struct dirent **b); - static int versionsort(const struct dirent **a, const struct dirent **b); +static int versionsort(const struct dirent **a, const struct dirent **b); - /* For compatibility with Symbian */ +/* For compatibility with Symbian */ #define wdirent _wdirent #define WDIR _WDIR #define wopendir _wopendir @@ -315,937 +314,907 @@ extern "C" { /* Internal utility functions */ - static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); - static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); - static int dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count); +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); - static int dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, - const wchar_t *wcstr, - size_t count); +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); - static void dirent_set_errno(int error); +static void dirent_set_errno(int error); - /* - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ - static _WDIR* - _wopendir( - const wchar_t *dirname) - { - _WDIR *dirp = NULL; - int error; +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } + /* Allocate new _WDIR structure */ + dirp = (_WDIR*)malloc(sizeof(struct _WDIR)); + if (dirp != NULL) { + DWORD n; - /* Allocate new _WDIR structure */ - dirp = (_WDIR*)malloc(sizeof(struct _WDIR)); - if (dirp != NULL) { - DWORD n; + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; - /* Reset _WDIR structure */ - dirp->handle = INVALID_HANDLE_VALUE; - dirp->patt = NULL; - dirp->cached = 0; + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); +# else + n = GetFullPathNameW(dirname, 0, NULL, NULL); +# endif - /* Compute the length of full path plus zero terminator + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt) { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). * * Note that on WinRT there's no way to convert relative paths * into absolute paths, so just assume it is an absolute path. */ -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - n = wcslen(dirname); -# else - n = GetFullPathNameW(dirname, 0, NULL, NULL); -# endif - - /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16); - if (dirp->patt) { - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly even when current - * working directory is changed between opendir() and rewinddir(). - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - wcsncpy_s(dirp->patt, n + 1, dirname, n); + wcsncpy_s(dirp->patt, n + 1, dirname, n); # else - n = GetFullPathNameW(dirname, n, dirp->patt, NULL); + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); # endif - if (n > 0) { - wchar_t *p; - - /* Append search pattern \* to the directory name */ - p = dirp->patt + n; - if (dirp->patt < p) { - switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; - } - } - *p++ = '*'; - *p = '\0'; + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; - /* Open directory stream and retrieve the first entry */ - if (dirent_first(dirp)) { - /* Directory stream opened successfully */ - error = 0; - } - else { - /* Cannot retrieve first entry */ - error = 1; - dirent_set_errno(ENOENT); + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; } - } - else { - /* Cannot retrieve full path name */ - dirent_set_errno(ENOENT); + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first(dirp)) { + /* Directory stream opened successfully */ + error = 0; + } else { + /* Cannot retrieve first entry */ error = 1; + dirent_set_errno(ENOENT); } - } - else { - /* Cannot allocate memory for search pattern */ + } else { + /* Cannot retrieve full path name */ + dirent_set_errno(ENOENT); error = 1; } - } - else { - /* Cannot allocate _WDIR structure */ + } else { + /* Cannot allocate memory for search pattern */ error = 1; } - /* Clean up in case of error */ - if (error && dirp) { - _wclosedir(dirp); - dirp = NULL; - } + } else { + /* Cannot allocate _WDIR structure */ + error = 1; + } - return dirp; + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir(dirp); + dirp = NULL; } + return dirp; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + struct _wdirent *entry; + /* - * Read next directory entry. - * - * Returns pointer to static directory entry which may be overwritten by - * subsequent calls to _wreaddir(). + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. */ - static struct _wdirent* - _wreaddir( - _WDIR *dirp) - { - struct _wdirent *entry; + (void)_wreaddir_r(dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int +_wreaddir_r( + _WDIR *dirp, + struct _wdirent *entry, + struct _wdirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next(dirp); + if (datap) { + size_t n; + DWORD attr; /* - * Read directory entry to buffer. We can safely ignore the return value - * as entry will be set to NULL in case of error. + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. */ - (void)_wreaddir_r(dirp, &dirp->ent, &entry); + n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; - /* Return pointer to statically allocated directory entry */ - return entry; - } + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; - /* - * Read next directory entry. - * - * Returns zero on success. If end of directory stream is reached, then sets - * result to NULL and returns zero. - */ - static int - _wreaddir_r( - _WDIR *dirp, - struct _wdirent *entry, - struct _wdirent **result) - { - WIN32_FIND_DATAW *datap; - - /* Read next directory entry */ - datap = dirent_next(dirp); - if (datap) { - size_t n; - DWORD attr; + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } - /* - * Copy file name as wide-character string. If the file name is too - * long to fit in to the destination buffer, then truncate file name - * to PATH_MAX characters and zero-terminate the buffer. - */ - n = 0; - while (n < PATH_MAX && datap->cFileName[n] != 0) { - entry->d_name[n] = datap->cFileName[n]; - n++; - } - entry->d_name[n] = 0; + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof(struct _wdirent); - /* Length of file name excluding zero terminator */ - entry->d_namlen = n; + /* Set result address */ + *result = entry; - /* File type */ - attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - entry->d_type = DT_CHR; - } - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - entry->d_type = DT_DIR; - } - else { - entry->d_type = DT_REG; - } + } else { - /* Reset dummy fields */ - entry->d_ino = 0; - entry->d_off = 0; - entry->d_reclen = sizeof(struct _wdirent); + /* Return NULL to indicate end of directory */ + *result = NULL; - /* Set result address */ - *result = entry; + } - } - else { + return /*OK*/0; +} - /* Return NULL to indicate end of directory */ - *result = NULL; +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + /* Release search pattern */ + if (dirp->patt) { + free(dirp->patt); + dirp->patt = NULL; } - return /*OK*/0; - } + /* Release directory structure */ + free(dirp); + ok = /*success*/0; - /* - * Close directory stream opened by opendir() function. This invalidates the - * DIR structure as well as any directory entry read previously by - * _wreaddir(). - */ - static int - _wclosedir( - _WDIR *dirp) - { - int ok; - if (dirp) { - - /* Release search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose(dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - } + } else { - /* Release search pattern */ - if (dirp->patt) { - free(dirp->patt); - dirp->patt = NULL; - } + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; - /* Release directory structure */ - free(dirp); - ok = /*success*/0; + } + return ok; +} +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); } - else { - - /* Invalid directory stream */ - dirent_set_errno(EBADF); - ok = /*failure*/-1; - } - return ok; + /* Open new search handle */ + dirent_first(dirp); } +} - /* - * Rewind directory stream such that _wreaddir() returns the very first - * file name again. - */ - static void - _wrewinddir( - _WDIR* dirp) - { - if (dirp) { - /* Release existing search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose(dirp->handle); - } - - /* Open new search handle */ - dirent_first(dirp); - } - } +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; - /* Get first directory entry (internal) */ - static WIN32_FIND_DATAW* - dirent_first( - _WDIR *dirp) - { - WIN32_FIND_DATAW *datap; - - /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileExW( - dirp->patt, FindExInfoStandard, &dirp->data, - FindExSearchNameMatch, NULL, 0); - if (dirp->handle != INVALID_HANDLE_VALUE) { + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { - /* a directory entry is now waiting in memory */ - datap = &dirp->data; - dirp->cached = 1; + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; - } - else { + } else { - /* Failed to re-open directory: no directory entry in memory */ - dirp->cached = 0; - datap = NULL; + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; - } - return datap; } + return datap; +} - /* - * Get next directory entry (internal). - * - * Returns - */ - static WIN32_FIND_DATAW* - dirent_next( - _WDIR *dirp) - { - WIN32_FIND_DATAW *p; - - /* Get next directory entry */ - if (dirp->cached != 0) { +/* + * Get next directory entry (internal). + * + * Returns + */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; - /* A valid directory entry already in memory */ - p = &dirp->data; - dirp->cached = 0; + /* Get next directory entry */ + if (dirp->cached != 0) { - } - else if (dirp->handle != INVALID_HANDLE_VALUE) { + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; - /* Get the next directory entry from stream */ - if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { - /* Got a file */ - p = &dirp->data; - } - else { - /* The very last entry has been processed or an error occurred */ - FindClose(dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - p = NULL; - } + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + /* Get the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occurred */ + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; } - else { - /* End of directory stream reached */ - p = NULL; + } else { - } + /* End of directory stream reached */ + p = NULL; - return p; } - /* - * Open directory stream using plain old C-string. - */ - static DIR* - opendir( - const char *dirname) - { - struct DIR *dirp; - int error; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } + return p; +} - /* Allocate memory for DIR structure */ - dirp = (DIR*)malloc(sizeof(struct DIR)); - if (dirp) { - wchar_t wname[PATH_MAX + 1]; - size_t n; - - /* Convert directory name to wide-character string */ - error = dirent_mbstowcs_s( - &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); - if (!error) { - - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir(wname); - if (dirp->wdirp) { - /* Directory stream opened */ - error = 0; - } - else { - /* Failed to open directory stream */ - error = 1; - } +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } - } - else { - /* - * Cannot convert file name to wide-character string. This - * occurs if the string contains invalid multi-byte sequences or - * the output buffer is too small to contain the resulting - * string. - */ + /* Allocate memory for DIR structure */ + dirp = (DIR*)malloc(sizeof(struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX + 1]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s( + &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } else { + /* Failed to open directory stream */ error = 1; } - } - else { - /* Cannot allocate DIR structure */ + } else { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ error = 1; } - /* Clean up in case of error */ - if (error && dirp) { - free(dirp); - dirp = NULL; - } - - return dirp; + } else { + /* Cannot allocate DIR structure */ + error = 1; } - /* - * Read next directory entry. - */ - static struct dirent* - readdir( - DIR *dirp) - { - struct dirent *entry; + /* Clean up in case of error */ + if (error && dirp) { + free(dirp); + dirp = NULL; + } - /* - * Read directory entry to buffer. We can safely ignore the return value - * as entry will be set to NULL in case of error. - */ - (void)readdir_r(dirp, &dirp->ent, &entry); + return dirp; +} - /* Return pointer to statically allocated directory entry */ - return entry; - } +/* + * Read next directory entry. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + struct dirent *entry; /* - * Read next directory entry into called-allocated buffer. - * - * Returns zero on success. If the end of directory stream is reached, then - * sets result to NULL and returns zero. + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. */ - static int - readdir_r( - DIR *dirp, - struct dirent *entry, - struct dirent **result) - { - WIN32_FIND_DATAW *datap; - - /* Read next directory entry */ - datap = dirent_next(dirp->wdirp); - if (datap) { - size_t n; - int error; - - /* Attempt to convert file name to multi-byte string */ - error = dirent_wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); + (void)readdir_r(dirp, &dirp->ent, &entry); - /* - * If the file name cannot be represented by a multi-byte string, - * then attempt to use old 8+3 file name. This allows traditional - * Unix-code to access some file names despite of unicode - * characters, although file names may seem unfamiliar to the user. - * - * Be ware that the code below cannot come up with a short file - * name unless the file system provides one. At least - * VirtualBox shared folders fail to do this. - */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = dirent_wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cAlternateFileName, PATH_MAX + 1); - } + /* Return pointer to statically allocated directory entry */ + return entry; +} - if (!error) { - DWORD attr; +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int +readdir_r( + DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next(dirp->wdirp); + if (datap) { + size_t n; + int error; - /* Length of file name excluding zero terminator */ - entry->d_namlen = n - 1; + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); - /* File attributes */ - attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - entry->d_type = DT_CHR; - } - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - entry->d_type = DT_DIR; - } - else { - entry->d_type = DT_REG; - } + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } - /* Reset dummy fields */ - entry->d_ino = 0; - entry->d_off = 0; - entry->d_reclen = sizeof(struct dirent); + if (!error) { + DWORD attr; - } - else { - - /* - * Cannot convert file name to multi-byte string so construct - * an erroneous directory entry and return that. Note that - * we cannot return NULL as that would stop the processing - * of directory entries completely. - */ - entry->d_name[0] = '?'; - entry->d_name[1] = '\0'; - entry->d_namlen = 1; - entry->d_type = DT_UNKNOWN; - entry->d_ino = 0; - entry->d_off = -1; - entry->d_reclen = 0; + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; } - /* Return pointer to directory entry */ - *result = entry; + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof(struct dirent); - } - else { + } else { - /* No more directory entries */ - *result = NULL; + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; } - return /*OK*/0; + /* Return pointer to directory entry */ + *result = entry; + + } else { + + /* No more directory entries */ + *result = NULL; + } - /* - * Close directory stream. - */ - static int - closedir( - DIR *dirp) - { - int ok; - if (dirp) { + return /*OK*/0; +} - /* Close wide-character directory stream */ - ok = _wclosedir(dirp->wdirp); - dirp->wdirp = NULL; +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { - /* Release multi-byte character version */ - free(dirp); + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; - } - else { + /* Release multi-byte character version */ + free(dirp); - /* Invalid directory stream */ - dirent_set_errno(EBADF); - ok = /*failure*/-1; + } else { - } - return ok; - } + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; - /* - * Rewind directory stream to beginning. - */ - static void - rewinddir( - DIR* dirp) - { - /* Rewind wide-character string directory stream */ - _wrewinddir(dirp->wdirp); } + return ok; +} - /* - * Scan directory for entries. - */ - static int - scandir( - const char *dirname, - struct dirent ***namelist, - int(*filter)(const struct dirent*), - int(*compare)(const struct dirent**, const struct dirent**)) - { - struct dirent **files = NULL; - size_t size = 0; - size_t allocated = 0; - const size_t init_size = 1; - DIR *dir = NULL; - struct dirent *entry; - struct dirent *tmp = NULL; - size_t i; - int result = 0; - - /* Open directory stream */ - dir = opendir(dirname); - if (dir) { - - /* Read directory entries to memory */ - while (1) { - - /* Enlarge pointer table to make room for another pointer */ - if (size >= allocated) { - void *p; - size_t num_entries; - - /* Compute number of entries in the enlarged pointer table */ - if (size < init_size) { - /* Allocate initial pointer table */ - num_entries = init_size; - } - else { - /* Double the size */ - num_entries = size * 2; - } +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir(dirp->wdirp); +} - /* Allocate first pointer table or enlarge existing table */ - p = realloc(files, sizeof(void*) * num_entries); - if (p != NULL) { - /* Got the memory */ - files = (dirent**)p; - allocated = num_entries; - } - else { - /* Out of memory */ - result = -1; - break; - } +/* + * Scan directory for entries. + */ +static int +scandir( + const char *dirname, + struct dirent ***namelist, + int(*filter)(const struct dirent*), + int(*compare)(const struct dirent**, const struct dirent**)) +{ + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + const size_t init_size = 1; + DIR *dir = NULL; + struct dirent *entry; + struct dirent *tmp = NULL; + size_t i; + int result = 0; + + /* Open directory stream */ + dir = opendir(dirname); + if (dir) { + + /* Read directory entries to memory */ + while (1) { + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + void *p; + size_t num_entries; + + /* Compute number of entries in the enlarged pointer table */ + if (size < init_size) { + /* Allocate initial pointer table */ + num_entries = init_size; + } else { + /* Double the size */ + num_entries = size * 2; + } + /* Allocate first pointer table or enlarge existing table */ + p = realloc(files, sizeof(void*) * num_entries); + if (p != NULL) { + /* Got the memory */ + files = (dirent**)p; + allocated = num_entries; + } else { + /* Out of memory */ + result = -1; + break; } - /* Allocate room for temporary directory entry */ + } + + /* Allocate room for temporary directory entry */ + if (tmp == NULL) { + tmp = (struct dirent*) malloc(sizeof(struct dirent)); if (tmp == NULL) { - tmp = (struct dirent*) malloc(sizeof(struct dirent)); - if (tmp == NULL) { - /* Cannot allocate temporary directory entry */ - result = -1; - break; - } + /* Cannot allocate temporary directory entry */ + result = -1; + break; } + } - /* Read directory entry to temporary area */ - if (readdir_r(dir, tmp, &entry) == /*OK*/0) { - - /* Did we get an entry? */ - if (entry != NULL) { - int pass; + /* Read directory entry to temporary area */ + if (readdir_r(dir, tmp, &entry) == /*OK*/0) { - /* Determine whether to include the entry in result */ - if (filter) { - /* Let the filter function decide */ - pass = filter(tmp); - } - else { - /* No filter function, include everything */ - pass = 1; - } + /* Did we get an entry? */ + if (entry != NULL) { + int pass; - if (pass) { - /* Store the temporary entry to pointer table */ - files[size++] = tmp; - tmp = NULL; + /* Determine whether to include the entry in result */ + if (filter) { + /* Let the filter function decide */ + pass = filter(tmp); + } else { + /* No filter function, include everything */ + pass = 1; + } - /* Keep up with the number of files */ - result++; - } + if (pass) { + /* Store the temporary entry to pointer table */ + files[size++] = tmp; + tmp = NULL; + /* Keep up with the number of files */ + result++; } - else { - - /* - * End of directory stream reached => sort entries and - * exit. - */ - qsort(files, size, sizeof(void*), - (int(*) (const void*, const void*)) compare); - break; - } + } else { - } - else { - /* Error reading directory entry */ - result = /*Error*/ -1; + /* + * End of directory stream reached => sort entries and + * exit. + */ + qsort(files, size, sizeof(void*), + (int(*) (const void*, const void*)) compare); break; + } + } else { + /* Error reading directory entry */ + result = /*Error*/ -1; + break; } } - else { - /* Cannot open directory */ - result = /*Error*/ -1; - } - /* Release temporary directory entry */ - if (tmp) { - free(tmp); - } - - /* Release allocated memory on error */ - if (result < 0) { - for (i = 0; i < size; i++) { - free(files[i]); - } - free(files); - files = NULL; - } + } else { + /* Cannot open directory */ + result = /*Error*/ -1; + } - /* Close directory stream */ - if (dir) { - closedir(dir); - } + /* Release temporary directory entry */ + if (tmp) { + free(tmp); + } - /* Pass pointer table to caller */ - if (namelist) { - *namelist = files; + /* Release allocated memory on error */ + if (result < 0) { + for (i = 0; i < size; i++) { + free(files[i]); } - return result; + free(files); + files = NULL; } - /* Alphabetical sorting */ - static int - alphasort( - const struct dirent **a, const struct dirent **b) - { - return strcoll((*a)->d_name, (*b)->d_name); + /* Close directory stream */ + if (dir) { + closedir(dir); } - /* Sort versions */ - static int - versionsort( - const struct dirent **a, const struct dirent **b) - { - /* FIXME: implement strverscmp and use that */ - return alphasort(a, b); + /* Pass pointer table to caller */ + if (namelist) { + *namelist = files; } + return result; +} - /* Convert multi-byte string to wide character string */ - static int - dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count) - { - int error; - int n; - size_t len; - UINT cp; - DWORD flags; - - /* Determine code page for multi-byte string */ - if (AreFileApisANSI()) { - /* Default ANSI code page */ - cp = GetACP(); - } - else { - /* Default OEM code page */ - cp = GetOEMCP(); - } +/* Alphabetical sorting */ +static int +alphasort( + const struct dirent **a, const struct dirent **b) +{ + return strcoll((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int +versionsort( + const struct dirent **a, const struct dirent **b) +{ + /* FIXME: implement strverscmp and use that */ + return alphasort(a, b); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + int n; + size_t len; + UINT cp; + DWORD flags; + + /* Determine code page for multi-byte string */ + if (AreFileApisANSI()) { + /* Default ANSI code page */ + cp = GetACP(); + } else { + /* Default OEM code page */ + cp = GetOEMCP(); + } + /* + * Determine flags based on the character set. For more information, + * please see https://docs.microsoft.com/fi-fi/windows/desktop/api/stringapiset/nf-stringapiset-multibytetowidechar + */ + switch (cp) { + case 42: + case 50220: + case 50221: + case 50222: + case 50225: + case 50227: + case 50229: + case 57002: + case 57003: + case 57004: + case 57005: + case 57006: + case 57007: + case 57008: + case 57009: + case 57010: + case 57011: + case 65000: + /* MultiByteToWideChar does not support MB_ERR_INVALID_CHARS */ + flags = 0; + break; + + default: /* - * Determine flags based on the character set. For more information, - * please see https://docs.microsoft.com/fi-fi/windows/desktop/api/stringapiset/nf-stringapiset-multibytetowidechar + * Ask MultiByteToWideChar to return an error if a multi-byte + * character cannot be converted to a wide-character. */ - switch (cp) { - case 42: - case 50220: - case 50221: - case 50222: - case 50225: - case 50227: - case 50229: - case 57002: - case 57003: - case 57004: - case 57005: - case 57006: - case 57007: - case 57008: - case 57009: - case 57010: - case 57011: - case 65000: - /* MultiByteToWideChar does not support MB_ERR_INVALID_CHARS */ - flags = 0; - break; - - default: - /* - * Ask MultiByteToWideChar to return an error if a multi-byte - * character cannot be converted to a wide-character. - */ - flags = MB_ERR_INVALID_CHARS; - } + flags = MB_ERR_INVALID_CHARS; + } - /* Compute the length of input string without zero-terminator */ - len = 0; - while (mbstr[len] != '\0' && len < count) { - len++; - } + /* Compute the length of input string without zero-terminator */ + len = 0; + while (mbstr[len] != '\0' && len < count) { + len++; + } - /* Convert to wide-character string */ - n = MultiByteToWideChar( - /* Source code page */ cp, - /* Flags */ flags, - /* Pointer to string to convert */ mbstr, - /* Size of multi-byte string */ (int)len, - /* Pointer to output buffer */ wcstr, - /* Size of output buffer */ (int)sizeInWords - 1 - ); - - /* Ensure that output buffer is zero-terminated */ - wcstr[n] = '\0'; - - /* Return length of wide-character string with zero-terminator */ - *pReturnValue = (size_t)(n + 1); - - /* Return zero if conversion succeeded */ - if (n > 0) { - error = 0; - } - else { - error = 1; - } - return error; + /* Convert to wide-character string */ + n = MultiByteToWideChar( + /* Source code page */ cp, + /* Flags */ flags, + /* Pointer to string to convert */ mbstr, + /* Size of multi-byte string */ (int)len, + /* Pointer to output buffer */ wcstr, + /* Size of output buffer */ (int)sizeInWords - 1 + ); + + /* Ensure that output buffer is zero-terminated */ + wcstr[n] = '\0'; + + /* Return length of wide-character string with zero-terminator */ + *pReturnValue = (size_t)(n + 1); + + /* Return zero if conversion succeeded */ + if (n > 0) { + error = 0; + } else { + error = 1; } + return error; +} - /* Convert wide-character string to multi-byte string */ - static int - dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, /* max size of mbstr */ - const wchar_t *wcstr, - size_t count) - { - int n; - int error; - UINT cp; - size_t len; - BOOL flag = 0; - LPBOOL pflag; - - /* Determine code page for multi-byte string */ - if (AreFileApisANSI()) { - /* Default ANSI code page */ - cp = GetACP(); - } - else { - /* Default OEM code page */ - cp = GetOEMCP(); - } +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int n; + int error; + UINT cp; + size_t len; + BOOL flag = 0; + LPBOOL pflag; + + /* Determine code page for multi-byte string */ + if (AreFileApisANSI()) { + /* Default ANSI code page */ + cp = GetACP(); + } else { + /* Default OEM code page */ + cp = GetOEMCP(); + } - /* Compute the length of input string without zero-terminator */ - len = 0; - while (wcstr[len] != '\0' && len < count) { - len++; - } + /* Compute the length of input string without zero-terminator */ + len = 0; + while (wcstr[len] != '\0' && len < count) { + len++; + } + /* + * Determine if we can ask WideCharToMultiByte to return information on + * broken characters. For more information, please see + * https://docs.microsoft.com/en-us/windows/desktop/api/stringapiset/nf-stringapiset-widechartomultibyte + */ + switch (cp) { + case CP_UTF7: + case CP_UTF8: /* - * Determine if we can ask WideCharToMultiByte to return information on - * broken characters. For more information, please see - * https://docs.microsoft.com/en-us/windows/desktop/api/stringapiset/nf-stringapiset-widechartomultibyte + * WideCharToMultiByte fails if we request information on default + * characters. This is just a nuisance but doesn't affect the + * conversion: if Windows is configured to use UTF-8, then the default + * character should not be needed anyway. */ - switch (cp) { - case CP_UTF7: - case CP_UTF8: - /* - * WideCharToMultiByte fails if we request information on default - * characters. This is just a nuisance but doesn't affect the - * conversion: if Windows is configured to use UTF-8, then the default - * character should not be needed anyway. - */ - pflag = NULL; - break; + pflag = NULL; + break; - default: - /* - * Request that WideCharToMultiByte sets the flag if it uses the - * default character. - */ - pflag = &flag; - } + default: + /* + * Request that WideCharToMultiByte sets the flag if it uses the + * default character. + */ + pflag = &flag; + } - /* Convert wide-character string to multi-byte character string */ - n = WideCharToMultiByte( - /* Target code page */ cp, - /* Flags */ 0, - /* Pointer to unicode string */ wcstr, - /* Length of unicode string */ (int)len, - /* Pointer to output buffer */ mbstr, - /* Size of output buffer */ (int)sizeInBytes - 1, - /* Default character */ NULL, - /* Whether default character was used or not */ pflag - ); - - /* Ensure that output buffer is zero-terminated */ - mbstr[n] = '\0'; - - /* Return length of multi-byte string with zero-terminator */ - *pReturnValue = (size_t)(n + 1); - - /* Return zero if conversion succeeded without using default characters */ - if (n > 0 && flag == 0) { - error = 0; - } - else { - error = 1; - } - return error; + /* Convert wide-character string to multi-byte character string */ + n = WideCharToMultiByte( + /* Target code page */ cp, + /* Flags */ 0, + /* Pointer to unicode string */ wcstr, + /* Length of unicode string */ (int)len, + /* Pointer to output buffer */ mbstr, + /* Size of output buffer */ (int)sizeInBytes - 1, + /* Default character */ NULL, + /* Whether default character was used or not */ pflag + ); + + /* Ensure that output buffer is zero-terminated */ + mbstr[n] = '\0'; + + /* Return length of multi-byte string with zero-terminator */ + *pReturnValue = (size_t)(n + 1); + + /* Return zero if conversion succeeded without using default characters */ + if (n > 0 && flag == 0) { + error = 0; + } else { + error = 1; } + return error; +} - /* Set errno variable */ - static void - dirent_set_errno( - int error) - { +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ #if defined(_MSC_VER) && _MSC_VER >= 1400 - /* Microsoft Visual Studio 2005 and later */ - _set_errno(error); + /* Microsoft Visual Studio 2005 and later */ + _set_errno(error); #else - /* Non-Microsoft compiler or older Microsoft compiler */ - errno = error; + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; #endif - } +} #ifdef __cplusplus diff --git a/app/bin/include/levenshtein.h b/app/bin/include/levenshtein.h index b3e0111..1ea6c36 100644 --- a/app/bin/include/levenshtein.h +++ b/app/bin/include/levenshtein.h @@ -15,7 +15,8 @@ size_t levenshtein(const char *a, const char *b); size_t -levenshtein_n (const char *a, const size_t length, const char *b, const size_t bLength); +levenshtein_n (const char *a, const size_t length, const char *b, + const size_t bLength); #ifdef __cplusplus } diff --git a/app/bin/include/paramfile.h b/app/bin/include/paramfile.h index 97f635a..8ae7f59 100644 --- a/app/bin/include/paramfile.h +++ b/app/bin/include/paramfile.h @@ -1,35 +1,35 @@ #ifndef HAVE_PARAMFILE_H - #define HAVE_PARAMFILE_H - #include - #include - #include "common.h" +#define HAVE_PARAMFILE_H +#include +#include +#include "common.h" - extern DIST_T curBarScale; - extern dynArr_t paramProc_da; - extern dynArr_t paramFileInfo_da; +extern DIST_T curBarScale; +extern dynArr_t paramProc_da; +extern dynArr_t paramFileInfo_da; - void ParamCheckSumLine(char * line); - wBool_t IsParamValid(int fileInx); - bool IsParamFileDeleted(int fileInx); - bool IsParamFileFavorite(int fileInx); - void SetParamFileState(int index); - int ReadParamFile(const char *fileName); - int ReloadDeletedParamFile(int fileindex); - void SetParamFileDeleted(int fileInx, bool deleted); - void SetParamFileFavorite(int fileInx, bool favorite); - char * GetParamFileName(int fileInx); - char * GetParamFileContents(int fileInx); - bool ReadParams(long key, const char * dirName, const char * fileName); +void ParamCheckSumLine(char * line); +wBool_t IsParamValid(int fileInx); +bool IsParamFileDeleted(int fileInx); +bool IsParamFileFavorite(int fileInx); +void SetParamFileState(int index); +int ReadParamFile(const char *fileName); +int ReloadDeletedParamFile(int fileindex); +void SetParamFileDeleted(int fileInx, bool deleted); +void SetParamFileFavorite(int fileInx, bool favorite); +char * GetParamFileName(int fileInx); +char * GetParamFileContents(int fileInx); +bool ReadParams(long key, const char * dirName, const char * fileName); - #define CONTENTSCOMMAND "CONTENTS" - char *GetParameterFileContent(char *file); +#define CONTENTSCOMMAND "CONTENTS" +char *GetParameterFileContent(char *file); - #define TURNOUTCOMMAND "TURNOUT" - #define STRUCTURECOMMAND "STRUCTURE" - #define CARCOMMAND "CARPART" - #define CARPROTOCOMMAND "CARPROTO" +#define TURNOUTCOMMAND "TURNOUT" +#define STRUCTURECOMMAND "STRUCTURE" +#define CARCOMMAND "CARPART" +#define CARPROTOCOMMAND "CARPROTO" - char * GetParameterFileScale(char *file); +char * GetParameterFileScale(char *file); #endif // !HAVE_PARAMFILE_H diff --git a/app/bin/include/paramfilelist.h b/app/bin/include/paramfilelist.h index 0ad7523..2893292 100644 --- a/app/bin/include/paramfilelist.h +++ b/app/bin/include/paramfilelist.h @@ -1,37 +1,37 @@ #ifndef HAVE_PARAMFILELIST_H - #define HAVE_PARAMFILELIST_H - #include - #include "include/paramfile.h" +#define HAVE_PARAMFILELIST_H +#include +#include "include/paramfile.h" - typedef struct { - char * name; /** < name of parameter file */ - char * contents; - int deleted; - int deletedShadow; - int valid; /** < FALSE for dropped file */ - bool favorite; - enum paramFileState trackState; - enum paramFileState structureState; - } paramFileInfo_t; - typedef paramFileInfo_t * paramFileInfo_p; +typedef struct { + char * name; /** < name of parameter file */ + char * contents; + int deleted; + int deletedShadow; + int valid; /** < FALSE for dropped file */ + bool favorite; + enum paramFileState trackState; + enum paramFileState structureState; +} paramFileInfo_t; +typedef paramFileInfo_t * paramFileInfo_p; - #define paramFileInfo(N) DYNARR_N( paramFileInfo_t, paramFileInfo_da, N ) - - char *GetParamFileDir(void); - void SetParamFileDir(char *fullPath); - void LoadParamFileList(void); - //BOOL_T ReadDefaultParams(const char * dirName); - void SaveParamFileList(void); - int GetParamFileCount(); - void UpdateParamFileList(void); - void ParamFilesChange(long changes); - int LoadParamFile(int files, char ** fileName, void * data); +#define paramFileInfo(N) DYNARR_N( paramFileInfo_t, paramFileInfo_da, N ) + +char *GetParamFileDir(void); +void SetParamFileDir(char *fullPath); +void LoadParamFileList(void); +//BOOL_T ReadDefaultParams(const char * dirName); +void SaveParamFileList(void); +int GetParamFileCount(); +void UpdateParamFileList(void); +void ParamFilesChange(long changes); +int LoadParamFile(int files, char ** fileName, void * data); // void InitializeParamDir(void); - void ParamFileListConfirmChange(void); - void ParamFileListCancelChange(void); - BOOL_T ParamFileListInit(void); +void ParamFileListConfirmChange(void); +void ParamFileListCancelChange(void); +BOOL_T ParamFileListInit(void); - void SearchUiOk(void * junk); - bool ReloadParamFile(wIndex_t index); - bool UnloadParamFile(wIndex_t fileIndex); +void SearchUiOk(void * junk); +bool ReloadParamFile(wIndex_t index); +bool UnloadParamFile(wIndex_t fileIndex); #endif // !HAVE_PARAMFILELIST_H diff --git a/app/bin/include/partcatalog.h b/app/bin/include/partcatalog.h index e1ea110..365e78b 100644 --- a/app/bin/include/partcatalog.h +++ b/app/bin/include/partcatalog.h @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HAVE_TRACKCATALOG_H @@ -28,16 +28,16 @@ #define MAXFILESPERCONTENT 10 /**< count of files with the same content header */ struct sCatalogEntry { - struct sCatalogEntry *next, *prev; - unsigned files; /**< current count of files */ - char *fullFileName[MAXFILESPERCONTENT]; /**< fully qualified file name */ - char *contents; /**< content field of parameter file */ - char *tag; /**< data about the file */ + struct sCatalogEntry *next, *prev; + unsigned files; /**< current count of files */ + char *fullFileName[MAXFILESPERCONTENT]; /**< fully qualified file name */ + char *contents; /**< content field of parameter file */ + char *tag; /**< data about the file */ }; typedef struct sCatalogEntry CatalogEntry; struct sCatalog { - CatalogEntry *head; /**< The entries */ + CatalogEntry *head; /**< The entries */ }; typedef struct sCatalog Catalog; @@ -48,54 +48,57 @@ CatalogEntry It is managed as a linked list */ struct sIndexEntry { - struct sIndexEntry *next; - struct sIndexEntry *prev; - char *keyWord; /**< keyword */ - dynArr_t *references; /**< references to the CatalogEntry */ + struct sIndexEntry *next; + struct sIndexEntry *prev; + char *keyWord; /**< keyword */ + dynArr_t *references; /**< references to the CatalogEntry */ }; typedef struct sIndexEntry IndexEntry; struct sParameterLib { - Catalog *catalog; /**< list of files cataloged */ - IndexEntry *index; /**< Index for lookup */ - unsigned wordCount; /**< How many words indexed */ - unsigned parameterFileCount; /**< */ - char *words; + Catalog *catalog; /**< list of files cataloged */ + IndexEntry *index; /**< Index for lookup */ + unsigned wordCount; /**< How many words indexed */ + unsigned parameterFileCount; /**< */ + char *words; }; typedef struct sParameterLib - ParameterLib; /**< core data structure for the catalog */ + ParameterLib; /**< core data structure for the catalog */ enum WORDSTATE { - SEARCHED, - DISCARDED, - NOTFOUND, + SEARCHED, + DISCARDED, + NOTFOUND, CLOSE, - STATE_COUNT + STATE_COUNT }; struct sSearchResult { - Catalog subCatalog; - unsigned totalFound; - unsigned words; /**< no of words in search string */ - struct sSingleResult { - char *keyWord; - unsigned count; - enum WORDSTATE state; - } *kw; + Catalog subCatalog; + unsigned totalFound; + unsigned words; /**< no of words in search string */ + struct sSingleResult { + char *keyWord; + unsigned count; + enum WORDSTATE state; + } *kw; }; typedef struct sSearchResult SearchResult; Catalog *InitCatalog(void); void DestroyCatalog(Catalog *catalog); -CatalogEntry * InsertInOrder(Catalog *catalog, const char *contents, const char *tag); -void UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents, char *tag); +CatalogEntry * InsertInOrder(Catalog *catalog, const char *contents, + const char *tag); +void UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents, + char *tag); ParameterLib *InitLibrary(void); ParameterLib *CreateLibrary(char *directory); void DestroyLibrary(ParameterLib *tracklib); bool CreateCatalogFromDir(ParameterLib *trackLib, char *directory); unsigned CreateLibraryIndex(ParameterLib *trackLib); -unsigned SearchLibrary(ParameterLib *library, char *searchExpression, SearchResult *totalResult); +unsigned SearchLibrary(ParameterLib *library, char *searchExpression, + SearchResult *totalResult); char *SearchStatistics(SearchResult *result); void SearchDiscardResult(SearchResult *res); unsigned CountCatalogEntries(Catalog *catalog); diff --git a/app/bin/include/problemrep.h b/app/bin/include/problemrep.h new file mode 100644 index 0000000..bcc6982 --- /dev/null +++ b/app/bin/include/problemrep.h @@ -0,0 +1,37 @@ +/** \file problemrep.h + * Collect data for a problem report and remove private info +*/ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2024 Martin Fischer + * + * 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 the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef HAVE_PROBLEMREP_H +#define HAVE_PROBLEMREP_H + +//problemrep.c + +void DoProblemCollect(void* unused); + +// problemrepui.c + +void ProblemrepCreateW(void* ptr); +void ProblemrepUpdateW(char* text, ...); +int ProblemSaveLayout(void); + +#endif // !HAVE_PROBLEMREP_H + diff --git a/app/bin/include/stringxtc.h b/app/bin/include/stringxtc.h index cbadd0e..dc054d7 100644 --- a/app/bin/include/stringxtc.h +++ b/app/bin/include/stringxtc.h @@ -1,8 +1,9 @@ #include #ifndef HAVE_STRINGXTC_H - #define HAVE_STRINGXTC_H - size_t strscpy(char *dest, const char *src, size_t count); - char *XtcStrlwr(char *str); - int XtcStricmp(const char *a, const char *b); +#define HAVE_STRINGXTC_H +size_t strscat(char *dest, const char *src, size_t count); +size_t strscpy(char *dest, const char *src, size_t count); +char *XtcStrlwr(char *str); +int XtcStricmp(const char *a, const char *b); #endif diff --git a/app/bin/include/svgformat.h b/app/bin/include/svgformat.h index 7cf5c85..075bbe1 100644 --- a/app/bin/include/svgformat.h +++ b/app/bin/include/svgformat.h @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HAVE_SVGFORMAT_H @@ -25,7 +25,7 @@ #include #include -#define MININMUMLINEWIDTH 3.0 +#define MINIMUMLINEWIDTH 4.0 typedef mxml_node_t SVGParent; typedef mxml_node_t SVGDocument; diff --git a/app/bin/include/utf8convert.h b/app/bin/include/utf8convert.h index 6a3e678..f6d8fb6 100644 --- a/app/bin/include/utf8convert.h +++ b/app/bin/include/utf8convert.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HAVE_UTF8CONVERT_H -- cgit v1.2.3