3
|
1 /* $Id: macros.c,v 1.1.1.1 1997/12/06 05:41:29 darius Exp $ */
|
|
2
|
|
3 /* here's pretty much all the macro code. */
|
|
4 /* This bears little resemblance to the */
|
|
5 /* BRM code, i.e. it's somewhat organized :)*/
|
|
6 /* Bill Dyess 10/05/93 [BDyess]*/
|
|
7
|
|
8 #ifdef MACROS
|
|
9 #include"copyright.h"
|
|
10 #include<stdio.h>
|
|
11 #if !defined(SVR4) && !defined(sparc)
|
|
12 #include<strings.h>
|
|
13 #else
|
|
14 #include<string.h>
|
|
15 #endif /* !SVR4 && !sparc */
|
|
16 #include<ctype.h>
|
|
17 #include<fcntl.h>
|
|
18 #include<sys/types.h>
|
|
19 #include"Wlib.h"
|
|
20 #include"data.h"
|
|
21 #include"defs.h"
|
|
22 #include"struct.h"
|
|
23 #include"gameconf.h"
|
|
24 #include"proto.h"
|
|
25
|
|
26 #define MAXMACRO 4096
|
|
27 #if defined(__STDC__) || defined(RS6K) || defined(sgi)
|
|
28 typedef signed char s_char;
|
|
29 #else
|
|
30 typedef char s_char;
|
|
31 #endif
|
|
32
|
|
33 /* prototypes */
|
|
34 void doMacro2 P((struct macro * m, W_Event * data));
|
|
35 void handle_dollar P((char **locpntr, char **destpntr, W_Event * data));
|
|
36 void handle_special P((char **locpntr, char **destpntr, W_Event * data));
|
|
37 char *strtoupper P((char *buf));
|
|
38 char *strtolower P((char *buf));
|
|
39 void handle_test P((char **locpntr, char **destpntr, W_Event * data));
|
|
40 void handle_conditional P((char **locpntr, char **destpntr, W_Event * data));
|
|
41 void getTestString P((char *buf, char **locpntr, char **destpntr, W_Event * data));
|
|
42 void getConditionalString P((char **locpntr, char **destpntr, W_Event * data));
|
|
43 void ignoreConditionalString P((char **locpntr));
|
|
44
|
|
45 int abortflag = 0;
|
|
46
|
|
47 void
|
|
48 initMacros()
|
|
49 {
|
|
50 struct stringlist *s;
|
|
51 char *loc;
|
|
52 unsigned char ch;
|
|
53 struct macro *m;
|
|
54 int i;
|
|
55 struct dmacro_list *dm;
|
|
56 struct dmacro_list *dm_def;
|
|
57 int notdone;
|
|
58 unsigned char c;
|
|
59 char *str;
|
|
60
|
|
61 /* initialize macro lookup tables */
|
|
62 bzero(macrotable, sizeof(struct macro *) * 256);
|
|
63
|
|
64 #ifdef RC_DISTRESS
|
|
65 /* sizeof doesn't work if it isn't in the same source file, shoot me */
|
|
66 MCOPY(dist_defaults, dist_prefered, sizedist);
|
|
67 #endif
|
|
68
|
|
69 for (s = defaults; s; s = s->next) {
|
|
70 #ifdef RC_DISTRESS
|
|
71 if (strncmpi(s->string, "dist.", 5) == 0) {
|
|
72 str = (s->string) + 5;
|
|
73 if (*str == '^') {
|
|
74 str++;
|
|
75 if (*str == '^')
|
|
76 c = '^';
|
|
77 else
|
|
78 c = *str + 128;
|
|
79 } else
|
|
80 c = *str;
|
|
81 str++;
|
|
82 if (*str != '.') {
|
|
83 str = (s->string) + 4;
|
|
84 c = '\0';
|
|
85 }
|
|
86 str++;
|
|
87
|
|
88 notdone = 1;
|
|
89 for (dm = &dist_prefered[take], dm_def = &dist_defaults[take], i = take;
|
|
90 dm->name && notdone; dm++, dm_def++, i++) {
|
|
91 if (strcmpi(str, dm->name) == 0) {
|
|
92 dm->macro = strdup(s->value);
|
|
93 if (c) {
|
|
94 if (!macrotable[c]) {
|
|
95 macrotable[c] = (struct macro *) malloc(sizeof(struct macro));
|
|
96 bzero(macrotable[c], sizeof(struct macro));
|
|
97 }
|
|
98 macrotable[c]->flags |= MACRCD;
|
|
99 macrotable[c]->to = i;
|
|
100 /* printf("dist.%c.%s: %s\n",c,dm->name,dm->macro);*/
|
|
101 dm->c = c;
|
|
102 dm_def->c = c;
|
|
103 }
|
|
104 notdone = 0;
|
|
105 }
|
|
106 }
|
|
107 }
|
|
108 #endif /* RC_DISTRESS */
|
|
109 #ifdef BEEPLITE
|
|
110
|
|
111 else if (strncmpi(s->string, "lite.", 5) == 0) {
|
|
112 int offset = 5;
|
|
113 char **lt;
|
|
114
|
|
115 if (s->string[6] == '.')
|
|
116 offset = 7;
|
|
117
|
|
118 notdone = 1;
|
|
119
|
|
120 for (lt = &distlite[take], dm = &dist_prefered[take];
|
|
121 dm->name && notdone; dm++, lt++) {
|
|
122 if (strcmpi(s->string + offset, dm->name) == 0) {
|
|
123 *lt = strdup(s->value);
|
|
124 /* printf("lite.%s: %s\n",dm->name,*lt);*/
|
|
125
|
|
126 notdone = 0;
|
|
127 }
|
|
128 }
|
|
129 if (notdone)
|
|
130 fprintf(stderr, "Unknown lite %s\n", s->string + offset);
|
|
131 }
|
|
132 #endif /* BEEPLITE */
|
|
133 if (!strncmpi("mac", s->string, 3)) {
|
|
134 if (s->string[3] == '.')
|
|
135 loc = s->string + 4;
|
|
136 else if (strncmpi("ro.", s->string + 3, 3))
|
|
137 continue;
|
|
138 else
|
|
139 loc = s->string + 6;
|
|
140 if (*loc == '^') { /* possible control char */
|
|
141 loc++;
|
|
142 if (*loc == '^' && *loc)
|
|
143 ch = '^';
|
|
144 else
|
|
145 ch = *loc + 128;
|
|
146 } else
|
|
147 ch = *loc;
|
|
148 loc++;
|
|
149 if (!macrotable[ch]) {
|
|
150 /*
|
|
151 make sure it doesn't already exist. I've allowed people
|
|
152 to have singlemacro: before the macro.*.* statements, so
|
|
153 it is possible
|
|
154 */
|
|
155 /*
|
|
156 modified to allow multline macros by creating a linked
|
|
157 list of macro structures. -JR
|
|
158 */
|
|
159 if (ch == '?') {
|
|
160 printf("Can't use '?' as a macro. It is reserved for the macro window. Ignoring.\n");
|
|
161 continue;
|
|
162 }
|
|
163 macrotable[ch] = m = (struct macro *) malloc(sizeof(struct macro));
|
|
164 bzero(m, sizeof(struct macro));
|
|
165 } else {
|
|
166 #ifdef RC_DISTRESS
|
|
167 if (macrotable[ch]->flags & MACRCD) {
|
|
168 m = macrotable[ch];
|
|
169 m->flags &= ~(MACRCD); /* in case singleMacro was
|
|
170 set */
|
|
171 m->next = 0;
|
|
172 } else
|
|
173 #endif
|
|
174 {
|
|
175 m = (struct macro *) malloc(sizeof(struct macro));
|
|
176 m->next = macrotable[ch];
|
|
177 macrotable[ch] = m;
|
|
178 m->next->flags |= MACMULTI;
|
|
179 m->flags = m->next->flags;
|
|
180 }
|
|
181 }
|
|
182 if (*(loc++) != '.')
|
|
183 m->to = -2; /* no destination given */
|
|
184 else {
|
|
185 ch = *loc;
|
|
186 if (ch == '%') {
|
|
187 m->specialto = toupper(*(loc + 1));
|
|
188 m->to = -1;
|
|
189 } else {
|
|
190 m->to = ch;
|
|
191 }
|
|
192 }
|
|
193 m->string = strdup(s->value);
|
|
194 } else if (!strncmpi("singlemacro", s->string, 11)) {
|
|
195 loc = s->value;
|
|
196 while (*loc) {
|
|
197 ch = *(loc++);
|
|
198 if (ch == '^') {/* for control chars */
|
|
199 if (*loc != '^' && *loc)
|
|
200 ch = *loc + 128;
|
|
201 loc++;
|
|
202 }
|
|
203 if (!macrotable[ch]) {
|
|
204 m = macrotable[ch] = (struct macro *) malloc(sizeof(struct macro));
|
|
205 bzero(m, sizeof(struct macro));
|
|
206 m->flags = MACSINGLE;
|
|
207 } else {
|
|
208 for (m = macrotable[ch]; m; m = m->next)
|
|
209 m->flags |= MACSINGLE;
|
|
210 }
|
|
211 }
|
|
212 }
|
|
213 }
|
|
214 for (i = 0; i < 256; i++) {
|
|
215 /* eliminate any macros that have (null) macro strings */
|
|
216 if (macrotable[i] && !(macrotable[i]->flags & MACRCD)) {
|
|
217 struct macro *tmp, **scan;
|
|
218
|
|
219 scan=¯otable[i];
|
|
220 while (*scan) {
|
|
221 if ( (*scan)->string ) {
|
|
222 scan = &(*scan)->next;
|
|
223 } else {
|
|
224 tmp = (*scan);
|
|
225 *scan = tmp->next;
|
|
226 free(tmp);
|
|
227 }
|
|
228 }
|
|
229 }
|
|
230 }
|
|
231 #ifdef RC_DISTRESS
|
|
232 /*
|
|
233 make macro entries for the default RCD keys, if those keys don't have
|
|
234 macros defined
|
|
235 */
|
|
236 for (dm = &dist_prefered[take], i = take; dm->name; dm++, i++) {
|
|
237 if (!macrotable[dm->c]) {
|
|
238 macrotable[dm->c] = (struct macro *) malloc(sizeof(struct macro));
|
|
239 bzero(macrotable[dm->c], sizeof(struct macro));
|
|
240 macrotable[dm->c]->flags = MACRCD;
|
|
241 macrotable[dm->c]->to = i;
|
|
242 }
|
|
243 }
|
|
244 #endif
|
|
245 }
|
|
246
|
|
247 void
|
|
248 doMacro(data)
|
|
249 W_Event *data;
|
|
250 /* takes a key as input and creates a string that is then sent to smessage*/
|
|
251 {
|
|
252 static struct macro *m;
|
|
253 int key = data->key;
|
|
254
|
|
255 if (key == '?') {
|
|
256 showMacroWin();
|
|
257 macroState = 0;
|
|
258 return;
|
|
259 }
|
|
260 if (macroState != 2)
|
|
261 m = macrotable[key];
|
|
262 if (!m) {
|
|
263 W_Beep();
|
|
264 warning("No such macro");
|
|
265 macroState = 0;
|
|
266 return; /* no macro */
|
|
267 }
|
|
268 #ifdef RC_DISTRESS
|
|
269 if (m->flags & MACRCD) {
|
|
270 rcd(m->to, data);
|
|
271 macroState = 0;
|
|
272 return;
|
|
273 }
|
|
274 #endif
|
|
275 while (m) {
|
|
276 if (macroState == 2) {
|
|
277 m->to = key;
|
|
278 doMacro2(m, data);
|
|
279 m->to = -2;
|
|
280 } else {
|
|
281 doMacro2(m, data);
|
|
282 if (macroState == 2)
|
|
283 return;
|
|
284 }
|
|
285 m = m->next;
|
|
286 }
|
|
287 macroState = 0;
|
|
288 warning(" ");
|
|
289 }
|
|
290
|
|
291 void
|
|
292 doMacro2(m, data)
|
|
293 struct macro *m;
|
|
294 W_Event *data;
|
|
295 {
|
|
296 int group = -1, recip = 0;
|
|
297 char buf[MAXMACRO], sourcebuf[MAXMACRO];
|
|
298 char *loc, *dest;
|
|
299 struct obtype *target;
|
|
300
|
|
301 /* first figure out who I'm going to send it to */
|
|
302 if ((s_char)m->to == -1) { /* special recipient */
|
|
303 switch (m->specialto) {
|
|
304 case 'I': /* send a message to myself */
|
|
305 case 'C':
|
|
306 group = MINDIV;
|
|
307 recip = me->p_no;
|
|
308 break;
|
|
309 case 'U': /* send message to player nearest mouse */
|
|
310 case 'P':
|
|
311 group = MINDIV;
|
|
312 target = gettarget(data->Window, data->x, data->y, TARG_PLAYER);
|
|
313 recip = target->o_num;
|
|
314 break;
|
|
315 case 'T': /* send message to team of the player nearest
|
|
316 mouse */
|
|
317 case 'Z':
|
|
318 group = MTEAM;
|
|
319 target = gettarget(data->Window, data->x, data->y, TARG_PLAYER);
|
|
320 recip = idx_to_mask(players[target->o_num].p_teami);
|
|
321 break;
|
|
322 case 'G': /* send message to nearest friendly player to
|
|
323 my ship */
|
|
324 group = MINDIV;
|
|
325 target = gettarget((W_Window) 0, me->p_x, me->p_y,
|
|
326 TARG_PLAYER | TARG_FRIENDLY);
|
|
327 recip = target->o_num;
|
|
328 break;
|
|
329 case 'H': /* send message to nearest enemy player to my
|
|
330 ship */
|
|
331 group = MINDIV;
|
|
332 target = gettarget((W_Window) 0, me->p_x, me->p_y,
|
|
333 TARG_PLAYER | TARG_ENEMY);
|
|
334 recip = target->o_num;
|
|
335 break;
|
|
336 default:
|
|
337 warning("Bad macro - incorrect 'to' field");
|
|
338 break;
|
|
339 }
|
|
340 } else if ((s_char)m->to == -2) { /* get recipient not provided, so change
|
|
341 state to get one */
|
|
342 macroState = 2;
|
|
343 warning("Send macro to who?");
|
|
344 return;
|
|
345 } else
|
|
346 recip = m->to;
|
|
347 /* now parse the macro itself. */
|
|
348 strcpy(sourcebuf, m->string);
|
|
349 loc = sourcebuf;
|
|
350 dest = buf;
|
|
351 while (*loc) {
|
|
352 if (*loc == '$') {
|
|
353 loc++;
|
|
354 handle_dollar(&loc, &dest, data); /* handle the special escape */
|
|
355 } else if (*loc == '%') {
|
|
356 loc++;
|
|
357 if (*loc == '*')
|
|
358 return; /* %* means exit macro NOW */
|
|
359 handle_special(&loc, &dest, data); /* handle the special escape */
|
|
360 } else {
|
|
361 *(dest++) = *(loc++);
|
|
362 }
|
|
363 }
|
|
364 *dest = 0;
|
|
365 if (buf[0] == 0 || abortflag) { /* abortflag means somewhere there
|
|
366 was a %* */
|
|
367 abortflag = 0;
|
|
368 macroState = 0;
|
|
369 return; /* null message. If you *really* want to
|
|
370 print a null message, use <space> */
|
|
371 }
|
|
372 if (group == -1)
|
|
373 group = getgroup(recip, &recip);
|
|
374 if (group <= 0)
|
|
375 return;
|
|
376 if ((m->flags & MACMULTI) && (F_multiline_enabled || paradise))
|
|
377 group |= MMACRO;
|
|
378 pmessage(buf, recip, group);
|
|
379 }
|
|
380
|
|
381 void
|
|
382 handle_special(locpntr, destpntr, data)
|
|
383 char **locpntr, **destpntr;
|
|
384 W_Event *data;
|
|
385 {
|
|
386 char ch = **locpntr;
|
|
387 char *buf = *destpntr;
|
|
388 struct obtype *target;
|
|
389 struct macro *m;
|
|
390 int targettype = 0;
|
|
391 struct id *id;
|
|
392 /* for pingstats */
|
|
393 #if 0
|
|
394 extern int ping_iloss_sc; /* inc % loss 0--100, server to client */
|
|
395 extern int ping_iloss_cs; /* inc % loss 0--100, client to server */
|
|
396 #endif /* 0 */
|
|
397 extern int ping_tloss_sc; /* total % loss 0--100, server to client */
|
|
398 extern int ping_tloss_cs; /* total % loss 0--100, client to server */
|
|
399 #if 0
|
|
400 extern int ping_lag; /* delay in ms of last ping */
|
|
401 #endif /* 0 */
|
|
402 extern int ping_av; /* average rt */
|
|
403 extern int ping_sd; /* standard deviation */
|
|
404
|
|
405 switch (ch) {
|
|
406 case 'a': /* armies carried by sender */
|
|
407 sprintf(buf, "%d", me->p_armies);
|
|
408 break;
|
|
409 case 'd': /* sender damage percentage */
|
|
410 sprintf(buf, "%d", 100 * me->p_damage / me->p_ship->s_maxdamage);
|
|
411 break;
|
|
412 case 's': /* sender shield percentage */
|
|
413 sprintf(buf, "%d", 100 * me->p_shield / me->p_ship->s_maxshield);
|
|
414 break;
|
|
415 case 'f': /* sender fuel percentage */
|
|
416 sprintf(buf, "%d", 100 * me->p_fuel / me->p_ship->s_maxfuel);
|
|
417 break;
|
|
418 case 'w': /* sender wtemp percentage */
|
|
419 sprintf(buf, "%d", 100 * me->p_wtemp / me->p_ship->s_maxwpntemp);
|
|
420 break;
|
|
421 case 'e': /* sender etemp percentage */
|
|
422 sprintf(buf, "%d", 100 * me->p_etemp / me->p_ship->s_maxegntemp);
|
|
423 break;
|
|
424 case 'r': /* team id character of target player */
|
|
425 target = gettarget(data->Window, data->x, data->y, TARG_PLAYER);
|
|
426 buf[0] = teaminfo[players[target->o_num].p_teami].letter;
|
|
427 buf[1] = 0;
|
|
428 break;
|
|
429 case 't': /* team id character of target planet */
|
|
430 target = gettarget(data->Window, data->x, data->y, TARG_PLANET);
|
|
431 buf[0] = teaminfo[mask_to_idx(planets[target->o_num].pl_owner)].letter;
|
|
432 buf[1] = 0;
|
|
433 break;
|
|
434 case 'p': /* id character of target player */
|
|
435 targettype = TARG_PLAYER;
|
|
436 case 'g': /* id character of target friendly player */
|
|
437 if (!targettype)
|
|
438 targettype = TARG_PLAYER | TARG_FRIENDLY;
|
|
439 case 'h': /* id char of target enemy player */
|
|
440 if (!targettype)
|
|
441 targettype = TARG_PLAYER | TARG_ENEMY;
|
|
442 id = getTargetID(data->Window, data->x, data->y, targettype);
|
|
443 buf[0] = id->mapstring[1];
|
|
444 buf[1] = 0;
|
|
445 break;
|
|
446 case 'P': /* id character of player nearest sender */
|
|
447 id = getTargetID((W_Window) 0, me->p_x, me->p_y, TARG_PLAYER);
|
|
448 buf[0] = id->mapstring[1];
|
|
449 buf[1] = 0;
|
|
450 break;
|
|
451 case 'T': /* team id character of sender team */
|
|
452 buf[0] = me->p_mapchars[0];
|
|
453 buf[1] = 0;
|
|
454 break;
|
|
455 case 'c': /* sender id character */
|
|
456 buf[0] = me->p_mapchars[1];
|
|
457 buf[1] = 0;
|
|
458 break;
|
|
459 case 'C': /* 1 if cloaked, 0 if not [BDyess] */
|
|
460 if (me->p_flags & PFCLOAK)
|
|
461 buf[0] = '1';
|
|
462 else
|
|
463 buf[0] = '0';
|
|
464 buf[1] = 0;
|
|
465 break;
|
|
466 case 'n': /* armies on target planet */
|
|
467 target = gettarget(data->Window, data->x, data->y, TARG_PLANET);
|
|
468 sprintf(buf, "%d", planets[target->o_num].pl_info ?
|
|
469 planets[target->o_num].pl_armies :
|
|
470 -1);
|
|
471 break;
|
|
472 case 'E': /* 1 if etemped, 0 if not */
|
|
473 if (me->p_flags & PFENG)
|
|
474 buf[0] = '1';
|
|
475 else
|
|
476 buf[0] = '0';
|
|
477 buf[1] = 0;
|
|
478 break;
|
|
479 case 'W': /* 1 if wtemped, 0 if not */
|
|
480 if (me->p_flags & PFWEP)
|
|
481 buf[0] = '1';
|
|
482 else
|
|
483 buf[0] = '0';
|
|
484 buf[1] = 0;
|
|
485 break;
|
|
486 case 'S': /* sender two character ship type */
|
|
487 strncpy(buf, me->p_ship->s_desig, 2);
|
|
488 buf[2] = 0;
|
|
489 break;
|
|
490 case 'G': /* id char of friendly player nearest sender */
|
|
491 targettype = TARG_FRIENDLY;
|
|
492 case 'H': /* id char of enemy player nearest sender */
|
|
493 if (!targettype)
|
|
494 targettype = TARG_ENEMY;
|
|
495 id = getTargetID((W_Window) 0, me->p_x, me->p_y,
|
|
496 TARG_PLAYER | targettype);
|
|
497 buf[0] = id->mapstring[1];
|
|
498 buf[1] = 0;
|
|
499 break;
|
|
500 case 'l': /* three character name of target planet */
|
|
501 case 'L':
|
|
502 id = getTargetID(data->Window, data->x, data->y, TARG_PLANET);
|
|
503 strcpy(buf, id->mapstring);
|
|
504 buf[0] = tolower(buf[0]);
|
|
505 break;
|
|
506 case 'i': /* sender full player name (16 character max) */
|
|
507 case 'I':
|
|
508 strncpy(buf, me->p_name, 16);
|
|
509 buf[16] = 0;
|
|
510 break;
|
|
511 case 'u': /* full name of target player (16 character
|
|
512 max) */
|
|
513 case 'U':
|
|
514 id = getTargetID(data->Window, data->x, data->y, TARG_PLAYER);
|
|
515 strncpy(buf, id->name, 16);
|
|
516 buf[16] = 0;
|
|
517 break;
|
|
518 case 'z': /* 3 letter team id of target planet */
|
|
519 case 'Z':
|
|
520 id = getTargetID(data->Window, data->x, data->y, TARG_PLANET);
|
|
521 strcpy(buf, teaminfo[id->team].shortname);
|
|
522 strtolower(buf);
|
|
523 break;
|
|
524 case 'b': /* nearest planet to sender */
|
|
525 case 'B':
|
|
526 id = getTargetID((W_Window) 0, me->p_x, me->p_y, TARG_PLANET);
|
|
527 strcpy(buf, id->mapstring);
|
|
528 buf[0] = tolower(buf[0]);
|
|
529 break;
|
|
530 case 'v': /* average ping round trip time */
|
|
531 sprintf(buf, "%d", ping_av);
|
|
532 break;
|
|
533 case 'V': /* ping stdev */
|
|
534 sprintf(buf, "%d", ping_sd);
|
|
535 break;
|
|
536 case 'y': /* packet loss */
|
|
537 sprintf(buf, "%d", (2 * ping_tloss_sc + ping_tloss_cs) / 3);
|
|
538 break;
|
|
539 case 'm': /* last message */
|
|
540 case 'M':
|
|
541 strcpy(buf, lastMessage);
|
|
542 break;
|
|
543 case 'o': /* insert three letter team name */
|
|
544 case 'O':
|
|
545 strcpy(buf, teaminfo[me->p_teami].shortname);
|
|
546 break;
|
|
547 case ' ': /* nothing. This is so you can start a macro
|
|
548 with spaces */
|
|
549 buf[0] = ' ';
|
|
550 buf[1] = 0;
|
|
551 break;
|
|
552 case '%': /* insert % */
|
|
553 buf[0] = '%';
|
|
554 buf[1] = 0;
|
|
555 break;
|
|
556 case '?': /* start test */
|
|
557 (*locpntr)++;
|
|
558 handle_test(locpntr, destpntr, data);
|
|
559 return;
|
|
560 case '{': /* conditional */
|
|
561 handle_conditional(locpntr, destpntr, data);
|
|
562 return;
|
|
563 case '*': /* abort! */
|
|
564 abortflag = 1;
|
|
565 return;
|
|
566 case '2': /* is paradise? sorry, ran out of good
|
|
567 letters. '2' means, 'is Netrek II?'. */
|
|
568 buf[0] = paradise + '0';
|
|
569 buf[1] = 0;
|
|
570 break;
|
|
571 case '_': /* call another macro. Added 1/24/94 [BDyess] */
|
|
572 (*locpntr)++;
|
|
573 if (**locpntr == '^') { /* control char */
|
|
574 (*locpntr)++;
|
|
575 m = macrotable[**locpntr + (**locpntr == '^') ? 0 : 128];
|
|
576 } else {
|
|
577 m = macrotable[(int) **locpntr];
|
|
578 }
|
|
579 if (m) { /* does the macro exist? */
|
|
580 char temp[MAXMACRO];
|
|
581 strcpy(temp, m->string);
|
|
582 strcat(temp, *locpntr + 1);
|
|
583 strcpy(*locpntr + 1, temp);
|
|
584 } else { /* somebody screwed up */
|
|
585 printf("Error: called macro ");
|
|
586 if (&m - macrotable >= 128)
|
|
587 putchar('^');
|
|
588 printf("%c doesn't exist.\n", **locpntr);
|
|
589 }
|
|
590 buf[0] = 0;
|
|
591 break;
|
|
592 default:
|
|
593 sprintf(buf, "Unknown %% escape: %%%c", ch);
|
|
594 warning(buf);
|
|
595 buf[0] = 0;
|
|
596 break;
|
|
597 }
|
|
598 if (isupper(ch))
|
|
599 strtoupper(buf);
|
|
600 (*locpntr)++;
|
|
601 while (**destpntr)
|
|
602 (*destpntr)++;
|
|
603 return;
|
|
604 }
|
|
605
|
|
606 void
|
|
607 handle_test(locpntr, destpntr, data)
|
|
608 char **locpntr, **destpntr;
|
|
609 W_Event *data;
|
|
610 {
|
|
611 char l[MAXMACRO], r[MAXMACRO], condition = 0;
|
|
612 short trueflag = 0;
|
|
613
|
|
614 getTestString(l, locpntr, destpntr, data);
|
|
615 if (**locpntr != '%') {
|
|
616 condition = *((*locpntr)++);
|
|
617 getTestString(r, locpntr, destpntr, data);
|
|
618 }
|
|
619 switch (condition) {
|
|
620 case '=':
|
|
621 if (!strcmp(l, r))
|
|
622 trueflag = 1;
|
|
623 break;
|
|
624 case '>':
|
|
625 if (atoi(l) > atoi(r))
|
|
626 trueflag = 1;
|
|
627 break;
|
|
628 case '<':
|
|
629 if (atoi(l) < atoi(r))
|
|
630 trueflag = 1;
|
|
631 break;
|
|
632 default:
|
|
633 if (atoi(l))
|
|
634 trueflag = 1;
|
|
635 }
|
|
636 **destpntr = '0' + trueflag;
|
|
637 *(*destpntr + 1) = 0;
|
|
638 (*destpntr)++;
|
|
639 return;
|
|
640 }
|
|
641
|
|
642 void
|
|
643 handle_conditional(locpntr, destpntr, data)
|
|
644 char **locpntr, **destpntr;
|
|
645 W_Event *data;
|
|
646 {
|
|
647 (*locpntr)++;
|
|
648 **destpntr = 0;
|
|
649 (*destpntr)--;
|
|
650 if (**destpntr == '0') {
|
|
651 ignoreConditionalString(locpntr);
|
|
652 getConditionalString(locpntr, destpntr, data);
|
|
653 } else {
|
|
654 getConditionalString(locpntr, destpntr, data);
|
|
655 ignoreConditionalString(locpntr);
|
|
656 }
|
|
657 (*locpntr) += 2;
|
|
658 while (**destpntr)
|
|
659 (*destpntr)++;
|
|
660 return;
|
|
661 }
|
|
662
|
|
663 void
|
|
664 ignoreConditionalString(locpntr)
|
|
665 char **locpntr;
|
|
666 {
|
|
667 int depth = 0, breakflag = 0;
|
|
668
|
|
669 while (**locpntr) {
|
|
670 if (**locpntr == '%') {
|
|
671 switch (*(*locpntr + 1)) {
|
|
672 case '!':
|
|
673 if (!depth)
|
|
674 breakflag = 1;
|
|
675 (*locpntr) += 2;
|
|
676 break;
|
|
677 case '}':
|
|
678 if (depth) {
|
|
679 depth--;
|
|
680 (*locpntr) += 2;
|
|
681 } else
|
|
682 breakflag = 1;
|
|
683 break;
|
|
684 case '{':
|
|
685 depth++;
|
|
686 (*locpntr) += 2;
|
|
687 break;
|
|
688 case '*':
|
|
689 abortflag = 1;
|
|
690 return;
|
|
691 default:
|
|
692 (*locpntr)++;
|
|
693 }
|
|
694 if (breakflag)
|
|
695 break;
|
|
696 } else
|
|
697 (*locpntr)++;
|
|
698 }
|
|
699 }
|
|
700
|
|
701 void
|
|
702 getConditionalString(locpntr, destpntr, data)
|
|
703 char **locpntr, **destpntr;
|
|
704 W_Event *data;
|
|
705 {
|
|
706 char *dest = *destpntr;
|
|
707
|
|
708 while (**locpntr) {
|
|
709 if (**locpntr != '%' && **locpntr != '$' && **locpntr)
|
|
710 *(dest++) = *((*locpntr)++);
|
|
711 else if (*(*locpntr + 1) == '!') {
|
|
712 (*locpntr) += 2;
|
|
713 break;
|
|
714 } else if (*(*locpntr + 1) == '}')
|
|
715 break;
|
|
716 else if (**locpntr == '%') {
|
|
717 (*locpntr)++;
|
|
718 handle_special(locpntr, &dest, data);
|
|
719 while (*(dest++));
|
|
720 dest--;
|
|
721 } else { /* **locpntr must equal '$' */
|
|
722 (*locpntr)++;
|
|
723 handle_dollar(locpntr, &dest, data);
|
|
724 while (*(dest++));
|
|
725 dest--;
|
|
726 }
|
|
727 }
|
|
728 *dest = 0;
|
|
729 return;
|
|
730 }
|
|
731
|
|
732 void
|
|
733 getTestString(buf, locpntr, destpntr, data)
|
|
734 char *buf, **locpntr, **destpntr;
|
|
735 W_Event *data;
|
|
736 {
|
|
737 char *dest = buf;
|
|
738
|
|
739 if (**locpntr == '%') {
|
|
740 (*locpntr)++;
|
|
741 handle_special(locpntr, &buf, data);
|
|
742 } else if (**locpntr == '$') {
|
|
743 (*locpntr)++;
|
|
744 handle_dollar(locpntr, &buf, data);
|
|
745 } else {
|
|
746 while (**locpntr != '%' && **locpntr != '$' && **locpntr != '<' &&
|
|
747 **locpntr != '>' && **locpntr != '=' &&
|
|
748 **locpntr)
|
|
749 *(dest++) = *((*locpntr)++);
|
|
750 *dest = 0;
|
|
751 }
|
|
752 return;
|
|
753 }
|
|
754
|
|
755 char *
|
|
756 strtoupper(buf)
|
|
757 char *buf;
|
|
758 {
|
|
759 char *s;
|
|
760 for (s = buf; *s; s++)
|
|
761 *s = toupper(*s);
|
|
762 return buf;
|
|
763 }
|
|
764
|
|
765 char *
|
|
766 strtolower(buf)
|
|
767 char *buf;
|
|
768 {
|
|
769 char *s;
|
|
770 for (s = buf; *s; s++)
|
|
771 *s = tolower(*s);
|
|
772 return buf;
|
|
773 }
|
|
774
|
|
775 /**********************************************************************/
|
|
776
|
|
777 /*
|
|
778 start with a $
|
|
779
|
|
780 field 1:
|
|
781 (n)earest
|
|
782 (t)arget
|
|
783 (s)elf (doesn't have fields 2 and 3)
|
|
784 (_) ego (has no other fields)
|
|
785
|
|
786 field 2:
|
|
787 (a)ny
|
|
788 (t)eammate
|
|
789 (f)riendly
|
|
790 (h)ostile
|
|
791
|
|
792 field 3:
|
|
793 (a)ny
|
|
794 (u)ser
|
|
795 (p)lanet (includes asteroids)
|
|
796 (s)tar
|
|
797 (n)ebula
|
|
798 (b)lack hole
|
|
799 (^) non-planet
|
|
800 (*) any stellar object
|
|
801
|
|
802 field 4: (optional) NYI
|
|
803 (U)ppercase
|
|
804 (C)apitalize
|
|
805 (L)owercase
|
|
806
|
|
807 field 5:
|
|
808 full (n)ame (Hammor, Thought)
|
|
809 (i)dentifier (e.g. R5, Ka, Can, Sco)
|
|
810 (#) number (0-9a-z for players, %d for planets)
|
|
811 (t)eam name (Romulan)
|
|
812 (s)hort team id (ROM)
|
|
813 (l)etter of team (R)
|
|
814 (a)rmies
|
|
815 (@) sector
|
|
816 (A)rable, 0=not arable, 1=arable but not AGRI, 2=AGRI
|
|
817 (M)etal, 0, 1, 2(repair), or 3(sy)
|
|
818 (D)ilithium, 0, 1 or 2(fuel)
|
|
819
|
|
820 Any implementation of the paradise $ codes (subset or superset)
|
|
821 must implement and document the $_ code. -- Robert Forsman
|
|
822 */
|
|
823
|
|
824 void
|
|
825 handle_dollar(locpntr, destpntr, data)
|
|
826 char **locpntr, **destpntr;
|
|
827 W_Event *data;
|
|
828 {
|
|
829 char *buf = *destpntr;
|
|
830 struct id *target;
|
|
831 char ch = *((*locpntr)++);
|
|
832 W_Window w;
|
|
833 int x, y;
|
|
834 int flags;
|
|
835 int capitalize = 0;
|
|
836
|
|
837 buf[0] = 0;
|
|
838
|
|
839 if (ch == '_') {
|
|
840 strcpy(buf, "Paradise netrek $ codes are orthogonal and make sense.");
|
|
841 while (**destpntr)
|
|
842 (*destpntr)++;
|
|
843 return;
|
|
844 } if (ch == 's') {
|
|
845 target = getTargetID((W_Window) 0, me->p_x, me->p_y, TARG_PLAYER | TARG_SELF);
|
|
846 } else {
|
|
847 switch (tolower(ch)) {
|
|
848 case 'n':
|
|
849 w = 0;
|
|
850 x = me->p_x;
|
|
851 y = me->p_y;
|
|
852 break;
|
|
853 case 't':
|
|
854 w = data->Window;
|
|
855 x = data->x;
|
|
856 y = data->y;
|
|
857 break;
|
|
858 default:
|
|
859 printf("Invalid $ code field 1 : `%c'\n", ch);
|
|
860 return;
|
|
861 }
|
|
862
|
|
863 ch = *((*locpntr)++);
|
|
864 switch (tolower(ch)) {
|
|
865 case 'a':
|
|
866 flags = 0;
|
|
867 break;
|
|
868 case 't':
|
|
869 flags = TARG_TEAM;
|
|
870 break;
|
|
871 case 'f':
|
|
872 flags = TARG_FRIENDLY;
|
|
873 break;
|
|
874 case 'h':
|
|
875 flags = TARG_ENEMY;
|
|
876 break;
|
|
877 default:
|
|
878 printf("Invalid $ code field 2 : `%c'\n", ch);
|
|
879 return;
|
|
880 }
|
|
881
|
|
882 ch = *((*locpntr)++);
|
|
883 switch (tolower(ch)) {
|
|
884 case 'a':
|
|
885 flags |= TARG_PLAYER | TARG_ASTRAL;
|
|
886 break;
|
|
887 case 'u':
|
|
888 flags |= TARG_PLAYER;
|
|
889 break;
|
|
890 case 'p':
|
|
891 flags |= TARG_PLANET;
|
|
892 break;
|
|
893 case 's':
|
|
894 flags |= TARG_STAR;
|
|
895 break;
|
|
896 case 'n':
|
|
897 flags |= TARG_NEBULA;
|
|
898 break;
|
|
899 case 'b':
|
|
900 flags |= TARG_BLACKHOLE;
|
|
901 break;
|
|
902 case '^':
|
|
903 flags |= (TARG_ASTRAL & ~TARG_PLANET);
|
|
904 /* fall through */
|
|
905 case '*':
|
|
906 flags |= TARG_PLANET;
|
|
907 break;
|
|
908 default:
|
|
909 printf("Invalid $ code field 3 : `%c'\n", ch);
|
|
910 return;
|
|
911 }
|
|
912
|
|
913 target = getTargetID(w, x, y, flags);
|
|
914 }
|
|
915
|
|
916 ch = tolower(*((*locpntr)++));
|
|
917 if (ch == 'l')
|
|
918 capitalize = -1;
|
|
919 else if (ch == 'c')
|
|
920 capitalize = 1;
|
|
921 else if (ch == 'u')
|
|
922 capitalize = 2;
|
|
923 else
|
|
924 (*locpntr)--; /* oops, back up and try again */
|
|
925
|
|
926 ch = *((*locpntr)++);
|
|
927
|
|
928 switch (ch) {
|
|
929 case 'n':
|
|
930 strcpy(buf, target->name);
|
|
931 break;
|
|
932 case 'i':
|
|
933 /* if (target->type == PLANETTYPE) {*/
|
|
934 strcpy(buf, target->mapstring);
|
|
935 /*
|
|
936 } else {
|
|
937 buf[0] = target->mapstring[1];
|
|
938 buf[1] = 0;
|
|
939 }*/
|
|
940 break;
|
|
941 case '#':
|
|
942 if (target->type == PLANETTYPE) {
|
|
943 sprintf(buf, "%d", target->number);
|
|
944 } else {
|
|
945 buf[0] = target->mapstring[1];
|
|
946 buf[1] = 0;
|
|
947 }
|
|
948 break;
|
|
949 case 't':
|
|
950 strcpy(buf, teaminfo[target->team].name);
|
|
951 break;
|
|
952 case 's':
|
|
953 strcpy(buf, teaminfo[target->team].shortname);
|
|
954 break;
|
|
955 case 'l':
|
|
956 buf[0] = teaminfo[target->team].letter;
|
|
957 buf[1] = 0;
|
|
958 break;
|
|
959 case 'a':
|
|
960 sprintf(buf, "%d", (target->type == PLANETTYPE) ?
|
|
961 planets[target->number].pl_armies :
|
|
962 players[target->number].p_armies);
|
|
963 break;
|
|
964 case '@':
|
|
965 if (!paradise)
|
|
966 break;
|
|
967 if (target->type == PLANETTYPE) {
|
|
968 x = planets[target->number].pl_x;
|
|
969 y = planets[target->number].pl_y;
|
|
970 } else {
|
|
971 x = players[target->number].p_x;
|
|
972 y = players[target->number].p_y;
|
|
973 }
|
|
974 sprintf(buf, "%d-%d", x / GRIDSIZE + 1, y / GRIDSIZE + 1);
|
|
975 break;
|
|
976 case 'A': /* Arable or AGRI */
|
|
977 buf[0] = '0';
|
|
978 if (target->type == PLANETTYPE) {
|
|
979 if (planets[target->number].pl_flags & PLARABLE)
|
|
980 buf[0] = '1';
|
|
981 if (planets[target->number].pl_flags & PLAGRI)
|
|
982 buf[0] = '2';
|
|
983 }
|
|
984 buf[1] = 0;
|
|
985 break;
|
|
986 case 'M': /* Metal, Repair, or SY */
|
|
987 buf[0] = '0';
|
|
988 if (target->type == PLANETTYPE) {
|
|
989 if (planets[target->number].pl_flags & PLMETAL)
|
|
990 buf[0] = '1';
|
|
991 if (planets[target->number].pl_flags & PLREPAIR)
|
|
992 buf[0] = '2';
|
|
993 if (planets[target->number].pl_flags & PLSHIPYARD)
|
|
994 buf[0] = '3';
|
|
995 }
|
|
996 buf[1] = 0;
|
|
997 break;
|
|
998 case 'D': /* Dilythium or Fuel */
|
|
999 buf[0] = '0';
|
|
1000 if (target->type == PLANETTYPE) {
|
|
1001 if (planets[target->number].pl_flags & PLDILYTH)
|
|
1002 buf[0] = '1';
|
|
1003 if (planets[target->number].pl_flags & PLFUEL)
|
|
1004 buf[0] = '2';
|
|
1005 }
|
|
1006 buf[1] = 0;
|
|
1007 break;
|
|
1008 default:
|
|
1009 printf("Invalid $ code field 4 : `%c'\n", ch);
|
|
1010 return;
|
|
1011 }
|
|
1012
|
|
1013 if (capitalize < 0) {
|
|
1014 char *s;
|
|
1015 for (s = buf; *s; s++)
|
|
1016 *s = tolower(*s);
|
|
1017 } else if (capitalize > 1) {
|
|
1018 char *s;
|
|
1019 for (s = buf; *s; s++)
|
|
1020 *s = toupper(*s);
|
|
1021 } else if (capitalize) {
|
|
1022 char *s;
|
|
1023 s = buf;
|
|
1024 *s = toupper(*s);
|
|
1025 for (s++; *s; s++)
|
|
1026 *s = tolower(*s);
|
|
1027 }
|
|
1028 while (**destpntr)
|
|
1029 (*destpntr)++;
|
|
1030 return;
|
|
1031 }
|
|
1032 #endif /* MACROS */
|