Rev 6525 | Rev 8155 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
17 | |||
5504 | bpr | 18 | /* automatic selection of math rendering method */ |
10 | reyssat | 19 | |
20 | void exec_instex(char *p); |
||
21 | void calc_instexst(char *p); |
||
22 | |||
23 | struct { |
||
24 | char src[124], name[128]; |
||
25 | int size; |
||
26 | } oldinstex[100]; |
||
27 | int oldtexcnt=0; |
||
28 | |||
5504 | bpr | 29 | /* check whether the same tex source has already been produced */ |
10 | reyssat | 30 | int instex_ready(char *p, char *n) |
31 | { |
||
32 | int i; |
||
33 | char *cl, buf[MAX_LINELEN+1]; |
||
7673 | bpr | 34 | |
10 | reyssat | 35 | if(strlen(p)>=124) return 0; |
36 | cl=getvar("instex_color"); if(cl!=NULL && *cl!=0) return 0; |
||
37 | mystrncpy(buf,p,sizeof(buf)); tex_nospace(buf); |
||
38 | for(i=0;i<oldtexcnt;i++) { |
||
5504 | bpr | 39 | if(oldinstex[i].size==current_tex_size && |
40 | strcmp(oldinstex[i].src,buf)==0) { |
||
41 | ovlstrcpy(n,oldinstex[i].name); return 1; |
||
42 | } |
||
10 | reyssat | 43 | } |
44 | if(strlen(n)>=128 || oldtexcnt>=100) return 0; |
||
3718 | reyssat | 45 | ovlstrcpy(oldinstex[oldtexcnt].src,buf); |
46 | ovlstrcpy(oldinstex[oldtexcnt].name,n); |
||
10 | reyssat | 47 | oldinstex[oldtexcnt].size=current_tex_size; |
48 | oldtexcnt++; return 0; |
||
49 | } |
||
50 | |||
5504 | bpr | 51 | /* returns NULL if instex can use static */ |
10 | reyssat | 52 | char *instex_check_static(char *p) |
53 | { |
||
54 | char *f; |
||
55 | if(instex_usedynamic) return p; |
||
56 | for(f=strchr(p,'$'); |
||
5504 | bpr | 57 | f!=NULL && *(f+1)!='(' && *(f+1)!='[' && *(f+1)!='_' && !isalnum(*(f+1)); |
58 | f=strchr(f+2,'$')); |
||
10 | reyssat | 59 | if(f==NULL) f=strstr(m_file.name,"sessions/"); |
60 | return f; |
||
61 | } |
||
62 | |||
63 | char tnames[]="sqrt int integrate sum prod product \ |
||
64 | Int Sum Prod conj abs"; |
||
65 | |||
5617 | bpr | 66 | int __gototex (char *p, char *f, int ts) |
5611 | bpr | 67 | { |
68 | char alignbak[2048]; |
||
5617 | bpr | 69 | char *pp, buf[MAX_LINELEN+1]; |
70 | ovlstrcpy(buf,p); |
||
5611 | bpr | 71 | instex_style="$$"; |
72 | if(!ts) texmath(buf); |
||
7673 | bpr | 73 | /* ts=0 but there is some computer matrix to transform |
5611 | bpr | 74 | * done by texmath, but it does much more as replacing strings in tmathfn |
75 | * OK if buf contains " math computer-syntax" ; if not, the result may be bad |
||
76 | */ |
||
77 | else {// seems tex : need to interpret names of variables as \x or \calB |
||
78 | //if (mathalign_base < 2) { //to check |
||
79 | char *p1; |
||
80 | p1=find_word_start(buf); |
||
81 | if(*p1=='\\') { |
||
82 | int i; |
||
83 | char *pt; |
||
84 | for(i=1;isalnum(p1[i]);i++); /* find an alphanumeric string beginning by \\ */ |
||
85 | if(p1[i]==0 && (pt=mathfont(p1))!=NULL) { |
||
5617 | bpr | 86 | _output_(pt); *p=0; return 1; |
5611 | bpr | 87 | } |
88 | } |
||
89 | // } |
||
90 | } |
||
91 | /* send to mathml */ |
||
7673 | bpr | 92 | if (mathalign_base == 2 && mathml(buf,0)) { *p=0 ;return 1; } |
5611 | bpr | 93 | /* end if mathml option in case ts=1 or "computer matrix" */ |
94 | |||
95 | /* creating images*/ |
||
96 | pp=getvar("ins_align"); |
||
97 | if(pp!=NULL) mystrncpy(alignbak,pp,sizeof(alignbak)); |
||
98 | setvar("ins_align","middle"); |
||
99 | mystrncpy(ins_alt,buf,sizeof(ins_alt)); |
||
100 | if(f==NULL) { |
||
101 | calc_instexst(buf); output("%s",buf); |
||
102 | } |
||
103 | else { |
||
104 | instex_usedynamic=1; exec_instex(buf); instex_usedynamic=0; |
||
105 | } |
||
7673 | bpr | 106 | instex_style=""; |
5611 | bpr | 107 | if(alignbak[0]) setvar("ins_align",alignbak); |
5617 | bpr | 108 | *p=0; return 0; |
7673 | bpr | 109 | } |
5611 | bpr | 110 | |
5504 | bpr | 111 | /* Intelligent insertion of math formulas, kernel */ |
10 | reyssat | 112 | void __insmath(char *p) |
113 | { |
||
114 | char *f, *pp, *pe, *p1, buf[MAX_LINELEN+1], nbuf[256]; |
||
115 | int ts, n, rawmathready; |
||
116 | |||
5465 | bpr | 117 | ovlstrcpy(buf,p); strip_trailing_spaces(buf); singlespace(buf); |
10 | reyssat | 118 | p1=getvar("insmath_slashsubst"); |
7673 | bpr | 119 | if(p1!=NULL && strstr(p1,"yes")!=NULL) slashsubst(buf); // substitute backslash parameters |
5465 | bpr | 120 | f=instex_check_static(buf); //decide if image already exists |
5512 | bpr | 121 | substit(buf);//substitute the variables |
5465 | bpr | 122 | /* here replace .. by , : i=1 .. 5 -> i=1, 5 !*/ |
10 | reyssat | 123 | for(pp=strstr(buf,".."); pp!=NULL; pp=strstr(pp,"..")) { |
5512 | bpr | 124 | if(*(pp+2)=='.' || *(pp+2)==',') { |
5504 | bpr | 125 | do pp++; while(*pp=='.'); continue; |
5512 | bpr | 126 | } |
127 | *pp=','; *(pp+1)=' '; |
||
10 | reyssat | 128 | } |
5512 | bpr | 129 | /* decide if it should be tex */ |
10 | reyssat | 130 | ts=0; if(strchr(buf,'\\') || strchr(buf,'}')) ts=1; |
5512 | bpr | 131 | /* if not and if variable insmath_rawmath is there, do rawmath */ |
7673 | bpr | 132 | rawmathready=0; |
5523 | bpr | 133 | if(!ts) { /* not tex, looking if rawmath is asked */ |
5504 | bpr | 134 | pp=getvar("insmath_rawmath"); |
135 | if(pp!=NULL && strstr(pp,"yes")!=NULL) { |
||
136 | rawmath(buf); rawmathready=1; |
||
137 | } |
||
10 | reyssat | 138 | } |
5523 | bpr | 139 | if(ts) { |
140 | _replace_matrix (buf,"\\matrix{","matrix"); //could be done in any case if ts=1 |
||
141 | _replace_matrix (buf,"\\pmatrix{","pmatrix"); |
||
142 | } |
||
143 | /* if ts=1 (it should be a tex formula) or if there is a [ , ; ] matrix */ |
||
7673 | bpr | 144 | if(ts || |
5523 | bpr | 145 | (strchr(buf,'[')!=NULL && (strchr(buf,',')!=NULL || strchr(buf,';')!=NULL))) { |
5611 | bpr | 146 | if(__gototex(buf, f, ts)) return; |
10 | reyssat | 147 | } |
5523 | bpr | 148 | |
149 | /* end creating images |
||
150 | * we are now in the case where ts=0 and no need of tex for matrix */ |
||
151 | |||
152 | /* find math variables */ |
||
10 | reyssat | 153 | for(pp=find_mathvar_start(buf); *pp; pp=find_mathvar_start(pe)) { |
5504 | bpr | 154 | pe=find_mathvar_end(pp); n=pe-pp; |
5523 | bpr | 155 | /* non alpha variable or too short or too long to be interpreted as tnames */ |
7673 | bpr | 156 | if(!isalpha(*pp) || n<3 || n>16) continue; |
5504 | bpr | 157 | memmove(nbuf,pp,n); nbuf[n]=0; |
5611 | bpr | 158 | if(wordchr(tnames,nbuf)!=NULL) { if(__gototex(buf, f, 0)) return;} |
7673 | bpr | 159 | /* find sqrt int integrate sum prod product Int Sum Prod conj abs, |
5523 | bpr | 160 | * so must be texmath interpretated ; after going to tex, return in any case |
161 | */ |
||
10 | reyssat | 162 | } |
7673 | bpr | 163 | /* look for / to interpretate as quotients - |
164 | * extend the version by accepting something else than ( |
||
165 | */ |
||
5523 | bpr | 166 | //for(pp=strchr(buf,'/'); pp!=NULL && *find_word_start(pp+1)!='('; pp=strchr(pp+1,'/')); |
167 | pp=strchr(buf,'/'); |
||
5611 | bpr | 168 | if(pp!=NULL){ if( __gototex(buf,f,0)) return;} /* so a/4 can be reinterpreted as {a over 4 } ; transform also 5/(x+1) */ |
10 | reyssat | 169 | if(rawmathready) rawmath_easy=1; |
170 | for(pp=strchr(buf,'<'); pp!=NULL; pp=strchr(pp+1,'<')) |
||
171 | string_modify(buf,pp,pp+1,"<"); |
||
172 | for(pp=strchr(buf,'>'); pp!=NULL; pp=strchr(pp+1,'>')) |
||
173 | string_modify(buf,pp,pp+1,">"); |
||
5544 | bpr | 174 | /* no tex has been introduced - so go to mathmlmath */ |
5611 | bpr | 175 | mathmlmath(buf); output("%s",buf); |
5465 | bpr | 176 | rawmath_easy=0; |
10 | reyssat | 177 | } |
178 | |||
5523 | bpr | 179 | /* the following is not used in modules : no insmath_logic=yes somewhere */ |
180 | |||
10 | reyssat | 181 | char *andor[]={"and","or","not","is","isnot"}; |
182 | #define andorcnt (sizeof(andor)/sizeof(andor[0])) |
||
183 | char *andorlang[andorcnt], andorlangbuf[1024]; |
||
184 | int andorlangcnt=-1; |
||
185 | |||
5504 | bpr | 186 | /* Processing logic statements in math formulas */ |
10 | reyssat | 187 | void _mathlogic(char *p, void _put(char *pp)) |
188 | { |
||
189 | char *p1, *p2, *ps; |
||
190 | int i; |
||
191 | if(strstr(p,"qzis")==NULL) { |
||
5504 | bpr | 192 | for(i=0;i<andorcnt && varchr(p,andor[i])==NULL; i++); |
193 | if(i>=andorcnt) { |
||
194 | _put(p); return; |
||
195 | } |
||
10 | reyssat | 196 | } |
197 | if(andorlangcnt<0) { |
||
5504 | bpr | 198 | char buf[MAX_LINELEN+1]; |
199 | accessfile(buf,"r","bases/sys/andor.%s",lang); |
||
200 | mystrncpy(andorlangbuf,find_word_start(buf),sizeof(andorlangbuf)); |
||
201 | for(i=0,p1=andorlangbuf;i<andorcnt;i++,p1=find_word_start(p2)) { |
||
202 | p2=strchr(p1,','); |
||
203 | if(p2==NULL) p2=p1+strlen(p1); else *p2++=0; |
||
204 | strip_trailing_spaces(p1); |
||
205 | if(*p1) andorlang[i]=p1; else break; |
||
10 | reyssat | 206 | } |
5504 | bpr | 207 | andorlangcnt=i; |
208 | } |
||
10 | reyssat | 209 | for(ps=p, p1=find_mathvar_start(p); *p1; p1=find_mathvar_start(p2)) { |
5504 | bpr | 210 | p2=find_mathvar_end(p1); |
211 | if(!isalpha(*p1)) continue; |
||
212 | if(strncmp(p1,"qzis",4)==0) { |
||
213 | char *p3, *p4, *p5; |
||
6525 | bpr | 214 | /*int tt;*/ |
5504 | bpr | 215 | p4=find_word_start(p2); |
216 | if(*p4!='(') continue; |
||
6525 | bpr | 217 | if(strncmp(p1+4,"not",3)==0) {/*tt=4;*/ p3=p1+7;} |
218 | else {/*tt=3; */p3=p1+4;} |
||
5504 | bpr | 219 | if(!isalpha(*p3)) continue; |
220 | p4++; p5=find_matching(p4,')'); |
||
221 | if(*p5!=')') continue; |
||
222 | *p5=0; *p2=0; p2=p5+1; |
||
7673 | bpr | 223 | |
224 | |||
5504 | bpr | 225 | continue; |
226 | } |
||
227 | for(i=0;i<andorlangcnt;i++) if(strncmp(p1,andor[i],p2-p1)==0) break; |
||
228 | if(i<andorlangcnt) { |
||
229 | *p1=0; ps=find_word_start(ps); if(*ps) _put(ps); |
||
230 | output(" %s ",andorlang[i]); ps=p2; |
||
231 | } |
||
10 | reyssat | 232 | } |
233 | ps=find_word_start(ps); if(*ps) _put(ps); |
||
234 | } |
||
235 | |||
5504 | bpr | 236 | /* Intelligent insertion of math formulas */ |
10 | reyssat | 237 | void insmath(char *p) |
238 | { |
||
239 | char *pt; |
||
240 | if(!outputing) goto end; |
||
241 | pt=getvar("insmath_logic"); |
||
242 | if(pt==NULL || strstr(pt,"yes")==NULL) { |
||
7673 | bpr | 243 | __insmath(p); |
5504 | bpr | 244 | end: *p=0; return; |
10 | reyssat | 245 | } |
246 | _mathlogic(p,__insmath); |
||
247 | } |