1 /****************************************************************************
2 
3 EDITSS: A shipshape editor for XPilot shipshapes     V2.1
4 Copyright (C) 1994 Ronald In 't Velt
5 
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 2 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, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 Right now, it is impossible to reach me via E-Mail.  When I will have
22 an account again somewhere, I will post a notice in alt.games.xpilot (or
23 rec.games.xpilot in case this newgroup is accepted into rec.).
24 
25 
26 EDITSS.C: main module
27 ****************************************************************************/
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <time.h>
34 #include <ctype.h>
35 #include <sys/param.h>
36 #include <pwd.h>
37 #include <unistd.h>
38 #include <X11/Intrinsic.h>
39 #include <X11/StringDefs.h>
40 #include <X11/Xaw/Command.h>
41 #include <X11/Xaw/Viewport.h>
42 #include <X11/Xaw/Box.h>
43 #include <X11/Xaw/Toggle.h>
44 #include <X11/Xaw/AsciiText.h>
45 #include <X11/Xaw/AsciiSrc.h>
46 #include <X11/Xaw/AsciiSink.h>
47 #include <X11/Xaw/Label.h>
48 #include <X11/Xaw/List.h>
49 #include <X11/Xaw/Form.h>
50 #include <X11/Xaw/Scrollbar.h>
51 #include <X11/Xaw/Dialog.h>
52 #include <X11/Xaw/Porthole.h>
53 #include <X11/Xaw/Paned.h>
54 
55 #include "const.h"
56 #include "types.h"
57 
58 
59 #include "pship.h"
60 #include "editss.h"
61 #include "xstuff.h"
62 
63 /*****************************************************************************
64 * The following vars are global						     *
65 *****************************************************************************/
66 XtAppContext app_context;
67 Widget toplevel, mainw;			/* main windows */
68 Widget b_quit, b_draw, b_kill;		/* The widgets */
69 Widget b_split, b_write;
70 Widget area, small, b_print, b_shipname, b_shipaut;
71 Widget sn_source, sn_sink, l_sn, b_default;
72 Widget sa_source, sa_sink;
73 Widget shipview, shipbm, b_clear, sl_source;
74 Widget sl_sink, b_shiplib, l_sl;
75 Widget l_size, l_sizeok, b_box, l_prob, b_psout;
76 Widget b_mg, b_lg, b_rg, b_ll, b_rl, b_mr, b_en;
77 
78 Pixmap pm_area, pm_small, pm_ships;	/* drawing areas */
79 Pixmap pm_kill, pm_split, pm_nose, pm_rear;  /* pointer pixmaps */
80 Pixmap pm_eng, pm_mis;
81 
82 Cursor cur_nose, cur_rear, cur_draw, cur_kill, cur_split;/* pointers */
83 Cursor cur_eng, cur_mis;
84 
85 int	bb_bor, va_bor;			/* border widths */
86 Pixel	bb_b, bb_f, nl_b, nl_f;		/* widget colors */
87 Pixel	st_b, st_f, bh_b, bh_f, bt_b, bt_f, ba_b, ba_f;
88 Pixel	pmc, plc, prc;
89 XColor	col_black, col_white;
90 int	scr_num, scr_depth;		/* number and depth of screen */
91 char 	bb_fs[30], bb_bs[30];		/* names of widget colors */
92 char	nl_fs[30], nl_bs[30], st_fs[30], st_bs[30];
93 char	bh_fs[30], bh_bs[30], ba_fs[30], ba_bs[30];
94 char	bt_fs[30], bt_bs[30];
95 char	mc[30], lc[30], rc[30];
96 int	f_w, f_h;			/* width & height of font */
97 
98 int	isdefault, colorok;		/* default file / colors exist? */
99 Dimension	pm_area_w, pm_area_h, pm_small_w, pm_small_h;
100 GC	gc_draw, gc_clear, gc_grid, gc_xor, gc_ship, gc_main, gc_left, gc_right;
101 XFontStruct *font_small;		/* smaller font */
102 XFontStruct *font;
103 char fontname[MAXLINELEN], shipname[MAXLINELEN], shipaut[MAXLINELEN];
104 char shiplib[MAXLINELEN];		/* names of stuff */
105 
106 int	xo, yo, nrships;		/* nr of ships in lib */
107 int	drawmode, dragpoint, dragmode;	/* current drawmodes */
108 int	rcformat;			/* is format in .xpilotrd format? */
109 char 	dr_val[] = {'D', 'K', 'S', '8', '7', '9', '1', '3', '5', '2'};
110 /* value array for radiobuttons */
111 
112 Time tl;				/* timer for double-click */
113 ship sh_ed;				/* current ship to be edited */
114 
115 int	callfrom=FALSE;			/* called from XXPMS */
116 
117 shiplist *sl;
118 /****************************************************************************/
Free_Shiplist(shiplist * sl)119 void	Free_Shiplist(shiplist *sl)
120 {
121 	if (sl!=NULL) {
122 		if (sl->s!=NULL) free(sl->s);
123 		free(sl);
124 	}
125 }
126 
Alloc_Shiplist(void)127 shiplist	*Alloc_Shiplist(void)
128 {
129 	return (shiplist *)malloc(sizeof(shiplist));
130 }
131 
132 
133 /* Remove all cr's from string s */
killcr(char * s)134 void killcr(char *s)
135 {
136 	char *b;
137 	b=strchr(s,'\n');
138 	if (b!=NULL) {
139 		*b='\0';
140 		if (*(b+1)!='\0') strcat(s, b+1);
141 	}
142 }
143 
144 
145 /* Kill trailing spaces and tabs from string s */
killsp(char * s)146 void killsp(char *s)
147 {
148 	int i;
149 	i=strlen(s)-1;
150 	while ((i>=0)&&( ((s[i]==' ')||(s[i]=='\t')) )) {
151 		s[i]='\0';
152 		i-=1;
153 	}
154 }
155 
156 
157 /* Get shiblib string from widget ans clean up */
getshiplib(void)158 void getshiplib(void)
159 {
160 	char *s;
161 	XtVaGetValues(b_shiplib, XtNstring, &s, NULL);
162 	strcpy(shiplib,s);
163 	killcr(shiplib);
164 	killsp(shiplib);
165 }
166 
167 
168 /* Get shibname string from widget ans clean up */
getshipname(void)169 void getshipname(void)
170 {
171 	char *s;
172 	XtVaGetValues(b_shipname, XtNstring, &s, NULL);
173 	strcpy(shipname,s);
174 	killcr(shipname);
175 	killsp(shipname);
176 	strcpy(sh_ed.name, shipname);
177 }
178 
179 
getshipaut(void)180 void getshipaut(void)
181 {
182 	char *s;
183 	XtVaGetValues(b_shipaut, XtNstring, &s, NULL);
184 	strcpy(shipaut,s);
185 	killcr(shipaut);
186 	killsp(shipaut);
187 	strcpy(sh_ed.author, shipaut);
188 }
189 
190 
191 
192 /* Determine home directory of the user */
userpath(void)193 char *userpath(void)
194 {
195 	static char res[MAXLINELEN], *h;
196 	struct passwd *pwd;
197 	res[0]='\0';
198 	h=getenv("HOME");
199 	if (h!=NULL) strcpy(res,h);
200 	if ((strlen(res)==0)&&(access(h,0)!=-1)) strcpy(res,h);
201 	if (strlen(res)==0) {
202 		pwd=getpwuid(getuid());
203 		if (pwd!=NULL) strcpy(res,pwd->pw_dir);
204 	}
205 	return res;
206 }
207 
208 /* Get a ship from the shiplib file.  Name into sname, ship into sship */
209 /* if same=TRUE, file will not reset, close on subsequent calls */
getoneshipdef(char * sship,FILE * fin)210 int getoneshipdef(char *sship, FILE *fin)
211 {
212 	char *sd;
213 	static char c[MAXSHIPLEN], d[MAXSHIPLEN];
214 
215 	getshiplib();
216 	if ((fin==NULL)||(feof(fin))) return FALSE;
217 	sship[0]='\0';
218 	fscanf(fin,"%[^\n]",c);
219 	fscanf(fin,"%*[\n]");
220 	sd=strchr(c,'\\');
221 	while (sd!=NULL) {
222 		*sd='\0';
223 		fscanf(fin,"%[^\n]",d);
224 		fscanf(fin,"%*[\n]");
225 		strcat(c, d);
226 		sd=strchr(c,'\\');
227 	}
228 	strcpy(sship, c);
229 	return TRUE;
230 }
231 
232 
233 
234 /* Find the closest line to px, py in the editship */
findline(int px,int py)235 int findline(int px, int py)
236 {
237 	int dx, dy, b, i, np, mindist, minpnt;
238 	float slope;
239 	if (sh_ed.n<2) return -1;
240 	mindist=9999; minpnt=-1;
241 	for (i=0; i<sh_ed.n; i++) {
242 		if (i==sh_ed.n-1) np=0; else np=i+1;
243 		dx=cx(sh_ed.p[np].x)-cx(sh_ed.p[i].x);
244 		dy=cy(sh_ed.p[np].y)-cy(sh_ed.p[i].y);
245 		b=0;
246 		if (abs(dx)>abs(dy)) {
247 			slope=(float)dy/(float)dx;
248 			b=cx(sh_ed.p[i].x)-px;
249 			if (((b<0)&&(dx>0))||((b>0)&&(dx<=0))) {
250 				b=px-cx(sh_ed.p[np].x);
251 				if (((b<0)&&(dx>0))||((b>0)&&(dx<=0))) b=0;
252 			}
253 			if (b<0) b=-b;
254 			if (b<(pm_area_w-20)/60)
255 				b=abs(py-(cy(sh_ed.p[i].y)+(int)(slope*(px-cx(sh_ed.p[i].x)))));
256 		} else {
257 			/* BUGFIX BG: Don't divide by zero.  core dumper. */
258 			if (dy == 0)
259 				slope = 0;
260 			else
261 				slope=(float)dx/(float)dy;
262 			b=cy(sh_ed.p[i].y)-py;
263 			if (((b<0)&&(dy>0))||((b>0)&&(dy<=0))) {
264 				b=py-cy(sh_ed.p[np].y);
265 				if (((b<0)&&(dy>0))||((b>0)&&(dy<=0))) b=0;
266 			}
267 			if (b<0) b=-b;
268 			if (b<(pm_area_h-20)/60)
269 				b=abs(px-(cx(sh_ed.p[i].x)+(int)(slope*(py-cy(sh_ed.p[i].y)))));
270 		}
271 		if ((b<(pm_area_w-20)/60)&&(b<mindist)) {
272 			mindist=b;
273 			minpnt=i;
274 		}
275 	}
276 	return minpnt;
277 }
278 
279 
280 /* Coordinate conversion */
cx(int x)281 int cx(int x)
282 {
283 	int i;
284 	i=x+15;
285 	i=(int)(i*(pm_area_w-20)/30)+10;
286 	return i;
287 }
288 
289 /* Coordinate conversion */
cy(int y)290 int cy(int y)
291 {
292 	int i;
293 	i=-y+15;
294 	i=(int)(i*(pm_area_h-20)/30)+10;
295 	return i;
296 }
297 
298 /* Coordinate conversion */
rx(int x)299 int rx(int x)
300 {
301 	int i;
302 	i=x-5;
303 	i=(int)(i*30/(pm_area_w-20))-15;
304 	if (i<-15) i=-15;
305 	if (i>15) i=15;
306 	return i;
307 }
308 
309 /* Coordinate conversion */
ry(int y)310 int ry(int y)
311 {
312 	int i;
313 	i=y-5;
314 	i=(int)(i*30/(pm_area_h-20))-15;
315 	if (i<-15) i=-15;
316 	if (i>15) i=15;
317 	return -i;
318 }
319 
320 /* Coordinate conversion */
rs(int i)321 int rs(int i)
322 {
323 	float f=(SPM_SIZE/40.0);
324 	return (int)((i+20)*f);
325 }
326 
327 
stringupp(char * s)328 char * stringupp(char *s)		/* make a string uppercase */
329 {
330 	static char kaas[1000];
331 	char *c;
332 
333 	strncpy(kaas, s, sizeof(kaas));
334 	kaas[sizeof(kaas) - 1] = '\0';
335 	c = kaas;
336 	while(*c) {
337 		*c = toupper(*c);
338 		c+=1;
339 	}
340 	return kaas;
341 }
342 
343 
344 /* Parse value in s into definition p */
fillin(char * s,fileinfo p)345 void fillin(char *s, fileinfo p)
346 {
347 	int di;		/* dummy's */
348 	float df;
349 	if (strstr(p.parse,"%S")!=NULL) {	/* capitalize string */
350 		strcpy(p.varad,stringupp(s));
351 		return;
352 	}
353 	if (strstr(p.parse,"%s")!=NULL) {	/* string */
354 		strcpy(p.varad,s);
355 		return;
356 	}
357 	if (strstr(p.parse,"%>s")!=NULL) {	/* append string */
358 		strcat(p.varad,p.def);
359 		strcat(p.varad,s);
360 		strcat(p.varad,"\n");
361 		return;
362 	}
363 	if (strstr(p.parse,"%>S")!=NULL) {	/* append capit. string */
364 		strcat(p.varad,p.def);
365 		strcat(p.varad,stringupp(s));
366 		strcat(p.varad,"\n");
367 		return;
368 	}
369 	if (strstr(p.parse,"%b")!=NULL) {	/* handle boolean */
370 		if ((!strcasecmp(s,"true"))||(!strcasecmp(s,"on"))||(!strcasecmp(s,"yes")))
371 			*(int *)p.varad=1;
372 		else
373 			*(int *)p.varad=0;
374 		return;
375 	}
376 	if (strstr(p.parse,"%t")!=NULL) {	/* handle troolean */
377 		if ((!strcasecmp(s,"true"))||(!strcasecmp(s,"on"))||(!strcasecmp(s,"yes")))
378 			*(int *)p.varad=1;
379 		else
380 			if (!strcasecmp(s,"none")) *(int *)p.varad=NONE;
381   				else *(int *)p.varad=0;
382 		return;
383 	}
384 	if (strstr(p.parse,"%i")!=NULL) {	/* handle int */
385 		di=atoi(s);
386 		*(int *)p.varad=di;
387 	}
388 	if (strstr(p.parse,"%f")!=NULL) {	/* handle float */
389 		df=atoi(s);
390 		*(float *)p.varad=df;
391 	}
392 }
393 
394 
395 /* parse file f and p */
parsefile(char * f,fileinfo * p)396 int parsefile(char *f, fileinfo *p)
397 {
398 	int i=0;
399 	FILE *fin;
400 	char a1[1000], a2[1000], a3[1000], a4[1000];
401 	char *b1;
402 
403 	fin=fopen(f,"r");	/* open the default file */
404 				/* else change to defaults first! */
405 
406 	while (p[i].parse!=NULL) {
407 		if (strstr(p[i].parse,"%>")!=NULL) strcpy(p[i].varad,"\0");
408 			else fillin(p[i].def,p[i]);
409 		i++;
410 	}
411 	if (fin==NULL) return FALSE;	/* do nothing if no file */
412 
413 	while (!feof(fin)) {	/* read the entire file! */
414 		a2[0]='\0';
415 		fscanf(fin,"%[^\n]%[\n]",a1,a4);	/* read to EOL */
416 		sscanf(a1,"%[^:#*\t ]%[:*\t ]%[^*\t]",a2,a4,a3);  /* strings */
417 		a4[0]='\0';
418 		sscanf(&a3[1],"%[^#]",a4);
419 		a3[1]='\0';
420 		strcat(a3,a4);
421 		b1=&a3[strlen(a3)-1];	/* strip last spaces */
422 		i=FALSE;
423 		while ((b1!=a3)&&(*b1==' ')) {
424 			b1--;
425 			i=TRUE;
426 		}
427 		if (i) {
428 			b1++;
429 			if (*b1==' ') *b1='\0';
430 		}
431 		i=0;
432 		while ((p[i].parse!=NULL)&&(strcasecmp(p[i].key,a2))) i++;
433 		if (p[i].parse!=NULL) {
434 			fillin(a3, p[i]);
435 		}
436 	}
437 	fclose (fin);
438 	return TRUE;
439 }
440 
441 
loaddefs(void)442 void loaddefs(void)			/* load defaults */
443 {
444 	char a[100],b[100];	/* dummy strings */
445 	static fileinfo parray[] = {
446 		{"%i","buttonbox_border",&bb_bor,"1"},
447 		{"%i","value_border",&va_bor,"0"},
448 		{"%s","buttonbox_b",&bb_bs,"white"},
449 		{"%s","buttonbox_f",&bb_fs,"black"},
450 		{"%s","namelist_b",&nl_bs,"white"},
451 		{"%s","namelist_f",&nl_fs,"black"},
452 		{"%s","status_b",&st_bs,"white"},
453 		{"%s","status_f",&st_fs,"black"},
454 		{"%s","button_high_b",&bh_bs,"white"},
455 		{"%s","button_high_f",&bh_fs,"black"},
456 		{"%s","button_toggle_b",&bt_bs,"white"},
457 		{"%s","button_toggle_f",&bt_fs,"black"},
458 		{"%s","button_action_b",&ba_bs,"white"},
459 		{"%s","button_action_f",&ba_fs,"black"},
460 		{"%s","smallfont",&fontname,"8x13"},
461 		{"%s","shiplib",&shiplib,".xpilotrc"},
462 		{"%s","maincol",&mc,"black"},
463 		{"%s","leftcol",&lc,"black"},
464 		{"%s","rightcol",&rc,"black"},
465 		{NULL,NULL,NULL,NULL}
466 	};
467 
468 	a[0]='\0';
469 	b[0]='\0';
470 	strcpy(b,userpath());
471 	strcat(b,"/.editssrc");
472         isdefault=parsefile(b,parray);
473 }
474 
475 
476 /* Read ships from shiplib, display them */
getdir(void)477 void getdir(void)
478 {
479 	char a[MAXSHIPLEN], b[MAXLINELEN];
480 	int i1, i;
481 	Dimension x, y;
482 	ship *sh;
483 	shiplist *slp, *slpp;
484 	FILE *fin;
485 
486 	while (sl!=NULL) {
487 		/* BUGFIX BG: Don't access memory after free().  core dumper. */
488 		slp = sl->n;
489 		sl->n = NULL;
490 		Free_Shiplist(sl);
491 		sl = slp;
492 	}
493 
494 	strcpy(b,userpath());
495 	if (strlen(b)==0) printf("WARNING!   Cannot determine home directory\n");
496 	strcat(b,"/");
497 	strcat(b,shiplib);
498 	fin=fopen(b,"r");
499 
500 	if (pm_ships>0) {
501 		XFillRectangle(XtDisplay(toplevel),pm_ships,gc_draw,0,0,SPM_SIZE,SPM_SIZE*nrships);
502 		XCopyArea(XtDisplay(shipbm), pm_ships, XtWindow(shipbm),
503 			DefaultGCOfScreen(XtScreen(toplevel)), 0, 0,
504 			SPM_SIZE, SPM_SIZE*nrships, 0,0);
505 		XFreePixmap(XtDisplay(toplevel),pm_ships);
506 	}
507 	nrships=0;
508 	while (getoneshipdef(a,fin)) {
509 		nrships+=1;
510 	}
511 	if (fin!=NULL) fclose(fin);
512 	if (nrships<1) i1=1; else i1=nrships;
513 
514 	a[0]='\0';
515 	pm_ships = XCreatePixmap(XtDisplay(toplevel), RootWindowOfScreen(XtScreen(toplevel)),
516 			SPM_SIZE,SPM_SIZE*i1,scr_depth);
517 	XtResizeWidget(shipbm, SPM_SIZE,SPM_SIZE*i1, 0);
518 	XFillRectangle(XtDisplay(toplevel),pm_ships,gc_draw,0,0,SPM_SIZE,SPM_SIZE*i1);
519 
520 	fin=fopen(b,"r");
521 
522 
523 	nrships=0;
524 	a[0]='\0';
525 	b[0]='\0';
526 	slp = NULL;
527 		while(getoneshipdef(a, fin))  {
528 		sh=Convert_shape_str(strchr(a,'('));
529 		if (sh!=NULL) {
530 			if (sl == NULL) {
531 				sl = Alloc_Shiplist();
532 				slp = sl;
533 			} else {
534 				slp->n = Alloc_Shiplist();
535 				slp = slp->n;
536 			}
537 			slp->s = sh;
538 			for (i=0; i<sh->n; i++) {
539 				if (i<sh->n-1)
540 					XDrawLine(XtDisplay(toplevel),pm_ships,gc_clear,rs(sh->p[i].x),rs(-sh->p[i].y)+nrships*SPM_SIZE,rs(sh->p[i+1].x),rs(-sh->p[i+1].y)+nrships*SPM_SIZE);
541 				else
542 					XDrawLine(XtDisplay(toplevel),pm_ships,gc_clear,rs(sh->p[i].x),rs(-sh->p[i].y)+nrships*SPM_SIZE,rs(sh->p[0].x),rs(-sh->p[0].y)+nrships*SPM_SIZE);
543 			}
544 			nrships+=1;
545 		}
546 	}
547 	if (slp!=NULL) slp->n = NULL;
548 	XCopyArea(XtDisplay(shipbm), pm_ships, XtWindow(shipbm),
549 		DefaultGCOfScreen(XtScreen(toplevel)), 0, 0,
550 		SPM_SIZE, SPM_SIZE*i1, 0,0);
551 	XtVaGetValues(shipview, XtNwidth, &x, XtNheight, &y, NULL);
552 	XtResizeWidget(shipview, x, y+1, 1);
553 	XtResizeWidget(shipview, x, y, 1);
554 
555 	if (fin) fclose(fin);
556 	XtSetSensitive(b_psout, (nrships>0));
557 }
558 
559 
560 /* The main */
main(int argc,char ** argv)561 int main(int argc, char **argv)
562 {
563 	ship *newship;
564 	sl = NULL;
565 	printf("%s  (c) 1994 R. In 't Velt \n",VERSION);
566 	loaddefs();
567 	cleanship(&sh_ed);
568 	shipname[0]='\0';
569 	x_init(argc, argv);
570 	drawmode=DM_NONE;
571 	if ((argc>=2)&&(strchr(argv[1],'(')!=NULL)) {
572 		newship=Convert_shape_str(argv[1]);
573 		cpyship(&sh_ed, newship);
574 		Free_ship_shape(newship);
575 	}
576 	XtAppMainLoop(app_context);
577 
578 	return 0;
579 }
580 
581