/[svn]/gigedit/trunk/src/gigedit/global.h
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/global.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2474 by schoenebeck, Sun Sep 15 18:16:21 2013 UTC revision 3472 by persson, Sat Feb 16 19:56:56 2019 UTC
# Line 1  Line 1 
1  /*                                                         -*- c++ -*-  /*                                                         -*- c++ -*-
2   * Copyright (C) 2007-2013 Andreas Persson   * Copyright (C) 2007-2019 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 24  Line 24 
24  # include <config.h>  # include <config.h>
25  #endif  #endif
26    
27    #include <cstring>
28    #include <algorithm>
29    
30    #ifdef GLIBMM_HEADER_FILE
31    # include GLIBMM_HEADER_FILE(glibmmconfig.h)
32    #else
33    # include <glibmmconfig.h>
34    #endif
35    
36    #if !defined(WIN32)
37    # include <unistd.h>
38    # include <errno.h>
39    #endif
40    
41  #include <sstream>  #include <sstream>
42    #include <map>
43    #include <sigc++/signal.h>
44    
45    #ifdef LIBGIG_HEADER_FILE
46    # include LIBGIG_HEADER_FILE(gig.h)
47    # include LIBGIG_HEADER_FILE(Serialization.h)
48    #else
49    # include <gig.h>
50    # include <Serialization.h>
51    #endif
52    
53  //FIXME: for some reason AC GETTEXT check fails on the Mac cross compiler?  //FIXME: for some reason AC GETTEXT check fails on the Mac cross compiler?
54  #if (HAVE_GETTEXT || defined(__APPLE__))  #ifdef GETTEXT_HEADER_FILE
55    # include GETTEXT_HEADER_FILE(libintl.h)
56    #elif (HAVE_GETTEXT || defined(__APPLE__))
57  # include <libintl.h>  # include <libintl.h>
58  # define _(String) gettext(String)  # define _(String) gettext(String)
59  #else  #else
# Line 40  Line 66 
66  # define VERSION VER_STRING // VER_STRING defined in libgig_private.h  # define VERSION VER_STRING // VER_STRING defined in libgig_private.h
67  #endif // WIN32  #endif // WIN32
68    
69    #define UNICODE_RIGHT_ARROW     Glib::ustring(1, gunichar(0x2192))
70    #define UNICODE_LEFT_ARROW      Glib::ustring(1, gunichar(0x2190))
71    #define UNICODE_SHIFT_KEY_SYMBOL    Glib::ustring("\xe2\x87\xa7")
72    #if defined(__APPLE__)
73    # define UNICODE_ALT_KEY_SYMBOL     Glib::ustring("\xe2\x8c\xa5")
74    #else
75    # define UNICODE_ALT_KEY_SYMBOL     Glib::ustring("Alt")
76    #endif
77    #define UNICODE_ERASE_KEY_SYMBOL    Glib::ustring("\xe2\x8c\xab")
78    #define UNICODE_CTRL_KEY_SYMBOL     Glib::ustring("Ctrl")
79    #define UNICODE_CMD_KEY_SYMBOL      Glib::ustring(1, gunichar(0x2318))
80    #if defined(__APPLE__)
81    # define UNICODE_PRIMARY_KEY_SYMBOL     UNICODE_CMD_KEY_SYMBOL
82    #else
83    # define UNICODE_PRIMARY_KEY_SYMBOL     UNICODE_CTRL_KEY_SYMBOL
84    #endif
85    
86    // taken from gdk/gdkkeysyms.h
87    // (define on demand, to avoid unnecessary dev lib package build dependency)
88    #ifndef GDK_KEY_Control_L
89    # define GDK_KEY_Control_L 0xffe3
90    #endif
91    #ifndef GDK_KEY_Control_R
92    # define GDK_KEY_Control_R 0xffe4
93    #endif
94    #ifndef GDK_KEY_Left
95    # define GDK_KEY_Left 0xff51
96    #endif
97    #ifndef GDK_KEY_Right
98    # define GDK_KEY_Right 0xff53
99    #endif
100    #ifndef GDK_KEY_Up
101    # define GDK_KEY_Up 0xff52
102    #endif
103    #ifndef GDK_KEY_Down
104    # define GDK_KEY_Down 0xff54
105    #endif
106    
107    #include <glibmm/convert.h>
108    
109    #define GIG_STR_ENCODING "CP1252"
110    
111    static inline
112    Glib::ustring gig_to_utf8(const gig::String& gig_string) {
113        return Glib::convert_with_fallback(gig_string, "UTF-8", GIG_STR_ENCODING, "?");
114    }
115    
116    static inline
117    gig::String gig_from_utf8(const Glib::ustring& utf8_string) {
118        return Glib::convert_with_fallback(utf8_string, GIG_STR_ENCODING, "UTF-8", "?");
119    }
120    
121    inline Glib::ustring ltrim(Glib::ustring s) {
122        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
123        return s;
124    }
125    
126    inline Glib::ustring rtrim(Glib::ustring s) {
127        s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
128        return s;
129    }
130    
131    inline Glib::ustring trim(Glib::ustring s) {
132        return ltrim(rtrim(s));
133    }
134    
135  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
136      std::stringstream ss;      std::stringstream ss;
137      ss << o;      ss << o;
138      return ss.str();      return ss.str();
139  }  }
140    
141    inline static bool endsWith(const std::string& haystack, const std::string& needle, bool caseSensitive) {
142        if (haystack.size() < needle.size()) return false;
143        const std::string sub = haystack.substr(haystack.size() - needle.size(), needle.size());
144        return (caseSensitive) ? (sub == needle) : (!strcasecmp(sub.c_str(), needle.c_str()));
145    }
146    
147    inline int getDimensionIndex(gig::dimension_t type, gig::Region* rgn) {
148        for (uint i = 0; i < rgn->Dimensions; ++i)
149            if (rgn->pDimensionDefinitions[i].dimension == type)
150                return i;
151        return -1;
152    }
153    
154    inline int getDimensionRegionIndex(gig::DimensionRegion* dr) {
155        if (!dr) return -1;
156        gig::Region* rgn = (gig::Region*)dr->GetParent();
157        for (uint i = 0; i < 256; ++i)
158            if (rgn->pDimensionRegions[i] == dr)
159                return i;
160        return -1;
161    }
162    
163    /// Find the number of bits required to hold the specified amount of zones.
164    inline int zoneCountToBits(int nZones) {
165        if (!nZones) return 0;
166        int iFinalBits = 0;
167        int zoneBits = nZones - 1;
168        for (; zoneBits > 1; iFinalBits += 2, zoneBits >>= 2);
169        iFinalBits += zoneBits;
170        return iFinalBits;
171    }
172    
173    /**
174     * Returns the sum of all bits of all dimensions defined before the given
175     * dimensions (@a type). This allows to access cases of that particular
176     * dimension directly. If the supplied dimension @a type does not exist in the
177     * the supplied @a region, then this function returns -1 instead!
178     *
179     * @param type - dimension that shall be used
180     * @param rgn - parent region of that dimension
181     */
182    inline int baseBits(gig::dimension_t type, gig::Region* rgn) {
183        int previousBits = 0;
184        for (uint i = 0; i < rgn->Dimensions; ++i) {
185            if (rgn->pDimensionDefinitions[i].dimension == type) return previousBits;
186            previousBits += rgn->pDimensionDefinitions[i].bits;
187        }
188        return -1;
189    }
190    
191    // key: dimension type, value: dimension's zone index
192    class DimensionCase : public std::map<gig::dimension_t,int> {
193    public:
194        bool isViolating(const DimensionCase& c) const {
195            for (DimensionCase::const_iterator it = begin(); it != end(); ++it) {
196                if (c.find(it->first) == c.end()) continue;
197                if (c.find(it->first)->second != it->second) return true;
198            }
199            return false;
200        }
201    
202        // prevent passing gig::dimension_none from creating a new pair
203        // (TODO: other invalid gig::dimension_t values should be filtered here as well)
204        int& operator[](const gig::dimension_t& k) {
205            static int unused = 0;
206            if (k == gig::dimension_none) {
207                unused = 0;
208                return unused;
209            }
210            return std::map<gig::dimension_t,int>::operator[](k);
211        }
212    };
213    
214    //TODO: this function and caseOfDimRegion() from dimregionchooser.h are duplicates, eliminate either one of them!
215    inline DimensionCase dimensionCaseOf(gig::DimensionRegion* dr) {
216        DimensionCase dimCase;
217        int idr = getDimensionRegionIndex(dr);
218        if (idr < 0) return dimCase;
219        gig::Region* rgn = (gig::Region*)dr->GetParent();
220        int bitpos = 0;
221        for (int d = 0; d < rgn->Dimensions; ++d) {
222            const gig::dimension_def_t& dimdef = rgn->pDimensionDefinitions[d];
223            const int zone = (idr >> bitpos) & ((1 << dimdef.bits) - 1);
224            dimCase[dimdef.dimension] = zone;
225            bitpos += rgn->pDimensionDefinitions[d].bits;
226        }
227        return dimCase;
228    }
229    
230    /**
231     * Checks whether the passed dimension zones are within the boundaries of the
232     * defined dimensions. This is especially relevant if there are dimensions
233     * defined with an amount not equal to a power of two, in that case there are
234     * unused dimensions regions which should be ignored.
235     */
236    inline bool isUsedCase(const DimensionCase& c, gig::Region* rgn) {
237        for (int d = 0; d < rgn->Dimensions; ++d) {
238            gig::dimension_t type = rgn->pDimensionDefinitions[d].dimension;
239            if (c.find(type) == c.end()) continue;
240            int zone = c.find(type)->second;
241            if (zone < 0 || zone >= rgn->pDimensionDefinitions[d].zones)
242                return false;
243        }
244        return true;
245    }
246    
247    inline std::vector<gig::DimensionRegion*> dimensionRegionsMatching(
248        const DimensionCase& dimCase, gig::Region* rgn, bool skipUnusedZones = false)
249    {
250        std::vector<gig::DimensionRegion*> v;
251        for (int idr = 0; idr < 256; ++idr) {
252            if (!rgn->pDimensionRegions[idr]) continue;
253            DimensionCase c = dimensionCaseOf(rgn->pDimensionRegions[idr]);
254            if (dimCase.isViolating(c)) continue;
255            if (skipUnusedZones && !isUsedCase(c, rgn)) continue;
256            v.push_back(rgn->pDimensionRegions[idr]);
257        }
258        return v;
259    }
260    
261    inline gig::DimensionRegion* dimensionRegionMatching(const DimensionCase& dimCase, gig::Region* rgn) {
262        for (int idr = 0; idr < 256; ++idr) {
263            if (!rgn->pDimensionRegions[idr]) continue;
264            DimensionCase c = dimensionCaseOf(rgn->pDimensionRegions[idr]);
265            if (c == dimCase) return rgn->pDimensionRegions[idr];
266        }
267        return NULL;
268    }
269    
270    template<typename T_Message>
271    class SignalGuard {
272    public:
273        SignalGuard(sigc::signal<void, T_Message>& start, sigc::signal<void, T_Message>& end, T_Message message)
274            : m_end(end), m_message(message)
275        {
276            if (message) start.emit(message);
277        }
278    
279        virtual ~SignalGuard() {
280            if (m_message) m_end.emit(m_message);
281        }
282    protected:
283        sigc::signal<void, T_Message>& m_end;
284        T_Message m_message;
285    };
286    
287  #endif // GIGEDIT_GLOBAL_H  #endif // GIGEDIT_GLOBAL_H

Legend:
Removed from v.2474  
changed lines
  Added in v.3472

  ViewVC Help
Powered by ViewVC