1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/2d/RCS/chain.c $
21  * $Revision: 1.8 $
22  * $Author: kevin $
23  * $Date: 1994/12/05 21:02:35 $
24  *
25  * Routines for chaining functions to 2D primitives.
26  *
27  * This file is part of the 2D library.
28  *
29  * $Log: chain.c $
30  * Revision 1.8  1994/12/05  21:02:35  kevin
31  * Reworked to avoid linking in unused function tables.
32  *
33  * Revision 1.7  1994/12/02  21:51:39  kevin
34  * Moved chaining globals accessed in gr_set_canvas to grd.c to avoid linking in unused code.
35  *
36  * Revision 1.6  1993/12/07  11:45:15  baf
37  * Renames gr_chain_add_over
38  *
39  * Revision 1.5  1993/12/02  13:44:13  baf
40  * Added the ability to unchain and rechain.
41  *
42  * Revision 1.4  1993/11/30  20:47:08  baf
43  * Chainged generic mode stuff so it can
44  * be done at any time.
45  *
46  * Revision 1.3  1993/11/16  23:06:33  baf
47  * Added the ability to chain void functions
48  * after the primitive.
49  *
50  * Revision 1.2  1993/11/15  03:26:53  baf
51  * Added void chaining (functions that just
52  * get executed and pass on)
53  *
54  * Revision 1.1  1993/11/12  09:29:49  baf
55  * Initial revision
56  *
57  */
58 
59 #include "chain.h"
60 #include "chnfuncs.h"
61 #include "grmalloc.h"
62 #include "tabdat.h"
63 #include "bitmap.h"
64 #include "cnvtab.h"
65 #include "cnvdrv.h"
66 #include "icanvas.h"
67 #include "grnull.h"
68 
69 grs_func_chain *grd_chain_table[GRD_CANVAS_FUNCS];
70 
gr_chain_add_over(int n,void (* f)())71 grs_func_chain *gr_chain_add_over(int n, void (*f)())
72 {
73    grs_func_chain *p = (grs_func_chain *)(malloc(sizeof(grs_func_chain)));	// was gr_malloc
74    if (grd_chain_table[n] == NULL) {
75       /* First time: stash and replace primitives */
76       int k;
77       chn_primitives[n] = (void (**)())(malloc(BMT_TYPES*sizeof(void (*)())));	// was gr_malloc
78       for (k=0; k<BMT_TYPES; k++)
79           if (grd_canvas_table_list[k] != NULL)
80             chn_primitives[n][k] = grd_canvas_table_list[k][n];
81       for (k=0; k<BMT_TYPES; k++)
82           if (grd_canvas_table_list[k] != NULL)
83             grd_canvas_table_list[k][n] = chn_canvas_table[n];
84       /* The above two loops are kept apart for a reason:
85            two pointers may be the same, and we want to save the
86             initial values of them all. */
87    }
88    /* Hook into chain */
89    p->f = f;
90    p->next = grd_chain_table[n];
91    p->flags = 0;
92    grd_chain_table[n] = p;
93    return p;
94 }
95 
gr_chain_add_before(int n,void (* f)(void))96 grs_func_chain *gr_chain_add_before(int n, void (*f)(void))
97 {
98    grs_func_chain *p;
99    p = gr_chain_add_over(n, f);
100    p->flags |= 1;
101    return p;
102 }
103 
gr_chain_add_after(int n,void (* f)(void))104 grs_func_chain *gr_chain_add_after(int n, void (*f)(void))
105 {
106    grs_func_chain *p = (grs_func_chain *)(malloc(sizeof(grs_func_chain)));	// was gr_malloc
107    p->f = f;
108    p->next = NULL;
109    p->flags = CHNF_VOID | CHNF_AFTER;
110    if (grd_chain_table[n] == NULL) {
111       /* First time: stash and replace primitives */
112       int k;
113       chn_primitives[n] = (void (**)())(malloc(BMT_TYPES*sizeof(void (*)())));	// was gr_malloc
114       for (k=0; k<BMT_TYPES; k++)
115           if (grd_canvas_table_list[k] != NULL)
116             chn_primitives[n][k] = grd_canvas_table_list[k][n];
117       for (k=0; k<BMT_TYPES; k++)
118           if (grd_canvas_table_list[k] != NULL)
119             grd_canvas_table_list[k][n] = chn_canvas_table[n];
120       /* The above two loops are kept apart for a reason:
121            two pointers may be the same, and we want to save the
122             initial values of them all. */
123       grd_chain_table[n] = p;
124    }
125    else {
126       grs_func_chain *q = grd_chain_table[n];
127       while (q->next != NULL) q = q->next;
128       q->next = p;
129    }
130    return p;
131 }
132 
gr_unchain(int n)133 void gr_unchain(int n)
134 {
135    int k;
136    /* check for unchained primitive */
137    if (chn_primitives[n] == NULL) return;
138    for (k=0; k<BMT_TYPES; k++)
139       if (grd_canvas_table_list[k] != NULL)
140          grd_canvas_table_list[k][n] = chn_primitives[n][k];
141 }
142 
gr_rechain(int n)143 void gr_rechain(int n)
144 {
145    int k;
146    if (chn_primitives[n] == NULL) return;
147    for (k=0; k<BMT_TYPES; k++)
148       if (grd_canvas_table_list[k] != NULL)
149          grd_canvas_table_list[k][n] = chn_canvas_table[n];
150 }
151 
gr_unchain_all()152 void gr_unchain_all()
153 {
154    int k;
155    for (k=0; k<GRD_CANVAS_FUNCS; k++) gr_unchain(k);
156 }
157 
gr_rechain_all()158 void gr_rechain_all()
159 {
160    int k;
161    for (k=0; k<GRD_CANVAS_FUNCS; k++) gr_rechain(k);
162 }
163 
164 
165 /* This returns the next function in the rest of the current chain. */
chain_rest()166 void (*chain_rest())()
167 {
168    for (gr_current_chain = gr_current_chain->next; gr_current_chain != NULL; gr_current_chain = gr_current_chain->next) {
169       if (!(gr_current_chain->flags & CHNF_VOID))
170          return gr_current_chain->f;
171       if (gr_current_chain->flags & CHNF_AFTER) break;
172       gr_current_chain->f();
173    }
174    if (gr_current_primitive <= GET_PIXEL24 || gr_current_primitive >= CALC_ROW)
175       return chn_primitives[gr_current_primitive][grd_pixel_index];
176    return chn_primitives[gr_current_primitive][grd_canvas_index];
177 }
178 
179 #include "canvas.h"
180 #include "cnvdat.h"
181 #include "cnvdrv.h"
182 #include "fcntab.h"
183 #include "tabdrv.h"
184 #include "fill.h"
185 
gr_force_generic()186 void gr_force_generic()
187 {
188    chn_flags |= CHN_GEN;
189    grd_canvas_table_list[BMT_GEN]=gen_canvas_table;
190    grd_function_table_list[BMT_GEN]= (grt_function_table *) gen_function_table;
191    if (grd_canvas_table != NULL)
192       gr_set_canvas(grd_canvas);
193 }
194 
gr_unforce_generic()195 void gr_unforce_generic()
196 {
197    chn_flags &= ~CHN_GEN;
198    gr_set_canvas(grd_canvas);
199 }
200 
201