1 /* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules.
2  * xscreensaver, Copyright (c) 1997-2018 Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or
10  * implied warranty.
11  *
12  * The definitions in this file make it possible to compile an xlockmore
13  * module into a standalone program, and thus use it with xscreensaver.
14  * By Jamie Zawinski <jwz@jwz.org> on 10-May-97; based on the ideas
15  * in the older xlock.h by Charles Hannum <mycroft@ai.mit.edu>.  (I had
16  * to redo it, since xlockmore has diverged so far from xlock...)
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif /* HAVE_CONFIG_H */
22 
23 #ifndef __STDC__
24 ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
25   /* (The ansi dependency is that we use string concatenation,
26      and cpp-based stringification of tokens.) */
27 #endif
28 
29 #include "screenhackI.h"
30 #include "xlockmoreI.h"
31 
32 # define ENTRYPOINT static
33 
34 /* Accessor macros for the ModeInfo structure
35  */
36 #define MI_DISPLAY(MI)		((MI)->dpy)
37 #define MI_WINDOW(MI)		((MI)->window)
38 #define MI_NUM_SCREENS(MI)	XLOCKMORE_NUM_SCREENS
39 #define MI_SCREEN(MI)		((MI)->screen_number)
40 #define MI_SCREENPTR(MI)	((MI)->xgwa.screen)
41 #define MI_WIN_WHITE_PIXEL(MI)	((MI)->white)
42 #define MI_WIN_BLACK_PIXEL(MI)	((MI)->black)
43 #define MI_NPIXELS(MI)		((MI)->npixels)
44 #define MI_PIXEL(MI,N)		((MI)->pixels[(N)])
45 #define MI_WIN_WIDTH(MI)	((MI)->xgwa.width)
46 #define MI_WIN_HEIGHT(MI)	((MI)->xgwa.height)
47 #define MI_WIN_DEPTH(MI)	((MI)->xgwa.depth)
48 #define MI_DEPTH(MI)		((MI)->xgwa.depth)
49 #define MI_WIN_COLORMAP(MI)	((MI)->xgwa.colormap)
50 #define MI_VISUAL(MI)		((MI)->xgwa.visual)
51 #define MI_GC(MI)		((MI)->gc)
52 #define MI_PAUSE(MI)		((MI)->pause)
53 #define MI_DELAY(MI)		((MI)->pause)
54 #define MI_WIN_IS_FULLRANDOM(MI)((MI)->fullrandom)
55 #define MI_WIN_IS_VERBOSE(MI)   (False)
56 #define MI_WIN_IS_INSTALL(MI)   (True)
57 #define MI_WIN_IS_MONO(MI)	(mono_p)
58 #define MI_WIN_IS_INROOT(MI)	((MI)->root_p)
59 #define MI_WIN_IS_INWINDOW(MI)	(!(MI)->root_p)
60 #define MI_WIN_IS_ICONIC(MI)	(False)
61 #define MI_WIN_IS_WIREFRAME(MI)	((MI)->wireframe_p)
62 #define MI_WIN_IS_USE3D(MI)	((MI)->threed)
63 #define MI_LEFT_COLOR(MI)	((MI)->threed_left_color)
64 #define MI_RIGHT_COLOR(MI)	((MI)->threed_right_color)
65 #define MI_BOTH_COLOR(MI)	((MI)->threed_both_color)
66 #define MI_NONE_COLOR(MI)	((MI)->threed_none_color)
67 #define MI_DELTA3D(MI)		((MI)->threed_delta)
68 #define MI_CYCLES(MI)		((MI)->cycles)
69 #define MI_BATCHCOUNT(MI)	((MI)->batchcount)
70 #define MI_SIZE(MI)		((MI)->size)
71 #define MI_IS_DRAWN(MI)		((MI)->is_drawn)
72 #define MI_IS_FPS(MI)		((MI)->fps_p)
73 #define MI_NCOLORS(MI)		((MI)->npixels)
74 #define MI_NAME(MI)		(progname)
75 
76 #define MI_COLORMAP(MI)	        (MI_WIN_COLORMAP((MI)))
77 #define MI_WIDTH(MI)		(MI_WIN_WIDTH((MI)))
78 #define MI_HEIGHT(MI)		(MI_WIN_HEIGHT((MI)))
79 #define MI_IS_ICONIC(MI)	(MI_WIN_IS_ICONIC((MI)))
80 #define MI_IS_WIREFRAME(MI)	(MI_WIN_IS_WIREFRAME((MI)))
81 #define MI_IS_MONO(MI)		(MI_WIN_IS_MONO((MI)))
82 #define MI_COUNT(MI)		(MI_BATCHCOUNT((MI)))
83 #define MI_BLACK_PIXEL(MI)	(MI_WIN_BLACK_PIXEL(MI))
84 #define MI_WHITE_PIXEL(MI)	(MI_WIN_WHITE_PIXEL(MI))
85 #define MI_IS_FULLRANDOM(MI)	(MI_WIN_IS_FULLRANDOM(MI))
86 #define MI_IS_VERBOSE(MI)	(MI_WIN_IS_VERBOSE(MI))
87 #define MI_IS_INSTALL(MI)	(MI_WIN_IS_INSTALL(MI))
88 #define MI_IS_DEBUG(MI)		(False)
89 #define MI_IS_MOUSE(MI)		(False)
90 
91 /* Under xlockmore, MI_CLEARWINDOW runs immediately, and for animated clears
92    it delays execution while the animation runs. This doesn't work on
93    XScreenSaver, which has mandatory double-buffering on macOS/iOS/Android.
94 
95    Tricky: As a result, MI_CLEARWINDOW doesn't clear the window until after
96    init_##() or draw_##() finishes.
97  */
98 #ifdef USE_GL
99 # define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi))
100 #else
101 # define MI_CLEARWINDOW(mi) ((mi)->needs_clear = True)
102 #endif
103 
104 /* MI_INIT and MI_ABORT are XScreenSaver extensions. These exist primarily for
105    the sake of ports to macOS, iOS, and Android, all of which need to restart
106    individual screenhacks repeatedly in the same process. This requires
107    reusing MI_SCREEN() numbers; previously many xlockmore API hacks did not
108    support this the way they were supposed to.
109  */
110 
111 /* MI_INIT implements the following pattern, as seen in various forms at the
112    beginning of init_##():
113 
114    if(!state_array) {
115      state_array = (state_t *)calloc(MI_NUM_SCREENS(mi), sizeof(state_t));
116      if(!state_array) {
117        fprintf(stderr, "%s: out of memory\n", progname);
118        return;
119      }
120    }
121    hack_free_state(mi);
122    memset(&state_array[MI_SCREEN(mi)], 0, sizeof(*state_array));
123 
124    MI_INIT also assumes ownership of the state_array over to xlockmore.c,
125    which frees it after all screens (or "screens") are closed.
126  */
127 
128 #define MI_INIT(mi, state_array) \
129   xlockmore_mi_init ((mi), sizeof(*(state_array)), (void **)&(state_array))
130 
131 /* Use MI_ABORT if an init_## or draw_## hook needs to shut everything down.
132    This replaces explicit calls to release_## hooks when things go wrong from
133    inside an xlockmore API screenhack.
134 
135    At some point this may do something other than just abort().
136  */
137 #define MI_ABORT(mi)		abort();
138 
139 #define FreeAllGL(dpy)		/* */
140 
141 /* Some other utility macros.
142  */
143 #define SINF(n)			((float)sin((double)(n)))
144 #define COSF(n)			((float)cos((double)(n)))
145 #define FABSF(n)		((float)fabs((double)(n)))
146 
147 #undef MAX
148 #undef MIN
149 #undef ABS
150 #define MAX(a,b)((a)>(b)?(a):(b))
151 #define MIN(a,b)((a)<(b)?(a):(b))
152 #define ABS(a)((a)<0 ? -(a) : (a))
153 
154 /* Maximum possible number of colors (*not* default number of colors.) */
155 #define NUMCOLORS 256
156 
157 
158 /* In an Xlib world, we define two global symbols here:
159    a struct in `MODULENAME_xscreensaver_function_table',
160    and a pointer to that in `xscreensaver_function_table'.
161 
162    In a Cocoa or Android world, we only define the prefixed symbol;
163    the un-prefixed symbol does not exist.
164  */
165 #ifdef HAVE_MOBILE
166 # define XSCREENSAVER_LINK(NAME)
167 #else
168 # define XSCREENSAVER_LINK(NAME) \
169    struct xscreensaver_function_table *xscreensaver_function_table = &NAME;
170 #endif
171 
172 
173 # if !defined(USE_GL) || defined(HAVE_COCOA) || defined(HAVE_ANDROID)
174 #  define xlockmore_pick_gl_visual 0
175 #  define xlockmore_validate_gl_visual 0
176 # endif  /* !USE_GL || HAVE_COCOA || HAVE_ANDROID */
177 
178 # ifdef USE_GL
179 #  define XLOCKMORE_FPS xlockmore_gl_compute_fps
180 #  define XLOCKMORE_FPS_FREE xlockmore_gl_free_fps
181 # else
182 #  define XLOCKMORE_FPS xlockmore_do_fps
183 #  define XLOCKMORE_FPS_FREE fps_free
184 # endif
185 
186 # ifdef HAVE_JWXYZ
187 #  ifdef USE_GL
188 #   define XLOCKMORE_VISUAL GL_VISUAL
189 #  else
190 #   define XLOCKMORE_VISUAL DEFAULT_VISUAL
191 #  endif
192 # else /* !HAVE_JWXYZ */
193 #  define XLOCKMORE_VISUAL \
194      xlockmore_pick_gl_visual, xlockmore_validate_gl_visual
195 # endif /* !HAVE_JWXYZ */
196 
197 #ifdef WRITABLE_COLORS
198 # undef WRITABLE_COLORS
199 # define WRITABLE_COLORS 1
200 #else
201 # define WRITABLE_COLORS 0
202 #endif
203 
204 #if defined(UNIFORM_COLORS)
205 # define XLOCKMORE_COLOR_SCHEME color_scheme_uniform
206 #elif defined(SMOOTH_COLORS)
207 # define XLOCKMORE_COLOR_SCHEME color_scheme_smooth
208 #elif defined(BRIGHT_COLORS)
209 # define XLOCKMORE_COLOR_SCHEME color_scheme_bright
210 #else
211 # define XLOCKMORE_COLOR_SCHEME color_scheme_default
212 #endif
213 
214 /* This is the macro that links this program in with the rest of
215    xscreensaver.  For example:
216 
217      XSCREENSAVER_MODULE   ("Atlantis", atlantis)
218      XSCREENSAVER_MODULE_2 ("GLMatrix", glmatrix, matrix)
219 
220    CLASS:   a string, the class name for resources.
221    NAME:    a token, the name of the executable.  Should be the same
222             as CLASS, but downcased.
223    PREFIX:  the symbol used in the function names, e.g., `draw_atlantis'.
224 
225    NAME and PREFIX are usually the same.  If they are not, use
226    XSCREENSAVER_MODULE_2() instead of XSCREENSAVER_MODULE().
227  */
228 #define XSCREENSAVER_MODULE_2(CLASS,NAME,PREFIX)			\
229 									\
230   static struct xlockmore_function_table				\
231 	 NAME ## _xlockmore_function_table = {			\
232 	   CLASS,							\
233 	   DEFAULTS,							\
234 	   WRITABLE_COLORS,						\
235 	   XLOCKMORE_COLOR_SCHEME,					\
236 	   init_    ## PREFIX,						\
237 	   draw_    ## PREFIX,						\
238 	   reshape_ ## PREFIX,						\
239 	   release_ ## PREFIX,						\
240 	   free_    ## PREFIX,						\
241 	   PREFIX   ## _handle_event,					\
242 	   & PREFIX ## _opts						\
243   };									\
244 									\
245   struct xscreensaver_function_table					\
246 	 NAME ## _xscreensaver_function_table = {			\
247 	   0, 0, 0,							\
248 	   xlockmore_setup,						\
249 	   & NAME ## _xlockmore_function_table,				\
250 	   0, 0, 0, 0, 0,						\
251 	   XLOCKMORE_FPS, XLOCKMORE_FPS_FREE,				\
252 	   XLOCKMORE_VISUAL };						\
253 									\
254   XSCREENSAVER_LINK (NAME ## _xscreensaver_function_table)
255 
256 #define XSCREENSAVER_MODULE(CLASS,PREFIX)				\
257       XSCREENSAVER_MODULE_2(CLASS,PREFIX,PREFIX)
258