/**************************************************************************** EDITSS: A shipshape editor for XPilot shipshapes V2.1 Copyright (C) 1994 Ronald In 't Velt This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Right now, it is impossible to reach me via E-Mail. When I will have an account again somewhere, I will post a notice in alt.games.xpilot (or rec.games.xpilot in case this newgroup is accepted into rec.). EDITSS.C: main module ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "const.h" #include "types.h" #include "pship.h" #include "editss.h" #include "xstuff.h" /***************************************************************************** * The following vars are global * *****************************************************************************/ XtAppContext app_context; Widget toplevel, mainw; /* main windows */ Widget b_quit, b_draw, b_kill; /* The widgets */ Widget b_split, b_write; Widget area, small, b_print, b_shipname, b_shipaut; Widget sn_source, sn_sink, l_sn, b_default; Widget sa_source, sa_sink; Widget shipview, shipbm, b_clear, sl_source; Widget sl_sink, b_shiplib, l_sl; Widget l_size, l_sizeok, b_box, l_prob, b_psout; Widget b_mg, b_lg, b_rg, b_ll, b_rl, b_mr, b_en; Pixmap pm_area, pm_small, pm_ships; /* drawing areas */ Pixmap pm_kill, pm_split, pm_nose, pm_rear; /* pointer pixmaps */ Pixmap pm_eng, pm_mis; Cursor cur_nose, cur_rear, cur_draw, cur_kill, cur_split;/* pointers */ Cursor cur_eng, cur_mis; int bb_bor, va_bor; /* border widths */ Pixel bb_b, bb_f, nl_b, nl_f; /* widget colors */ Pixel st_b, st_f, bh_b, bh_f, bt_b, bt_f, ba_b, ba_f; Pixel pmc, plc, prc; XColor col_black, col_white; int scr_num, scr_depth; /* number and depth of screen */ char bb_fs[30], bb_bs[30]; /* names of widget colors */ char nl_fs[30], nl_bs[30], st_fs[30], st_bs[30]; char bh_fs[30], bh_bs[30], ba_fs[30], ba_bs[30]; char bt_fs[30], bt_bs[30]; char mc[30], lc[30], rc[30]; int f_w, f_h; /* width & height of font */ int isdefault, colorok; /* default file / colors exist? */ Dimension pm_area_w, pm_area_h, pm_small_w, pm_small_h; GC gc_draw, gc_clear, gc_grid, gc_xor, gc_ship, gc_main, gc_left, gc_right; XFontStruct *font_small; /* smaller font */ XFontStruct *font; char fontname[MAXLINELEN], shipname[MAXLINELEN], shipaut[MAXLINELEN]; char shiplib[MAXLINELEN]; /* names of stuff */ int xo, yo, nrships; /* nr of ships in lib */ int drawmode, dragpoint, dragmode; /* current drawmodes */ int rcformat; /* is format in .xpilotrd format? */ char dr_val[] = {'D', 'K', 'S', '8', '7', '9', '1', '3', '5', '2'}; /* value array for radiobuttons */ Time tl; /* timer for double-click */ ship sh_ed; /* current ship to be edited */ int callfrom=FALSE; /* called from XXPMS */ shiplist *sl; /****************************************************************************/ void Free_Shiplist(shiplist *sl) { if (sl!=NULL) { if (sl->s!=NULL) free(sl->s); free(sl); } } shiplist *Alloc_Shiplist(void) { return (shiplist *)malloc(sizeof(shiplist)); } /* Remove all cr's from string s */ void killcr(char *s) { char *b; b=strchr(s,'\n'); if (b!=NULL) { *b='\0'; if (*(b+1)!='\0') strcat(s, b+1); } } /* Kill trailing spaces and tabs from string s */ void killsp(char *s) { int i; i=strlen(s)-1; while ((i>=0)&&( ((s[i]==' ')||(s[i]=='\t')) )) { s[i]='\0'; i-=1; } } /* Get shiblib string from widget ans clean up */ void getshiplib(void) { char *s; XtVaGetValues(b_shiplib, XtNstring, &s, NULL); strcpy(shiplib,s); killcr(shiplib); killsp(shiplib); } /* Get shibname string from widget ans clean up */ void getshipname(void) { char *s; XtVaGetValues(b_shipname, XtNstring, &s, NULL); strcpy(shipname,s); killcr(shipname); killsp(shipname); strcpy(sh_ed.name, shipname); } void getshipaut(void) { char *s; XtVaGetValues(b_shipaut, XtNstring, &s, NULL); strcpy(shipaut,s); killcr(shipaut); killsp(shipaut); strcpy(sh_ed.author, shipaut); } /* Determine home directory of the user */ char *userpath(void) { static char res[MAXLINELEN], *h; struct passwd *pwd; res[0]='\0'; h=getenv("HOME"); if (h!=NULL) strcpy(res,h); if ((strlen(res)==0)&&(access(h,0)!=-1)) strcpy(res,h); if (strlen(res)==0) { pwd=getpwuid(getuid()); if (pwd!=NULL) strcpy(res,pwd->pw_dir); } return res; } /* Get a ship from the shiplib file. Name into sname, ship into sship */ /* if same=TRUE, file will not reset, close on subsequent calls */ int getoneshipdef(char *sship, FILE *fin) { char *sd; static char c[MAXSHIPLEN], d[MAXSHIPLEN]; getshiplib(); if ((fin==NULL)||(feof(fin))) return FALSE; sship[0]='\0'; fscanf(fin,"%[^\n]",c); fscanf(fin,"%*[\n]"); sd=strchr(c,'\\'); while (sd!=NULL) { *sd='\0'; fscanf(fin,"%[^\n]",d); fscanf(fin,"%*[\n]"); strcat(c, d); sd=strchr(c,'\\'); } strcpy(sship, c); return TRUE; } /* Find the closest line to px, py in the editship */ int findline(int px, int py) { int dx, dy, b, i, np, mindist, minpnt; float slope; if (sh_ed.n<2) return -1; mindist=9999; minpnt=-1; for (i=0; iabs(dy)) { slope=(float)dy/(float)dx; b=cx(sh_ed.p[i].x)-px; if (((b<0)&&(dx>0))||((b>0)&&(dx<=0))) { b=px-cx(sh_ed.p[np].x); if (((b<0)&&(dx>0))||((b>0)&&(dx<=0))) b=0; } if (b<0) b=-b; if (b<(pm_area_w-20)/60) b=abs(py-(cy(sh_ed.p[i].y)+(int)(slope*(px-cx(sh_ed.p[i].x))))); } else { /* BUGFIX BG: Don't divide by zero. core dumper. */ if (dy == 0) slope = 0; else slope=(float)dx/(float)dy; b=cy(sh_ed.p[i].y)-py; if (((b<0)&&(dy>0))||((b>0)&&(dy<=0))) { b=py-cy(sh_ed.p[np].y); if (((b<0)&&(dy>0))||((b>0)&&(dy<=0))) b=0; } if (b<0) b=-b; if (b<(pm_area_h-20)/60) b=abs(px-(cx(sh_ed.p[i].x)+(int)(slope*(py-cy(sh_ed.p[i].y))))); } if ((b<(pm_area_w-20)/60)&&(b15) i=15; return i; } /* Coordinate conversion */ int ry(int y) { int i; i=y-5; i=(int)(i*30/(pm_area_h-20))-15; if (i<-15) i=-15; if (i>15) i=15; return -i; } /* Coordinate conversion */ int rs(int i) { float f=(SPM_SIZE/40.0); return (int)((i+20)*f); } char * stringupp(char *s) /* make a string uppercase */ { static char kaas[1000]; char *c; strncpy(kaas, s, sizeof(kaas)); kaas[sizeof(kaas) - 1] = '\0'; c = kaas; while(*c) { *c = toupper(*c); c+=1; } return kaas; } /* Parse value in s into definition p */ void fillin(char *s, fileinfo p) { int di; /* dummy's */ float df; if (strstr(p.parse,"%S")!=NULL) { /* capitalize string */ strcpy(p.varad,stringupp(s)); return; } if (strstr(p.parse,"%s")!=NULL) { /* string */ strcpy(p.varad,s); return; } if (strstr(p.parse,"%>s")!=NULL) { /* append string */ strcat(p.varad,p.def); strcat(p.varad,s); strcat(p.varad,"\n"); return; } if (strstr(p.parse,"%>S")!=NULL) { /* append capit. string */ strcat(p.varad,p.def); strcat(p.varad,stringupp(s)); strcat(p.varad,"\n"); return; } if (strstr(p.parse,"%b")!=NULL) { /* handle boolean */ if ((!strcasecmp(s,"true"))||(!strcasecmp(s,"on"))||(!strcasecmp(s,"yes"))) *(int *)p.varad=1; else *(int *)p.varad=0; return; } if (strstr(p.parse,"%t")!=NULL) { /* handle troolean */ if ((!strcasecmp(s,"true"))||(!strcasecmp(s,"on"))||(!strcasecmp(s,"yes"))) *(int *)p.varad=1; else if (!strcasecmp(s,"none")) *(int *)p.varad=NONE; else *(int *)p.varad=0; return; } if (strstr(p.parse,"%i")!=NULL) { /* handle int */ di=atoi(s); *(int *)p.varad=di; } if (strstr(p.parse,"%f")!=NULL) { /* handle float */ df=atoi(s); *(float *)p.varad=df; } } /* parse file f and p */ int parsefile(char *f, fileinfo *p) { int i=0; FILE *fin; char a1[1000], a2[1000], a3[1000], a4[1000]; char *b1; fin=fopen(f,"r"); /* open the default file */ /* else change to defaults first! */ while (p[i].parse!=NULL) { if (strstr(p[i].parse,"%>")!=NULL) strcpy(p[i].varad,"\0"); else fillin(p[i].def,p[i]); i++; } if (fin==NULL) return FALSE; /* do nothing if no file */ while (!feof(fin)) { /* read the entire file! */ a2[0]='\0'; fscanf(fin,"%[^\n]%[\n]",a1,a4); /* read to EOL */ sscanf(a1,"%[^:#*\t ]%[:*\t ]%[^*\t]",a2,a4,a3); /* strings */ a4[0]='\0'; sscanf(&a3[1],"%[^#]",a4); a3[1]='\0'; strcat(a3,a4); b1=&a3[strlen(a3)-1]; /* strip last spaces */ i=FALSE; while ((b1!=a3)&&(*b1==' ')) { b1--; i=TRUE; } if (i) { b1++; if (*b1==' ') *b1='\0'; } i=0; while ((p[i].parse!=NULL)&&(strcasecmp(p[i].key,a2))) i++; if (p[i].parse!=NULL) { fillin(a3, p[i]); } } fclose (fin); return TRUE; } void loaddefs(void) /* load defaults */ { char a[100],b[100]; /* dummy strings */ static fileinfo parray[] = { {"%i","buttonbox_border",&bb_bor,"1"}, {"%i","value_border",&va_bor,"0"}, {"%s","buttonbox_b",&bb_bs,"white"}, {"%s","buttonbox_f",&bb_fs,"black"}, {"%s","namelist_b",&nl_bs,"white"}, {"%s","namelist_f",&nl_fs,"black"}, {"%s","status_b",&st_bs,"white"}, {"%s","status_f",&st_fs,"black"}, {"%s","button_high_b",&bh_bs,"white"}, {"%s","button_high_f",&bh_fs,"black"}, {"%s","button_toggle_b",&bt_bs,"white"}, {"%s","button_toggle_f",&bt_fs,"black"}, {"%s","button_action_b",&ba_bs,"white"}, {"%s","button_action_f",&ba_fs,"black"}, {"%s","smallfont",&fontname,"8x13"}, {"%s","shiplib",&shiplib,".xpilotrc"}, {"%s","maincol",&mc,"black"}, {"%s","leftcol",&lc,"black"}, {"%s","rightcol",&rc,"black"}, {NULL,NULL,NULL,NULL} }; a[0]='\0'; b[0]='\0'; strcpy(b,userpath()); strcat(b,"/.editssrc"); isdefault=parsefile(b,parray); } /* Read ships from shiplib, display them */ void getdir(void) { char a[MAXSHIPLEN], b[MAXLINELEN]; int i1, i; Dimension x, y; ship *sh; shiplist *slp, *slpp; FILE *fin; while (sl!=NULL) { /* BUGFIX BG: Don't access memory after free(). core dumper. */ slp = sl->n; sl->n = NULL; Free_Shiplist(sl); sl = slp; } strcpy(b,userpath()); if (strlen(b)==0) printf("WARNING! Cannot determine home directory\n"); strcat(b,"/"); strcat(b,shiplib); fin=fopen(b,"r"); if (pm_ships>0) { XFillRectangle(XtDisplay(toplevel),pm_ships,gc_draw,0,0,SPM_SIZE,SPM_SIZE*nrships); XCopyArea(XtDisplay(shipbm), pm_ships, XtWindow(shipbm), DefaultGCOfScreen(XtScreen(toplevel)), 0, 0, SPM_SIZE, SPM_SIZE*nrships, 0,0); XFreePixmap(XtDisplay(toplevel),pm_ships); } nrships=0; while (getoneshipdef(a,fin)) { nrships+=1; } if (fin!=NULL) fclose(fin); if (nrships<1) i1=1; else i1=nrships; a[0]='\0'; pm_ships = XCreatePixmap(XtDisplay(toplevel), RootWindowOfScreen(XtScreen(toplevel)), SPM_SIZE,SPM_SIZE*i1,scr_depth); XtResizeWidget(shipbm, SPM_SIZE,SPM_SIZE*i1, 0); XFillRectangle(XtDisplay(toplevel),pm_ships,gc_draw,0,0,SPM_SIZE,SPM_SIZE*i1); fin=fopen(b,"r"); nrships=0; a[0]='\0'; b[0]='\0'; slp = NULL; while(getoneshipdef(a, fin)) { sh=Convert_shape_str(strchr(a,'(')); if (sh!=NULL) { if (sl == NULL) { sl = Alloc_Shiplist(); slp = sl; } else { slp->n = Alloc_Shiplist(); slp = slp->n; } slp->s = sh; for (i=0; in; i++) { if (in-1) 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); else 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); } nrships+=1; } } if (slp!=NULL) slp->n = NULL; XCopyArea(XtDisplay(shipbm), pm_ships, XtWindow(shipbm), DefaultGCOfScreen(XtScreen(toplevel)), 0, 0, SPM_SIZE, SPM_SIZE*i1, 0,0); XtVaGetValues(shipview, XtNwidth, &x, XtNheight, &y, NULL); XtResizeWidget(shipview, x, y+1, 1); XtResizeWidget(shipview, x, y, 1); if (fin) fclose(fin); XtSetSensitive(b_psout, (nrships>0)); } /* The main */ int main(int argc, char **argv) { ship *newship; sl = NULL; printf("%s (c) 1994 R. In 't Velt \n",VERSION); loaddefs(); cleanship(&sh_ed); shipname[0]='\0'; x_init(argc, argv); drawmode=DM_NONE; if ((argc>=2)&&(strchr(argv[1],'(')!=NULL)) { newship=Convert_shape_str(argv[1]); cpyship(&sh_ed, newship); Free_ship_shape(newship); } XtAppMainLoop(app_context); return 0; }