20130313
[gdash.git] / src / misc / util.cpp
blobc81b796415c326c44426ff1ab61e150f443939e2
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "config.h"
19 #include <glib.h>
20 #include <cstdlib>
21 #include <cstring>
23 #include "cave/helper/colors.hpp"
24 #include "misc/printf.hpp"
25 #include "misc/logger.hpp"
27 #include "misc/util.hpp"
29 std::string gd_tostring_free(char *str) {
30 std::string ret;
32 if (str) {
33 ret=str;
34 g_free(str);
37 return ret;
40 static std::string find_file_try_path(const char *path, const char *filename) {
41 std::string ret;
42 char *result;
44 // create path
45 result=g_build_path(G_DIR_SEPARATOR_S, path, filename, NULL);
47 // check if exists
48 if (g_file_test(result, G_FILE_TEST_EXISTS))
49 ret=result;
50 g_free(result);
52 return ret;
56 /* tries to find a file in the gdash installation and returns a path */
57 std::string gd_find_data_file(const std::string& filename, const std::vector<std::string>& dirs) {
58 for (unsigned i=0; i<dirs.size(); ++i) {
59 std::string result=find_file_try_path(dirs[i].c_str(), filename.c_str());
60 if (result!="")
61 return result;
64 return "";
67 int gd_clamp(int val, int min, int max) {
68 g_assert(min<=max);
70 if (val<min)
71 return min;
72 if (val>max)
73 return max;
74 return val;
77 /* return current date in 2008-12-04 format */
78 std::string gd_get_current_date() {
79 char dats[128];
81 GDate *dat=g_date_new();
82 g_date_set_time_t(dat, time(NULL));
83 g_date_strftime(dats, sizeof(dats), "%Y-%m-%d", dat);
84 g_date_free(dat);
86 return dats;
90 std::string gd_get_current_date_time() {
91 char dats[128];
93 GDate *dat=g_date_new();
94 g_date_set_time_t(dat, time(0));
95 g_date_strftime(dats, sizeof(dats), "%Y-%m-%d %H:%I", dat);
96 g_date_free(dat);
98 return dats;
101 /* remove leading and trailing spaces from string */
102 void gd_strchomp(std::string &s) {
103 while (s.length()>0 && s[0]==' ')
104 s.erase(0, 1);
105 while (s.length()>0 && s[s.length()-1]==' ')
106 s.erase(s.length()-1, 1);
109 int gd_str_ascii_casecmp(const std::string &s1, const std::string &s2) {
110 int s1len=s1.length();
111 int s2len=s2.length();
113 if (s1len==0 && s2len==0)
114 return 0;
115 if (s1len==0 && s2len!=0)
116 return -1;
117 if (s1len!=0 && s2len==0)
118 return 1;
120 /* compare characters */
121 int i=0;
122 while (i<s1len && i<s2len)
124 int c1=s1[i];
125 if (c1>='A' && c1<='Z')
126 c1=c1-'A'+'a'; /* convert to lowercase, but only ascii characters */
128 int c2=s2[i];
129 if (c2>='A' && c2<='Z')
130 c2=c2-'A'+'a';
132 if (c1!=c2)
133 return (c1-c2);
134 i++;
136 /* ... one of the strings (or both of them) are ended. */
137 if (s2len<s1len) /* if s1 is longer, it is "larger". (s2 is the prefix of s1.) */
138 return -1;
139 if (s2len>s1len) /* if s2 is longer, it is "larger". (s1 is the prefix of s2.) */
140 return 1;
141 return 0;
144 bool gd_str_ascii_caseequal(const std::string &s1, const std::string &s2) {
145 return gd_str_ascii_casecmp(s1, s2)==0;
148 bool gd_str_equal(const char *a, const char *b) {
149 return strcmp(a,b)==0;
152 bool gd_str_ascii_prefix(const std::string &str, const std::string &prefix) {
153 return gd_str_ascii_casecmp(str.substr(0, prefix.length()), prefix)==0;
157 std::vector<std::string> gd_wrap_text(const char *input, int width) {
158 std::vector<std::string> retlines;
160 std::istringstream is_lines(input);
161 std::string thisline;
162 while (getline(is_lines, thisline)) {
163 gunichar *inputtext = g_utf8_to_ucs4(thisline.c_str(), -1, NULL, NULL, NULL);
164 std::vector<gunichar> one_line, one_word;
165 int wordlen = 0, linelen = 0;
167 int i = 0;
168 while (inputtext[i] != 0) {
169 switch (inputtext[i]) {
170 case ' ':
171 if (!one_word.empty()) {
172 /* cannot fit, must start new line? */
173 if (linelen + wordlen > width) {
174 gchar *utf8 = g_ucs4_to_utf8(&one_line[0], one_line.size(), NULL, NULL, NULL);
175 retlines.push_back(utf8);
176 g_free(utf8);
177 one_line.clear();
178 linelen = 0;
180 one_line.insert(one_line.end(), one_word.begin(), one_word.end());
182 one_word.clear();
183 linelen += wordlen;
184 wordlen = 0;
185 one_line.push_back(' ');
186 linelen++;
187 break;
188 case GD_COLOR_SETCOLOR: /* the special markup character symbolizing color change */
189 one_word.push_back(inputtext[i]);
190 ++i;
191 one_word.push_back(inputtext[i]);
192 /* wordlen is deliberately not increased here */
193 break;
194 default:
195 one_word.push_back(inputtext[i]);
196 wordlen++;
197 break;
199 i++;
201 g_free(inputtext);
202 if (!one_word.empty()) {
203 /* cannot fit, must start new line? */
204 if (linelen + wordlen > width) {
205 gchar *utf8 = g_ucs4_to_utf8(&one_line[0], one_line.size(), NULL, NULL, NULL);
206 retlines.push_back(utf8);
207 g_free(utf8);
208 one_line.clear();
209 linelen = 0;
211 one_line.insert(one_line.end(), one_word.begin(), one_word.end());
213 /* add the rest of the line */
214 gchar *utf8 = g_ucs4_to_utf8(&one_line[0], one_line.size(), NULL, NULL, NULL);
215 retlines.push_back(utf8);
216 g_free(utf8);
219 return retlines;