/* Help compiler */ #include "common.h" #define DEBPRT 0 #define HELP #include "conthelp.h" #undef HELP #define TMPFILE "inentryx.tmp" #define TMPFILE1 "inentry1.tmp" static void HelpCompile(CharPtr source, CharPtr target); typedef struct { /* Index endtry */ CharPtr key; /* topic's key; used in \jump */ CharPtr extkey; /* external (i.e. visible to user) key */ CharPtr cond; /* condition when the topic is visible in search list */ long pos; /* in file */ } HelpEntry, PNTR HelpEntryPtr; static struct { CharPtr name; SpecialCode code; } Specials[]={ {"matrix", SS_MATRIX}, {"determinant", SS_DETERMINANT}, {"system", SS_SYSTEM}, {"table", SS_TABLE}, {"hat", SS_HAT}, {"tilde", SS_TILDE}, {"bar", SS_BAR}, {"dot", SS_DOT}, {"bardot", SS_BARDOT}, {"sqrt", SS_SQRT}, {"brackets", SS_BRACKETS}, {"frac", SS_FRAC}, {"lim", SS_LIM}, {"min", SS_MIN}, {"max", SS_MAX}, {"inf", SS_INF}, {"sup", SS_SUP}, {"int"SUFF, SS_INT}, {"sum"SUFF, SS_SUM}, {"prod"SUFF, SS_PROD}, {"Int"SUFF, SS_INTL}, {"Sum"SUFF, SS_SUML}, {"Prod"SUFF, SS_PRODL}, {"", SS_}, /* separator */ {"topic", SC_TOPIC}, {"f", SC_F}, {"bf", SC_BF}, {"cf", SC_CF}, {"li", SC_LI}, {"fi", SC_FI}, {"par", SC_PAR}, {"sb", SC_SB}, {"sa", SC_SA}, {"qc", SC_CENTER}, {"qr", SC_RIGHT}, {"tabs", SC_STAB}, {"end", SC_END}, {"jump", SC_JUMP}, {"include", SC_INCLUDE}, {"picture", SC_PICTURE}, {"desc", SC_DESC}, {"verbatim", SC_VERBATIM}, {"level", SC_LEVEL}, {"cond", SC_COND} }; typedef struct{ long fileptr; int object_code; int depth; int color; int fill_color; int area_fill; int line_style; /* font for P_TEXT */ #define TEXT_font line_style int thickness; /* font_size for P_TEXT */ #define TEXT_font_size thickness } ObjRef, PNTR ObjRefPtr; static int Xmin,Xmax,Ymin,Ymax; static int Dx,Dy; static int Wmin; static void MinMax(int x, int y) { if (Xmin>x) Xmin=x; if (Ymin>y) Ymin=y; if (Xmaxdepth==((ObjRefPtr)e2)->depth) return 0; if (((ObjRefPtr)e1)->depth>((ObjRefPtr)e2)->depth) return -1; return 1; } static int fig_resolution; static ObjRefPtr BuildIndex(FILE *fig, int *n) { ObjRefPtr index; FILE *tmp; ObjRef or; FloatLo fx,fy,fw; int x,y,rx,ry,pos,pn,i; tmp=fopen(TMPFILE,"w+b"); Xmin=MAXINT; Xmax=0; Ymin=MAXINT; Ymax=0; Wmin=MAXINT; /* Check the version */ if (fscanf(fig," #FIG %i.%i",&x,&y)!=2) { Message(MSG_OK,"This is not an xfig file"); abort(); } if (x!=3 || y!=1) { Message(MSG_OK,"The version of xfig file is %i.%i. Must be 3.1",x,y); abort(); } rewind(fig); /* skip 'header' */ for (i=0; i<4; i++) fscanf(fig,"%*[^\n]\n"); fscanf(fig,"%i %*[^\n]\n",&fig_resolution); while (!feof(fig)) { if (fscanf(fig," %i",&or.object_code)!=1) break; or.fileptr=ftell(fig); switch (or.object_code) { case P_ELLIPSE: fscanf(fig,"%*i %i %i %i %i %i %*i %i %*g %*i %*g%n %i %i %i %i %*i %*i %*i %*i", &or.line_style,&or.thickness,&or.color,&or.fill_color,&or.depth,&or.area_fill,&pos,&x,&y,&rx,&ry); MinMax(x-rx,y-ry); MinMax(x+rx,y+ry); or.fileptr+=pos; /* to center_x */ fwrite(&or,sizeof(or),1,tmp); if (Wmin>or.thickness) Wmin=or.thickness; break; case P_POLYLINE: fscanf(fig,"%*i %i %i %i %i %i %*i %*i %*g %*i %*i %*i %*i %*i%n %i", &or.line_style,&or.thickness,&or.color,&or.fill_color,&or.depth,&pos,&pn); for (i=0; ior.thickness) Wmin=or.thickness; break; case P_SPLINE: fscanf(fig,"%i %i %i %i %i %i %*i %*i %*g %*i %*i %*i%n %i", &i,&or.line_style,&or.thickness,&or.color,&or.fill_color,&or.depth,&pos,&pn); if (i>=2) or.object_code=P_SPLINEI; if (i&1) or.object_code=-or.object_code; /* <0 means closed spline */ for (i=0; ior.thickness) Wmin=or.thickness; break; case P_TEXT: fscanf(fig,"%*i %i %i %*i %i %g %*g %*i %n%g %g %i %i %*[^\n]\n", &or.color,&or.depth,&or.TEXT_font,&fw,&pos,&fy,&fx,&x,&y); or.TEXT_font_size=fw; rx=(int)fx; ry=(int)fy; MinMax(x,y-ry); MinMax(x+rx,y); or.fileptr+=pos; /* to height */ or.fill_color=0; fwrite(&or,sizeof(or),1,tmp); break; case P_ARC: fscanf(fig,"%*i %i %i %i %i %i %*i %i %*g %*i %i %*i %*i%n %g %g %i %i %*i %*i %*i %*i", &or.line_style,&or.thickness,&or.color,&or.fill_color,&or.depth,&or.area_fill,&i,&pos,&fx,&fy,&x,&y); if (i==1) or.object_code=-P_ARC; /* 1=counterclockwise */ fw=sqrt((fx-x)*(fx-x)+(fy-y)*(fy-y)); MinMax(round(fx-fw),round(fy-fw)); MinMax(round(fx+fw),round(fy+fw)); or.fileptr+=pos; /* to center_x */ fwrite(&or,sizeof(or),1,tmp); if (Wmin>or.thickness) Wmin=or.thickness; break; case P_COMPOUND: fscanf(fig,"%*i %*i %*i %*i"); break; case P_COMPOUNDE: break; default: Message(MSG_OK,"Unknown object_code %i",or.object_code); abort(); } } *n=(int)(ftell(tmp)/sizeof(or)); index=MemNew(ARRAYSIZE(ObjRef,*n)); rewind(tmp); for (i=0; i<*n; i++) { fread(index+i,sizeof(or),1,tmp); if (index[i].fill_color<0) index[i].fill_color=0; /* default is black */ switch (index[i].object_code) { case P_ELLIPSE: switch (index[i].area_fill) { case 0: /* see xfig file protocol */ switch (index[i].fill_color) { case -1: /* def */ case 0: /* black */ /* fill white is the same as don't fill or fill background */ index[i].fill_color=-1; break; default: /* any except def and black is white */ index[i].fill_color=0; /* black */ } break; case 20: break; default: index[i].fill_color=-1; /* don't fill */ } } /* switch */ } /* for */ qsort(index,*n,ARRAYSIZE(ObjRef,1),CmpObj); fclose(tmp); unlink(TMPFILE); Dx=Xmax-Xmin+1; Dy=Ymax-Ymin+1; return index; } /* Output: %i fig_resolution (fig units/inch) %g Width of the picture mesured in current help slate's width. %i Dx and %i Dy dimensions of source picture. %i Number of objects. ... objects ... %c \001 (end of picture indicator). Objects, common fields: %i Code (see P_... constants). %i Color. %i Fill color. %i Line style (font for P_TEXT). %i Thickness. Objects, specific fields: Code==P_ELLIPSE: %i upperleft_x, %i upperleft_y, %i lowerright_x, %i lowerright_y of bounding rectangle. %i 1 - fill, 0 - don't fill. Code==P_POLYLINE: %i number of points. %i %i x and y coordinats of points. Code==P_TEXT: %i height of text, %i length of text, %i lowerleft_x, %i lowerleft_y, %s text. */ static CharPtr PreprocessPicture(CharPtr q, FILE *tf) { FILE * fig; CharPtr p; ObjRefPtr index; ObjRefPtr or; FloatLo w,fx,fy; int pos,n,i,j,pn,x,y,rx,ry; Boolean closed; Char figname[PATH_MAX],text[300]; sscanf(q,"%f %[^ \n\t{}\\]%n",&w,figname,&pos); fig=fopen(figname,"rt"); index=BuildIndex(fig,&n); fprintf(tf,"%i %g %i %i",fig_resolution,w,Dx,Dy); fprintf(tf," %i\n",n); /* number of objects */ for (i=0; iobject_code, or->color, or->fill_color, or->line_style, /* font for P_TEXT */ or->thickness-((or->object_code==P_TEXT?0:Wmin)-0)); fseek(fig,or->fileptr,SEEK_SET); switch (or->object_code) { case P_ELLIPSE: fscanf(fig,"%i %i %i %i",&x,&y,&rx,&ry); x-=Xmin; y-=Ymin; fprintf(tf,"%i %i %i %i",x-rx,y-ry,x+rx,y+ry); fprintf(tf," %i",or->area_fill<0 ? 0 : 1); break; case -P_SPLINE: case -P_SPLINEI: closed=TRUE; goto poly; case P_POLYLINE: case P_SPLINE: /* uninterpolated spline is stored as polyline */ case P_SPLINEI: closed=FALSE; poly: fscanf(fig,"%i",&pn); fprintf(tf,"%i",closed ? pn+1 : pn); for (j=0; jobject_code)==P_SPLINEI) { for (j=0; jobject_code=or->object_code==P_SPLINEI ? P_SPLINE : -P_SPLINE; } break; case P_TEXT: fscanf(fig,"%g %g %i %i %[^\n]\n",&fy,&fx,&x,&y,text); x-=Xmin; y-=Ymin; p=StrStr(text,"\\001"); if (p) *p='\0'; if (StrChr(text+1,'\\')) { /* trick: translate special symbols inside $...$ */ FILE *tmp; int o; tmp=fopen(TMPFILE,"wt"); if (tmp) { for (; p=StrStr(text,"\\\\"),p; ) /* xfig adds \ to \ in text objects */ StrCpy(p,p+1); o=text[0]=='\\' ? 3 : 0; fputs(text+o,tmp); fclose(tmp); HelpCompile(TMPFILE,TMPFILE1); tmp=fopen(TMPFILE1,"rt"); if (tmp) { fseek(tmp,(long)sizeof(Int2),SEEK_SET); /* skip number of entries in index (0 here) */ fgets(text+o,sizeof(text)-o,tmp); fclose(tmp); } } unlink(TMPFILE); unlink(TMPFILE1); } fprintf(tf," %i %i %i %i %s",round(fy),round(fx),x,y,text); break; case P_ARC: case -P_ARC: fscanf(fig,"%g %g %i %i %*i %*i %i %i",&fx,&fy,&x,&y,&rx,&ry); fx-=Xmin; fy-=Ymin; x-=Xmin; y-=Ymin; rx-=Xmin; ry-=Ymin; w=sqrt((fx-x)*(fx-x)+(fy-y)*(fy-y)); fprintf(tf,"%i %i %i %i %i %i %i %i", (int)round(fx-w),(int)round(fy-w),(int)round(fx+w),(int)round(fy+w), x,y,rx,ry); break; } fputc('\n',tf); } fputc(001,tf); /* end of picture indicator */ fclose(fig); MemFree(index); return q+pos; } typedef struct { /* Forward jump descriptor */ long pos; /* where the file ptr is */ Int2 subscript; /* jump to topic described by hep[subscript] */ } HelpZap, PNTR HelpZapPtr; /* qsort callback */ static int CmpEntries(const void * e1, const void * e2) { int cmp; cmp=StrCmp(((HelpEntryPtr)e1)->key,((HelpEntryPtr)e2)->key); return cmp; } static void WriteIndex(FILE *tf, HelpEntryPtr hep, Int2 n) { CharPtr cond; Int2 i; rewind(tf); fwrite(&n,sizeof(n),1,tf); #if DEBPRT if (hep[0].pos) printf("***** *****\n"); #endif for (i=0; i=0; } if (compile) { #if _UNIX if (StrCmp(source,TMPFILE)) printf("Help compiler: %s ==> %s\n",source,target); #endif sf=fopen(source,"rt"); tf=fopen(target,"w+b"); DefNum=1; DefSkip=FALSE; DefTab[0]=StringSave( #if _MAC "_MAC" #endif #if _WIN "_WIN" #endif #if _UNIX "_UNIX" #endif ); /* Build the content of the help file */ bs=BSNew(100*sizeof(HelpEntry)); he.cond=NULL; while (!feof(sf)) { fgets(b,sizeof(b),sf); p=StrStr(b,"\\%"); if (p) *p='\0'; /* Preprocessor directives */ if (s=e=0,sscanf(b,"#define %n%*s%n",&s,&e),e>0) { if (DefNum>=DIM(DefTab)) { Message(MSG_OK,"You cannot define more than %i names",DefNum); DefNum=0; } DefTab[DefNum]=MemNew(e-s+1); b[e]='\0'; StrCpy(DefTab[DefNum++],b+s); continue; } if (s=e=0,sscanf(b,"#ifdef %n%*s%n",&s,&e),e>0) { b[e]='\0'; DefSkip=TRUE; for (i=0; i0) { b[e]='\0'; for (i=0; i0) { /* has been stored on the first pass */ continue; } if (s=e=0,sscanf(b,"#ifdef %n%*s%n",&s,&e),e>0) { b[e]='\0'; DefSkip=TRUE; for (i=0; i0) { b[e]='\0'; for (i=0; i': fputc(SC_TAB,tf); break; case ',': fputc('#',tf); fputc(SS_SPACE1,tf); break; case ':': fputc('#',tf); fputc(SS_SPACE2,tf); break; case ';': fputc('#',tf); fputc(SS_SPACE3,tf); break; case '!': fputc('#',tf); fputc(SS_SPACE_1,tf); break; case '+': fputc(SC_PS,tf); break; case '|': fputc(SC_CAT,tf); break; case '{': c[0]='{'; goto brace; case '}': c[0]='}'; brace:; for (i=1; i