1 /* -copyright-
2 #-#
3 #-# xsnow: let it snow on your desktop
4 #-# Copyright (C) 1984,1988,1990,1993-1995,2000-2001 Rick Jansen
5 #-# 2019,2020,2021 Willem Vermin
6 #-#
7 #-# This program is free software: you can redistribute it and/or modify
8 #-# it under the terms of the GNU General Public License as published by
9 #-# the Free Software Foundation, either version 3 of the License, or
10 #-# (at your option) any later version.
11 #-#
12 #-# This program is distributed in the hope that it will be useful,
13 #-# but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 #-# GNU General Public License for more details.
16 #-#
17 #-# You should have received a copy of the GNU General Public License
18 #-# along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #-#
20 */
21 #include <stdio.h>
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <stdlib.h>
25 #include <X11/Intrinsic.h>
26 #include <unistd.h>
27 #include <sys/stat.h>
28 #include "xsnow.h"
29 #include "utils.h"
30 #include "windows.h"
31 #include "meteo.h"
32 #include "debug.h"
33 #include "version.h"
34 #include "flags.h"
35
36
37 #ifdef TRACEBACK_AVAILALBLE
traceback()38 void traceback()
39 {
40 // see man backtrace
41 #define BT_BUF_SIZE 100
42 void *buffer[BT_BUF_SIZE];
43 int nptrs = backtrace(buffer, BT_BUF_SIZE);
44 backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO);
45 }
46 #endif
47
IsReadableFile(char * path)48 int IsReadableFile(char *path)
49 {
50 if (!path || access(path,R_OK) != 0)
51 return 0;
52 struct stat path_stat;
53 stat(path,&path_stat);
54 return S_ISREG(path_stat.st_mode);
55 }
56
HomeOpen(const char * file,const char * mode,char ** path)57 FILE *HomeOpen(const char *file,const char *mode, char **path)
58 {
59 char *h = getenv("HOME");
60 if (h == NULL)
61 return NULL;
62 char *home = strdup(h);
63 (*path) = (char *) malloc(strlen(home)+strlen(file)+2);
64 strcpy(*path,home);
65 strcat(*path,"/");
66 strcat(*path,file);
67 FILE *f = fopen(*path,mode);
68 free(home);
69 return f;
70 }
71
ClearScreen()72 void ClearScreen()
73 {
74 // remove all our snow-related drawings
75 XClearArea(global.display, global.SnowWin, 0,0,0,0,True);
76 // Yes this is hairy: also remove meteorite.
77 // It could be that a meteor region is still hanging around
78 meteo_erase();
79 XFlush(global.display);
80
81 }
82
mywrite(int fd,const void * buf,size_t count)83 ssize_t mywrite(int fd, const void *buf, size_t count)
84 {
85 const size_t m = 4096; // max per write
86 size_t w = 0; // # written chars
87 char *b = (char *)buf;
88
89 while (w < count)
90 {
91 size_t l = count - w;
92 if (l > m)
93 l = m;
94 ssize_t x = write(fd, b+w, l);
95 if (x < 0)
96 return -1;
97 w += x;
98 }
99 return 0;
100 }
101
myXClearArea(Display * dsp,Window win,int x,int y,int w,int h,int exposures)102 void myXClearArea(Display*dsp, Window win, int x, int y, int w, int h, int exposures)
103 {
104 if (w == 0 || h == 0 || w<0 || h<0 || w>20000 || h>20000)
105 {
106 P("myXClearArea: %d %d %d %d %d\n",x,y,w,h,exposures);
107 #ifdef TRACEBACK_AVAILALBLE
108 traceback();
109 #endif
110 return;
111 }
112 XClearArea(dsp, win, x,y,w,h,exposures);
113 }
114
sq3(float x,float y,float z)115 float sq3(float x, float y, float z)
116 {
117 return x*x + y*y + z*z;
118 }
119
sq2(float x,float y)120 float sq2(float x, float y)
121 {
122 return x*x + y*y;
123 }
124
fsignf(float x)125 float fsignf(float x)
126 {
127 if (x>0)
128 return 1.0f;
129 if (x<0)
130 return -1.0f;
131 return 0.0f;
132 }
133
ValidColor(const char * colorName)134 int ValidColor(const char *colorName)
135 {
136 XColor scrncolor;
137 XColor exactcolor;
138 int scrn = DefaultScreen(global.display);
139 return (XAllocNamedColor(global.display, DefaultColormap(global.display, scrn),
140 colorName, &scrncolor, &exactcolor));
141 }
142
AllocNamedColor(const char * colorName,Pixel dfltPix)143 Pixel AllocNamedColor(const char *colorName, Pixel dfltPix)
144 {
145 XColor scrncolor;
146 XColor exactcolor;
147 int scrn = DefaultScreen(global.display);
148 if (XAllocNamedColor(global.display, DefaultColormap(global.display, scrn),
149 colorName, &scrncolor, &exactcolor))
150 return scrncolor.pixel;
151 else
152 return dfltPix;
153 }
154
IAllocNamedColor(const char * colorName,Pixel dfltPix)155 Pixel IAllocNamedColor(const char *colorName, Pixel dfltPix)
156 {
157 return AllocNamedColor(colorName, dfltPix) | 0xff000000;
158 }
159
randint(int m)160 int randint(int m)
161 {
162 if (m <=0 )
163 return 0;
164 return drand48()*m;
165 }
166 // https://www.alanzucconi.com/2015/09/16/how-to-sample-from-a-gaussian-distribution/
167 // Interesting but not used now in xsnow
gaussian(double mean,double std,double min,double max)168 double gaussian (double mean, double std, double min, double max)
169 {
170 double x;
171 do {
172 double v1, v2, s;
173 do {
174 v1 = 2.0 * drand48() - 1.0;
175 v2 = 2.0 * drand48() - 1.0;
176 s = v1 * v1 + v2 * v2;
177 } while (s >= 1.0 || s == 0);
178 x = mean + v1 * sqrt((-2.0 * log(s)) / s) * std;
179 } while (x < min || x > max);
180 return x;
181 }
182
add_to_mainloop(gint prio,float time,GSourceFunc func)183 guint add_to_mainloop(gint prio,float time,GSourceFunc func)
184 {
185 return g_timeout_add_full(prio,(int)1000*(time),func,NULL,NULL);
186 }
187
add_to_mainloop1(gint prio,float time,GSourceFunc func,gpointer datap)188 guint add_to_mainloop1(gint prio,float time,GSourceFunc func,gpointer datap)
189 {
190 return g_timeout_add_full(prio,(int)1000*(time),func,datap,NULL);
191 }
192
remove_from_mainloop(guint * tag)193 void remove_from_mainloop(guint *tag)
194 {
195 if (*tag)
196 g_source_remove(*tag);
197 *tag = 0;
198 }
199
is_little_endian(void)200 int is_little_endian(void)
201 {
202 volatile int endiantest = 1;
203 return (*(char *)&endiantest) == 1;
204 }
205
my_cairo_paint_with_alpha(cairo_t * cr,double alpha)206 void my_cairo_paint_with_alpha(cairo_t *cr, double alpha)
207 {
208 if (alpha > 0.9)
209 cairo_paint(cr);
210 else
211 cairo_paint_with_alpha(cr,alpha);
212 P("%d alpha %f\n",global.counter++,alpha);
213 }
214
PrintVersion()215 void PrintVersion()
216 {
217 printf("%s\n%s\n",
218 PACKAGE_STRING, VERSIONBY);
219 }
220
rgba2color(GdkRGBA * c,char ** s)221 void rgba2color(GdkRGBA *c, char **s)
222 {
223 *s = (char *)malloc(8);
224 sprintf(*s,"#%02lx%02lx%02lx",lrint(c->red*255),lrint(c->green*255),lrint(c->blue*255));
225 }
226
Thanks(void)227 void Thanks(void)
228 {
229 if (global.HaltedByInterrupt)
230 printf("\nXsnow: Caught signal %d\n",global.HaltedByInterrupt);
231 if (strlen(global.Message))
232 printf("\n%s\n",global.Message);
233 printf("\nThank you for using xsnow\n");
234 }
235
ScaleChanged(int * prevscale)236 int ScaleChanged(int *prevscale)
237 {
238 int newscale;
239 if (*prevscale != (newscale=(int)(Flags.Scale*global.WindowScale)))
240 {
241 *prevscale = newscale;
242 return TRUE;
243 }
244 return FALSE;
245 }
246