PageRenderTime 55ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/misc.c

https://github.com/MadDog2k3/The-Powder-Toy
C | 686 lines | 632 code | 48 blank | 6 comment | 118 complexity | 68e4726e77a2f1e40053972478c997b9 MD5 | raw file
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <regex.h>
  5. #include <sys/types.h>
  6. #include <math.h>
  7. #include "misc.h"
  8. #include "defines.h"
  9. #include "interface.h"
  10. #include "graphics.h"
  11. #include "powder.h"
  12. #include <icondoc.h>
  13. #include <update.h>
  14. #if defined WIN32
  15. #include <windows.h>
  16. #else
  17. #include <unistd.h>
  18. #endif
  19. #ifdef MACOSX
  20. #include <ApplicationServices/ApplicationServices.h>
  21. #endif
  22. char *clipboard_text = NULL;
  23. //Signum function
  24. #if defined(WIN32) && !defined(__GNUC__)
  25. _inline int isign(float i)
  26. #else
  27. inline int isign(float i)
  28. #endif
  29. {
  30. if (i<0)
  31. return -1;
  32. if (i>0)
  33. return 1;
  34. return 0;
  35. }
  36. #if defined(WIN32) && !defined(__GNUC__)
  37. _inline unsigned clamp_flt(float f, float min, float max)
  38. #else
  39. inline unsigned clamp_flt(float f, float min, float max)
  40. #endif
  41. {
  42. if (f<min)
  43. return 0;
  44. if (f>max)
  45. return 255;
  46. return (int)(255.0f*(f-min)/(max-min));
  47. }
  48. #if defined(WIN32) && !defined(__GNUC__)
  49. _inline float restrict_flt(float f, float min, float max)
  50. #else
  51. inline float restrict_flt(float f, float min, float max)
  52. #endif
  53. {
  54. if (f<min)
  55. return min;
  56. if (f>max)
  57. return max;
  58. return f;
  59. }
  60. char *mystrdup(char *s)
  61. {
  62. char *x;
  63. if (s)
  64. {
  65. x = (char*)malloc(strlen(s)+1);
  66. strcpy(x, s);
  67. return x;
  68. }
  69. return s;
  70. }
  71. void strlist_add(struct strlist **list, char *str)
  72. {
  73. struct strlist *item = malloc(sizeof(struct strlist));
  74. item->str = mystrdup(str);
  75. item->next = *list;
  76. *list = item;
  77. }
  78. int strlist_find(struct strlist **list, char *str)
  79. {
  80. struct strlist *item;
  81. for (item=*list; item; item=item->next)
  82. if (!strcmp(item->str, str))
  83. return 1;
  84. return 0;
  85. }
  86. void strlist_free(struct strlist **list)
  87. {
  88. struct strlist *item;
  89. while (*list)
  90. {
  91. item = *list;
  92. *list = (*list)->next;
  93. free(item);
  94. }
  95. }
  96. void clean_text(char *text, int vwidth)
  97. {
  98. int i = 0;
  99. if(textwidth(text) > vwidth){
  100. text[textwidthx(text, vwidth)] = 0;
  101. }
  102. for(i = 0; i < strlen(text); i++){
  103. if(! (text[i]>=' ' && text[i]<127)){
  104. text[i] = ' ';
  105. }
  106. }
  107. }
  108. void save_presets(int do_update)
  109. {
  110. FILE *f=fopen("powder.def", "wb");
  111. unsigned char sig[4] = {0x50, 0x44, 0x65, 0x67};
  112. unsigned char tmp = sdl_scale;
  113. if (!f)
  114. return;
  115. fwrite(sig, 1, 4, f);
  116. save_string(f, svf_user);
  117. //save_string(f, svf_pass);
  118. save_string(f, svf_user_id);
  119. save_string(f, svf_session_id);
  120. fwrite(&tmp, 1, 1, f);
  121. tmp = cmode;
  122. fwrite(&tmp, 1, 1, f);
  123. tmp = svf_admin;
  124. fwrite(&tmp, 1, 1, f);
  125. tmp = svf_mod;
  126. fwrite(&tmp, 1, 1, f);
  127. save_string(f, http_proxy_string);
  128. tmp = SAVE_VERSION;
  129. fwrite(&tmp, 1, 1, f);
  130. tmp = MINOR_VERSION;
  131. fwrite(&tmp, 1, 1, f);
  132. tmp = do_update;
  133. fwrite(&tmp, 1, 1, f);
  134. fclose(f);
  135. }
  136. int sregexp(const char *str, char *pattern)
  137. {
  138. int result;
  139. regex_t patternc;
  140. if (regcomp(&patternc, pattern, 0)!=0)
  141. return 1;
  142. result = regexec(&patternc, str, 0, NULL, 0);
  143. regfree(&patternc);
  144. return result;
  145. }
  146. void load_presets(void)
  147. {
  148. FILE *f=fopen("powder.def", "rb");
  149. unsigned char sig[4], tmp;
  150. if (!f)
  151. return;
  152. fread(sig, 1, 4, f);
  153. if (sig[0]!=0x50 || sig[1]!=0x44 || sig[2]!=0x65)
  154. {
  155. if (sig[0]==0x4D && sig[1]==0x6F && sig[2]==0x46 && sig[3]==0x6F)
  156. {
  157. if (fseek(f, -3, SEEK_END))
  158. {
  159. remove("powder.def");
  160. return;
  161. }
  162. if (fread(sig, 1, 3, f) != 3)
  163. {
  164. remove("powder.def");
  165. goto fail;
  166. }
  167. last_major = sig[0];
  168. last_minor = sig[1];
  169. update_flag = sig[2];
  170. }
  171. fclose(f);
  172. remove("powder.def");
  173. return;
  174. }
  175. if (sig[3]==0x66) {
  176. if (load_string(f, svf_user, 63))
  177. goto fail;
  178. if (load_string(f, svf_pass, 63))
  179. goto fail;
  180. } else {
  181. if (load_string(f, svf_user, 63))
  182. goto fail;
  183. if (load_string(f, svf_user_id, 63))
  184. goto fail;
  185. if (load_string(f, svf_session_id, 63))
  186. goto fail;
  187. }
  188. svf_login = !!svf_session_id[0];
  189. if (fread(&tmp, 1, 1, f) != 1)
  190. goto fail;
  191. sdl_scale = (tmp == 2) ? 2 : 1;
  192. if (fread(&tmp, 1, 1, f) != 1)
  193. goto fail;
  194. cmode = tmp%CM_COUNT;
  195. if (fread(&tmp, 1, 1, f) != 1)
  196. goto fail;
  197. svf_admin = tmp;
  198. if (fread(&tmp, 1, 1, f) != 1)
  199. goto fail;
  200. svf_mod = tmp;
  201. if (load_string(f, http_proxy_string, 255))
  202. goto fail;
  203. if (fread(sig, 1, 3, f) != 3)
  204. goto fail;
  205. last_major = sig[0];
  206. last_minor = sig[1];
  207. update_flag = sig[2];
  208. fail:
  209. fclose(f);
  210. }
  211. void save_string(FILE *f, char *str)
  212. {
  213. int li = strlen(str);
  214. unsigned char lb[2];
  215. lb[0] = li;
  216. lb[1] = li >> 8;
  217. fwrite(lb, 2, 1, f);
  218. fwrite(str, li, 1, f);
  219. }
  220. int load_string(FILE *f, char *str, int max)
  221. {
  222. int li;
  223. unsigned char lb[2];
  224. fread(lb, 2, 1, f);
  225. li = lb[0] | (lb[1] << 8);
  226. if (li > max)
  227. {
  228. str[0] = 0;
  229. return 1;
  230. }
  231. fread(str, li, 1, f);
  232. str[li] = 0;
  233. return 0;
  234. }
  235. void strcaturl(char *dst, char *src)
  236. {
  237. char *d;
  238. unsigned char *s;
  239. for (d=dst; *d; d++) ;
  240. for (s=(unsigned char *)src; *s; s++)
  241. {
  242. if ((*s>='0' && *s<='9') ||
  243. (*s>='a' && *s<='z') ||
  244. (*s>='A' && *s<='Z'))
  245. *(d++) = *s;
  246. else
  247. {
  248. *(d++) = '%';
  249. *(d++) = hex[*s>>4];
  250. *(d++) = hex[*s&15];
  251. }
  252. }
  253. *d = 0;
  254. }
  255. void strappend(char *dst, char *src)
  256. {
  257. char *d;
  258. unsigned char *s;
  259. for (d=dst; *d; d++) ;
  260. for (s=(unsigned char *)src; *s; s++)
  261. {
  262. *(d++) = *s;
  263. }
  264. *d = 0;
  265. }
  266. void *file_load(char *fn, int *size)
  267. {
  268. FILE *f = fopen(fn, "rb");
  269. void *s;
  270. if (!f)
  271. return NULL;
  272. fseek(f, 0, SEEK_END);
  273. *size = ftell(f);
  274. fseek(f, 0, SEEK_SET);
  275. s = malloc(*size);
  276. if (!s)
  277. {
  278. fclose(f);
  279. return NULL;
  280. }
  281. fread(s, *size, 1, f);
  282. fclose(f);
  283. return s;
  284. }
  285. int cpu_check(void)
  286. {
  287. #ifdef MACOSX
  288. return 0;
  289. #else
  290. #ifdef X86
  291. unsigned af,bf,cf,df;
  292. x86_cpuid(0, af, bf, cf, df);
  293. if (bf==0x68747541 && cf==0x444D4163 && df==0x69746E65)
  294. amd = 1;
  295. x86_cpuid(1, af, bf, cf, df);
  296. #ifdef X86_SSE
  297. if (!(df&(1<<25)))
  298. return 1;
  299. #endif
  300. #ifdef X86_SSE2
  301. if (!(df&(1<<26)))
  302. return 1;
  303. #endif
  304. #ifdef X86_SSE3
  305. if (!(cf&1))
  306. return 1;
  307. #endif
  308. #endif
  309. #endif
  310. return 0;
  311. }
  312. matrix2d m2d_multiply_m2d(matrix2d m1, matrix2d m2)
  313. {
  314. matrix2d result = {
  315. m1.a*m2.a+m1.b*m2.c, m1.a*m2.b+m1.b*m2.d,
  316. m1.c*m2.a+m1.d*m2.c, m1.c*m2.b+m1.d*m2.d
  317. };
  318. return result;
  319. }
  320. vector2d m2d_multiply_v2d(matrix2d m, vector2d v)
  321. {
  322. vector2d result = {
  323. m.a*v.x+m.b*v.y,
  324. m.c*v.x+m.d*v.y
  325. };
  326. return result;
  327. }
  328. matrix2d m2d_multiply_float(matrix2d m, float s)
  329. {
  330. matrix2d result = {
  331. m.a*s, m.b*s,
  332. m.c*s, m.d*s,
  333. };
  334. return result;
  335. }
  336. vector2d v2d_multiply_float(vector2d v, float s)
  337. {
  338. vector2d result = {
  339. v.x*s,
  340. v.y*s
  341. };
  342. return result;
  343. }
  344. vector2d v2d_add(vector2d v1, vector2d v2)
  345. {
  346. vector2d result = {
  347. v1.x+v2.x,
  348. v1.y+v2.y
  349. };
  350. return result;
  351. }
  352. vector2d v2d_sub(vector2d v1, vector2d v2)
  353. {
  354. vector2d result = {
  355. v1.x-v2.x,
  356. v1.y-v2.y
  357. };
  358. return result;
  359. }
  360. matrix2d m2d_new(float me0, float me1, float me2, float me3)
  361. {
  362. matrix2d result = {me0,me1,me2,me3};
  363. return result;
  364. }
  365. vector2d v2d_new(float x, float y)
  366. {
  367. vector2d result = {x, y};
  368. return result;
  369. }
  370. void clipboard_push_text(char * text)
  371. {
  372. #ifdef MACOSX
  373. PasteboardRef newclipboard;
  374. if (PasteboardCreate(kPasteboardClipboard, &newclipboard)!=noErr) return;
  375. if (PasteboardClear(newclipboard)!=noErr) return;
  376. PasteboardSynchronize(newclipboard);
  377. CFDataRef data = CFDataCreate(kCFAllocatorDefault, text, strlen(text));
  378. PasteboardPutItemFlavor(newclipboard, (PasteboardItemID)1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0);
  379. #elif defined WIN32
  380. if (OpenClipboard(NULL))
  381. {
  382. HGLOBAL cbuffer;
  383. char * glbuffer;
  384. EmptyClipboard();
  385. cbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1);
  386. glbuffer = (char*)GlobalLock(cbuffer);
  387. strcpy(glbuffer, text);
  388. GlobalUnlock(cbuffer);
  389. SetClipboardData(CF_TEXT, cbuffer);
  390. CloseClipboard();
  391. }
  392. #elif (defined(LIN32) || defined(LIN64)) && defined(SDL_VIDEO_DRIVER_X11)
  393. if (clipboard_text!=NULL) {
  394. free(clipboard_text);
  395. clipboard_text = NULL;
  396. }
  397. clipboard_text = mystrdup(text);
  398. sdl_wminfo.info.x11.lock_func();
  399. XSetSelectionOwner(sdl_wminfo.info.x11.display, XA_CLIPBOARD, sdl_wminfo.info.x11.window, CurrentTime);
  400. XFlush(sdl_wminfo.info.x11.display);
  401. sdl_wminfo.info.x11.unlock_func();
  402. #else
  403. printf("Not implemented: put text on clipboard \"%s\"\n", text);
  404. #endif
  405. }
  406. char * clipboard_pull_text()
  407. {
  408. #ifdef MACOSX
  409. #elif defined WIN32
  410. if (OpenClipboard(NULL))
  411. {
  412. HANDLE cbuffer;
  413. char * glbuffer;
  414. cbuffer = GetClipboardData(CF_TEXT);
  415. glbuffer = (char*)GlobalLock(cbuffer);
  416. GlobalUnlock(cbuffer);
  417. CloseClipboard();
  418. if(glbuffer!=NULL){
  419. return mystrdup(glbuffer);
  420. } else {
  421. return "";
  422. }
  423. }
  424. #elif (defined(LIN32) || defined(LIN64)) && defined(SDL_VIDEO_DRIVER_X11)
  425. #else
  426. printf("Not implemented: get text from clipboard\n");
  427. return "";
  428. #endif
  429. }
  430. int register_extension()
  431. {
  432. #if defined WIN32
  433. LONG rresult;
  434. HKEY newkey;
  435. char *currentfilename = exe_name();
  436. char *iconname = NULL;
  437. char *opencommand = NULL;
  438. iconname = malloc(strlen(currentfilename)+6);
  439. opencommand = malloc(strlen(currentfilename)+13);
  440. sprintf(iconname, "%s,-102", currentfilename);
  441. sprintf(opencommand, "\"%s\" open \"%%1\"", currentfilename);
  442. //Create extension entry
  443. rresult = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes\\.cps", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &newkey, NULL);
  444. if (rresult != ERROR_SUCCESS) {
  445. return 0;
  446. }
  447. rresult = RegSetValueEx(newkey, 0, 0, REG_SZ, (LPBYTE)"PowderToySave", strlen("PowderToySave")+1);
  448. if (rresult != ERROR_SUCCESS) {
  449. RegCloseKey(newkey);
  450. return 0;
  451. }
  452. RegCloseKey(newkey);
  453. rresult = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes\\.stm", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &newkey, NULL);
  454. if (rresult != ERROR_SUCCESS) {
  455. return 0;
  456. }
  457. rresult = RegSetValueEx(newkey, 0, 0, REG_SZ, (LPBYTE)"PowderToySave", strlen("PowderToySave")+1);
  458. if (rresult != ERROR_SUCCESS) {
  459. RegCloseKey(newkey);
  460. return 0;
  461. }
  462. RegCloseKey(newkey);
  463. //Create program entry
  464. rresult = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes\\PowderToySave", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &newkey, NULL);
  465. if (rresult != ERROR_SUCCESS) {
  466. return 0;
  467. }
  468. rresult = RegSetValueEx(newkey, 0, 0, REG_SZ, (LPBYTE)"Powder Toy Save", strlen("Powder Toy Save")+1);
  469. if (rresult != ERROR_SUCCESS) {
  470. RegCloseKey(newkey);
  471. return 0;
  472. }
  473. RegCloseKey(newkey);
  474. //Set DefaultIcon
  475. rresult = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes\\PowderToySave\\DefaultIcon", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &newkey, NULL);
  476. if (rresult != ERROR_SUCCESS) {
  477. return 0;
  478. }
  479. rresult = RegSetValueEx(newkey, 0, 0, REG_SZ, (LPBYTE)iconname, strlen(iconname)+1);
  480. if (rresult != ERROR_SUCCESS) {
  481. RegCloseKey(newkey);
  482. return 0;
  483. }
  484. RegCloseKey(newkey);
  485. //Set Launch command
  486. rresult = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes\\PowderToySave\\shell\\open\\command", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &newkey, NULL);
  487. if (rresult != ERROR_SUCCESS) {
  488. return 0;
  489. }
  490. rresult = RegSetValueEx(newkey, 0, 0, REG_SZ, (LPBYTE)opencommand, strlen(opencommand)+1);
  491. if (rresult != ERROR_SUCCESS) {
  492. RegCloseKey(newkey);
  493. return 0;
  494. }
  495. RegCloseKey(newkey);
  496. if(iconname) free(iconname);
  497. if(opencommand) free(opencommand);
  498. if(currentfilename) free(currentfilename);
  499. return 1;
  500. #elif defined(LIN32) || defined(LIN64)
  501. char *currentfilename = exe_name();
  502. FILE *f;
  503. char *mimedata =
  504. "<?xml version=\"1.0\"?>\n"
  505. " <mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>\n"
  506. " <mime-type type=\"application/vnd.powdertoy.save\">\n"
  507. " <comment>Powder Toy save</comment>\n"
  508. " <glob pattern=\"*.cps\"/>\n"
  509. " <glob pattern=\"*.stm\"/>\n"
  510. " </mime-type>\n"
  511. "</mime-info>\n";
  512. f = fopen("powdertoy-save.xml", "wb");
  513. if (!f)
  514. return 0;
  515. fwrite(mimedata, 1, strlen(mimedata), f);
  516. fclose(f);
  517. char *desktopfiledata_tmp =
  518. "[Desktop Entry]\n"
  519. "Type=Application\n"
  520. "Name=Powder Toy\n"
  521. "Comment=Physics sandbox game\n"
  522. "MimeType=application/vnd.powdertoy.save;\n"
  523. "NoDisplay=true\n";
  524. char *desktopfiledata = malloc(strlen(desktopfiledata_tmp)+strlen(currentfilename)+100);
  525. strcpy(desktopfiledata, desktopfiledata_tmp);
  526. strappend(desktopfiledata, "Exec=");
  527. strappend(desktopfiledata, currentfilename);
  528. strappend(desktopfiledata, " open %f\n");
  529. f = fopen("powdertoy-tpt.desktop", "wb");
  530. if (!f)
  531. return 0;
  532. fwrite(desktopfiledata, 1, strlen(desktopfiledata), f);
  533. fclose(f);
  534. system("xdg-mime install powdertoy-save.xml");
  535. system("xdg-desktop-menu install powdertoy-tpt.desktop");
  536. f = fopen("powdertoy-save-32.png", "wb");
  537. if (!f)
  538. return 0;
  539. fwrite(icon_doc_32_png, 1, sizeof(icon_doc_32_png), f);
  540. fclose(f);
  541. f = fopen("powdertoy-save-16.png", "wb");
  542. if (!f)
  543. return 0;
  544. fwrite(icon_doc_16_png, 1, sizeof(icon_doc_16_png), f);
  545. fclose(f);
  546. system("xdg-icon-resource install --noupdate --context mimetypes --size 32 powdertoy-save-32.png application-vnd.powdertoy.save");
  547. system("xdg-icon-resource install --noupdate --context mimetypes --size 16 powdertoy-save-16.png application-vnd.powdertoy.save");
  548. system("xdg-icon-resource forceupdate");
  549. system("xdg-mime default powdertoy-tpt.desktop application/vnd.powdertoy.save");
  550. unlink("powdertoy-save-32.png");
  551. unlink("powdertoy-save-16.png");
  552. unlink("powdertoy-save.xml");
  553. unlink("powdertoy-tpt.desktop");
  554. return 1;
  555. #elif defined MACOSX
  556. return 0;
  557. #endif
  558. }
  559. void HSV_to_RGB(int h,int s,int v,int *r,int *g,int *b)//convert 0-255(0-360 for H) HSV values to 0-255 RGB
  560. {
  561. float hh, ss, vv, c, x;
  562. int m;
  563. hh = h/60.0f;//normalize values
  564. ss = s/255.0f;
  565. vv = v/255.0f;
  566. c = vv * ss;
  567. x = c * ( 1 - fabs(fmod(hh,2.0) -1) );
  568. if(hh<1){
  569. *r = (int)(c*255.0);
  570. *g = (int)(x*255.0);
  571. *b = 0;
  572. }
  573. else if(hh<2){
  574. *r = (int)(x*255.0);
  575. *g = (int)(c*255.0);
  576. *b = 0;
  577. }
  578. else if(hh<3){
  579. *r = 0;
  580. *g = (int)(c*255.0);
  581. *b = (int)(x*255.0);
  582. }
  583. else if(hh<4){
  584. *r = 0;
  585. *g = (int)(x*255.0);
  586. *b = (int)(c*255.0);
  587. }
  588. else if(hh<5){
  589. *r = (int)(x*255.0);
  590. *g = 0;
  591. *b = (int)(c*255.0);
  592. }
  593. else if(hh<6){
  594. *r = (int)(c*255.0);
  595. *g = 0;
  596. *b = (int)(x*255.0);
  597. }
  598. m = (int)((vv-c)*255.0);
  599. *r += m;
  600. *g += m;
  601. *b += m;
  602. }
  603. void RGB_to_HSV(int r,int g,int b,int *h,int *s,int *v)//convert 0-255 RGB values to 0-255(0-360 for H) HSV
  604. {
  605. float rr, gg, bb, a,x,c,d;
  606. rr = r/255.0f;//normalize values
  607. gg = g/255.0f;
  608. bb = b/255.0f;
  609. a = fmin(rr,gg);
  610. a = fmin(a,bb);
  611. x = fmax(rr,gg);
  612. x = fmax(x,bb);
  613. if (a==x)//greyscale
  614. {
  615. *h = 0;
  616. *s = 0;
  617. *v = (int)(a*255.0);
  618. }
  619. else
  620. {
  621. c = (rr==a) ? gg-bb : ((bb==a) ? rr-gg : bb-rr);
  622. d = (rr==a) ? 3 : ((bb==a) ? 1 : 5);
  623. *h = (int)(60.0*(d - c/(x - a)));
  624. *s = (int)(255.0*((x - a)/x));
  625. *v = (int)(255.0*x);
  626. }
  627. }
  628. void membwand(void * destv, void * srcv, size_t destsize, size_t srcsize)
  629. {
  630. size_t i;
  631. unsigned char * dest = destv;
  632. unsigned char * src = srcv;
  633. for(i = 0; i < destsize; i++){
  634. dest[i] = dest[i] & src[i%srcsize];
  635. }
  636. }
  637. vector2d v2d_zero = {0,0};
  638. matrix2d m2d_identity = {1,0,0,1};