1 string wordwrap_buffer;
3 void wordwrap_buffer_put(string s)
5 wordwrap_buffer = strcat(wordwrap_buffer, s);
8 string wordwrap(string s, float l)
12 wordwrap_cb(s, l, wordwrap_buffer_put);
19 void wordwrap_buffer_sprint(string s)
21 wordwrap_buffer = strcat(wordwrap_buffer, s);
24 sprint(self, wordwrap_buffer);
29 void wordwrap_sprint(string s, float l)
32 wordwrap_cb(s, l, wordwrap_buffer_sprint);
33 if(wordwrap_buffer != "")
34 sprint(self, strcat(wordwrap_buffer, "\n"));
40 string unescape(string in)
45 // but it doesn't seem to be necessary in my tests at least
50 for(i = 0; i < len; ++i)
52 s = substring(in, i, 1);
55 s = substring(in, i+1, 1);
57 str = strcat(str, "\n");
59 str = strcat(str, "\\");
61 str = strcat(str, substring(in, i, 2));
71 void wordwrap_cb(string s, float l, void(string) callback)
74 local float lleft, i, j, wlen;
78 for (i = 0;i < strlen(s);++i)
80 if (substring(s, i, 2) == "\\n")
86 else if (substring(s, i, 1) == "\n")
91 else if (substring(s, i, 1) == " ")
101 for (j = i+1;j < strlen(s);++j)
102 // ^^ this skips over the first character of a word, which
103 // is ALWAYS part of the word
104 // this is safe since if i+1 == strlen(s), i will become
105 // strlen(s)-1 at the end of this block and the function
106 // will terminate. A space can't be the first character we
107 // read here, and neither can a \n be the start, since these
108 // two cases have been handled above.
110 c = substring(s, j, 1);
117 // we need to keep this tempstring alive even if substring is
118 // called repeatedly, so call strcat even though we're not
128 callback(substring(s, i, wlen));
129 lleft = lleft - wlen;
136 float dist_point_line(vector p, vector l0, vector ldir)
138 ldir = normalize(ldir);
140 // remove the component in line direction
141 p = p - (p * ldir) * ldir;
143 // vlen of the remaining vector
147 void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
176 float median(float a, float b, float c)
179 return bound(a, b, c);
180 return bound(c, b, a);
183 // converts a number to a string with the indicated number of decimals
184 // works for up to 10 decimals!
185 string ftos_decimals(float number, float decimals)
191 // if negative, cut off the sign first
193 return strcat("-", ftos_decimals(-number, decimals));
194 // it now is always positive!
197 number = floor(number * pow(10, decimals) + 0.5);
200 result = ftos(number);
201 len = strlen(result);
202 // does it have a decimal point (should not happen)? If there is one, it is always at len-7)
203 // if ftos had fucked it up, which should never happen: "34278.000000"
205 if(substring(result, len - 7, 1) == ".")
207 dprint("ftos(integer) has comma? Can't be. Affected result: ", result, "\n");
208 result = substring(result, 0, len - 7);
213 return result; // don't insert a point for zero decimals
214 // is it too short? If yes, insert leading zeroes
217 result = strcat(substring("0000000000", 0, decimals - len + 1), result);
220 // and now... INSERT THE POINT!
221 tmp = substring(result, len - decimals, decimals);
222 result = strcat(substring(result, 0, len - decimals), ".", tmp);
227 vector colormapPaletteColor(float c, float isPants)
231 case 0: return '0.733 0.733 0.733';
232 case 1: return '0.451 0.341 0.122';
233 case 2: return '0.000 0.733 0.733';
234 case 3: return '0.000 1.000 0.000';
235 case 4: return '1.000 0.000 0.000';
236 case 5: return '0.000 0.502 1.000';
237 case 6: return '0.812 0.561 0.169';
238 case 7: return '0.718 0.529 0.420';
239 case 8: return '0.765 0.545 0.667';
240 case 9: return '1.000 0.000 1.000';
241 case 10: return '0.639 0.529 0.482';
242 case 11: return '0.310 0.388 0.341';
243 case 12: return '1.000 1.000 0.000';
244 case 13: return '0.000 0.000 1.000';
245 case 14: return '1.000 0.502 0.000';
249 '1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
250 + '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
251 + '0 0 1' * (0.502 + 0.498 * sin(time / 2.7182818285 + 4.1887902048));
254 '1 0 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 5.2359877560))
255 + '0 1 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 3.1415926536))
256 + '0 0 1' * (0.502 + 0.498 * sin(time / 3.1415926536 + 1.0471975512));
257 default: return '0.000 0.000 0.000';
261 // unzone the string, and return it as tempstring. Safe to be called on string_null
262 string fstrunzone(string s)
272 // Databases (hash tables)
273 #define DB_BUCKETS 8192
274 void db_save(float db, string pFilename)
277 fh = fopen(pFilename, FILE_WRITE);
279 error(strcat("Can't write DB to ", pFilename));
281 fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
282 for(i = 0; i < n; ++i)
283 fputs(fh, strcat(bufstr_get(db, i), "\n"));
292 float db_load(string pFilename)
294 float db, fh, i, j, n;
299 fh = fopen(pFilename, FILE_READ);
302 if(stof(fgets(fh)) == DB_BUCKETS)
305 while((l = fgets(fh)))
308 bufstr_set(db, i, l);
314 // different count of buckets?
315 // need to reorganize the database then (SLOW)
316 while((l = fgets(fh)))
318 n = tokenizebyseparator(l, "\\");
319 for(j = 2; j < n; j += 2)
320 db_put(db, uri_unescape(argv(j-1)), uri_unescape(argv(j)));
327 void db_dump(float db, string pFilename)
329 float fh, i, j, n, m;
330 fh = fopen(pFilename, FILE_WRITE);
332 error(strcat("Can't dump DB to ", pFilename));
335 for(i = 0; i < n; ++i)
337 m = tokenizebyseparator(bufstr_get(db, i), "\\");
338 for(j = 2; j < m; j += 2)
339 fputs(fh, strcat("\\", argv(j-1), "\\", argv(j), "\n"));
344 void db_close(float db)
349 string db_get(float db, string pKey)
352 h = mod(crc16(FALSE, pKey), DB_BUCKETS);
353 return uri_unescape(infoget(bufstr_get(db, h), pKey));
356 void db_put(float db, string pKey, string pValue)
359 h = mod(crc16(FALSE, pKey), DB_BUCKETS);
360 bufstr_set(db, h, infoadd(bufstr_get(db, h), pKey, uri_escape(pValue)));
367 db = db_load("foo.db");
368 print("LOADED. FILL...\n");
369 for(i = 0; i < DB_BUCKETS; ++i)
370 db_put(db, ftos(random()), "X");
371 print("FILLED. SAVE...\n");
372 db_save(db, "foo.db");
373 print("SAVED. CLOSE...\n");
378 // Multiline text file buffers
379 float buf_load(string pFilename)
386 fh = fopen(pFilename, FILE_READ);
390 while((l = fgets(fh)))
392 bufstr_set(buf, i, l);
399 void buf_save(float buf, string pFilename)
402 fh = fopen(pFilename, FILE_WRITE);
404 error(strcat("Can't write buf to ", pFilename));
405 n = buf_getsize(buf);
406 for(i = 0; i < n; ++i)
407 fputs(fh, strcat(bufstr_get(buf, i), "\n"));