/* Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
*
* 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.
*/
#include "wims.h"
/* internal variable */
int rawmath_easy=0;
struct hmname hmname[]={
{"CC", "", ""},
{"Delta", "", ""},
{"Gamma","", ""},
{"Inf", "$(m_infty)","\\infty"},
{"Lambda","", ""},
{"NN", "", ""},
{"Omega", "", ""},
{"Phi", "", ""},
{"Pi", "", ""},
{"Psi", "", ""},
{"QQ", "",""},
{"RR", "",""},
{"Sigma", "",""},
{"Xi", "",""},
{"ZZ", "",""},
{"alpha", "", ""},
{"beta", "", ""},
{"cap", "",""},
{"chi", "",""},
{"cup", "",""},
{"delta", "",""},
{"div", "÷", "÷"},
{"divide","÷","÷"},
{"epsilon","$(m_varepsilon)","\\varepsilon"},
{"eta", "",""},
{"exist", "$(m_exists)","\\exists"},
{"exists","", ""},
{"forall","",""},
{"gamma", "",""},
{"in", "",""},
{"inf", "$(m_infty)","\\infty"},
{"infinity","$(m_infty)","\\infty"},
{"infty", "",""},
{"intersect","$(m_cap)", "\\cap"},
{"intersection","$(m_cap)", "\\cap"},
{"iota", "",""},
{"kappa", "",""},
{"lambda","", ""},
{"mu", "",""},
{"nabla", "",""},
{"neq", "",""},
{"nu", "",""},
{"omega", "",""},
{"pi", "",""},
{"pm", "",""},
{"psi", "",""},
{"rho", "",""},
{"sigma", "",""},
{"subset","", ""},
{"subseteq","",""},
{"tau", "",""},
{"theta", "",""},
{"times", "×", "\\times"},
{"union", "$(m_cup)", "\\cup"},
{"varepsilon","",""},
{"varphi","", ""},
{"x", "","x"},
{"xi","",""},
{"y", "","y"},
{"z", "","z"},
{"zeta","",""},
};
int hmname_no=(sizeof(hmname)/sizeof(hmname[0]));
enum {RM_UNKNOWN, RM_FN, RM_VAR, RM_PREFIX};
struct mathname mathname[]={
{"Arc", RM_PREFIX, "arc"},
{"Arg", RM_PREFIX, "arg"},
{"Ci", RM_FN, ""},
{"E", RM_VAR, ""},
{"Euler", RM_VAR, ""},
{"I", RM_VAR, ""},
{"Int", RM_FN, ""},
{"PI", RM_VAR, ""},
{"Pi", RM_VAR, ""},
{"Prod", RM_FN, ""},
{"Si", RM_FN, ""},
{"Sum", RM_FN, ""},
{"arc", RM_PREFIX, ""},
{"arg", RM_PREFIX, ""},
{"binomial",RM_FN, ""},
{"diff", RM_FN, ""},
{"e", RM_VAR, ""},
{"erf", RM_FN, ""},
{"euler", RM_VAR, ""},
{"i", RM_VAR, ""},
{"infinity",RM_VAR, ""},
{"int", RM_FN, ""},
{"integrate",RM_FN, ""},
{"neq", RM_VAR, ""},
{"pi", RM_VAR, ""},
{"prod", RM_FN, ""},
{"product", RM_FN, ""},
{"psi", RM_FN, ""},
{"sum", RM_FN, ""},
{"theta", RM_FN, ""},
{"x", RM_VAR, ""},
{"y", RM_VAR, ""},
{"z", RM_VAR, ""},
{"zeta", RM_FN, ""},
};
int mathname_no=(sizeof(mathname)/sizeof(mathname[0]));
char rm_vbuf[MAX_LINELEN+1],rm_fbuf[MAX_LINELEN+1];
char *rm_uservar[MAX_LINELEN+1],*rm_userfn[MAX_LINELEN+1];
int rm_uservars,rm_userfns;
/* add user-defined variables and function names,
* internal, only called by rawmath().
*/
void getuservar(void)
{
char *p1, *p2, *p;
rm_uservars=rm_userfns=0;
p=getvar("wims_rawmath_variables");
if(p!=NULL && *p!=0) {
ovlstrcpy(rm_vbuf,p);
for(p=rm_vbuf;*p;p++) if(*p==',') *p=' ';
for(p1=find_word_start(rm_vbuf);*p1;p1=find_word_start(p2)) {
rm_uservar[rm_uservars++]=p1;
p2=find_word_end(p1);
if(*p2!=0) *(p2++)=0;
}
}
p=getvar("wims_rawmath_functions");
if(p!=NULL && *p!=0) {
ovlstrcpy(rm_fbuf,p);
for(p=rm_fbuf;*p;p++) if(*p==',') *p=' ';
for(p1=find_word_start(rm_fbuf);*p1;p1=find_word_start(p2)) {
rm_userfn[rm_userfns++]=p1;
p2=find_word_end(p1);
if(*p2!=0) *(p2++)=0;
}
}
}
/* Try to split a word into recognizable variables */
char *mathname_split(char *p)
{
int c,i,j,type;
c=0;
beg: for(i=get_evalcnt()-1;
i--);
if(i>=0 && get_evaltype(i)>0) {
type=RM_FN;
gotit:
if(!*(p+j)) return p;
if(myisdigit(*(p+j)) && type!=RM_FN) return NULL;
if(!c) {string_modify(p,p+j,p+j," "); p+=j+1;}
else p+=j;
c++; goto beg;
}
for(i=mathname_no-1;
i>=0 &&
|| mathname[i].style==RM_PREFIX);
i--);
if(i>=0) {
type=mathname[i].style;
goto gotit;
}
for(i=0;i<rm_uservars &&
if(i<rm_uservars) {
type=RM_VAR;
j
=strlen(rm_uservar
[i
]); goto gotit
;
}
for(i=0;i<rm_userfns &&
if(i<rm_userfns) {
type=RM_FN;
j
=strlen(rm_userfn
[i
]); goto gotit
;
}
return NULL;
}
int __replace_badchar (char *p, char *old, char *new)
{
int cnt = 0;
char *p1 ;
while((p1
=strstr(p
,old
))!=NULL
) {
string_modify
(p
,p1
,p1
+strlen(old
),"%s",new
);
cnt++;
}
return cnt ;
}
/* translate |x| into abs(x)*/
int __replace_abs ( char *p )
{
char *p1, *p2 ;
while((p1
=strchr(p
,'|'))!=NULL
) {
p2=find_matching(p1+1,'|');
if(p2==NULL) { return 1; break;} /* error; drop it. */
*p2=')'; string_modify(p,p1,p1+1,"abs(");
}
return 0;
}
/* signs: translate ++, +-, -+, ... into one sign. */
void __replace_plusminus ( char *p )
{
char *p1, *p2;
for(p1=p;*p1!=0;p1++) {
int sign, redundant;
if(*p1!='+' && *p1!='-') continue;
if(*p1=='+') sign=1; else sign=-1;
redundant=0;
for(p2=find_word_start(p1+1);*p2=='+' || *p2=='-';
p2=find_word_start(p2+1)) {
if(*p2=='-') sign*=-1;
redundant=1;
}
if(redundant
&& *p2
!='>' && strncmp(p2
,">",4)!=0) {
if(sign==1) *p1='+'; else *p1='-';
ovlstrcpy(p1+1,p2);
}
}
}
/* dangling decimal points
* 4. --> 4.0 4.x -> 4.0x
* .5 -> 0.5
* another treatment is done in insmath (will replace .. by , )
*/
void __treat_decimal(char *p)
{
char *p1 ;
/* multiple .. is conserved */
if(*(p1+1)=='.') {
do p1++; while(*p1=='.'); continue;
}
if(p1>p && myisdigit(*(p1-1)) && myisdigit(*(p1+1))) continue;
/* Non-digit dangling '.' is removed */
if((p1<=p || !myisdigit(*(p1-1))) && !myisdigit(*(p1+1))) {
ovlstrcpy(p1,p1+1); p1--; continue;
}
if(p1==p || !myisdigit(*(p1-1))) { // nondigit.digit
string_modify(p,p1,p1,"0"); p1++; //add zero before point
}
if(!myisdigit(*(p1+1))) string_modify(p,p1+1,p1+1,"0"); //add zero after point
}
}
/* replace new-lines, tabs, " */
void __replace_space(char *p)
{
char *p1 ;
for(p1=p;*p1!=0; p1++) {
if(*p1
=='\\' || isspace(*p1
)) *p1
=' ';// replace \ and all spaces by a simple space -
if(*p1=='\"') { string_modify(p,p1,p1+1,"''"); p1++;} // replace " by ''
}
}
/* Error-tolerant raw math translation routine
* Translate error-laden raw math into machine-understandable form.
* do nothing if there is some { or \\
*/
void rawmath(char *p)
{
char *p1, *p2, *p3, *p4;
char warnbuf[1024];
int ambiguous=0,unknown=0,flatpower=0,badprec=0,unmatch=0;// for warning
/* looks like a TeX source : do nothing */
if(strchr(p
,'^')==NULL
) flatpower
=-1;
if(strlen(p
)>=MAX_LINELEN
) {*p
=0; return;}
p1=find_word_start(p);if(*p1==0) return;
while(*p1=='+') p1++;
if(p1>p) ovlstrcpy(p,p1);
(void)__replace_badchar(p,"**", "^");
(void)__replace_badchar(p,"\xa0", " ");
/*if (__replace_badchar(p,"²", "^2 ")) flatpower=1;
if (__replace_badchar(p,"³", "^3 ")) flatpower=1;
*/
if (__replace_badchar(p,"\xB2", "^2 ")) flatpower=1;
if (__replace_badchar(p,"\xB3", "^3 ")) flatpower=1;
unmatch=__replace_abs(p);
__replace_plusminus(p) ;
__replace_space(p);
__treat_decimal(p);
if (rawmath_easy) return;
/* Principal translation: justapositions to multiplications */
if(strstr(p
,"^1/")!=NULL
) badprec
=1;
getuservar();
for(p1=p;*p1;p1++) {
if(!isalnum(*p1
) && *p1
!=')' && *p1
!=']') continue;
if(*p1==')' || *p1==']') {
p2=find_word_start(++p1);
add_star:
if(isalnum(*p2
) || *p2
=='(' || *p2
=='[') {
if(*p2=='(' && *p1==')') ambiguous=1;
if(p2>p1) *p1='*';
else string_modify(p,p1,p1,"*");
}
p1--;continue;
}
p2=find_mathvar_end(p1); p3=find_word_start(p2);
if(myisdigit(*p1)) {
p1=p2; p2=p3; goto add_star;
}
else {
char buf[MAX_LINELEN+1];
int i;
if(p2-p2>30) goto ambig;
memcpy(buf
,p1
,p2
-p1
);buf
[p2
-p1
]=0;
i=search_evaltab(buf);
if(i>=0 && get_evaltype(i)>0) {
fnname1:
p1=p2;p2=p3;
/*fnname:*/
if(*p2 && *p2!='(' && *p2!='*' && *p2!='/') {
char hatbuf[MAX_LINELEN+1];
hatbuf[0]=')'; hatbuf[1]=0;
if(*p2=='^') {
p3=p2+1;while(*p3==' ' || *p3=='+' || *p3=='-') p3++;
if(*p3=='(') {
p3=find_matching(p3+1,')');
if(p3
==NULL
) {unmatch
=1; p3
=p
+strlen(p
);}
else p3++;
}
else p3=find_mathvar_end(p3);
memmove(hatbuf
+1,p2
,p3
-p2
);hatbuf
[p3
-p2
+1]=0;
ovlstrcpy(p2,p3);
while(*p2==' ') p2++;
if(*p2=='*' || *p2=='/') {
p1--;continue;
}
if(*p2=='(') {
p3=find_matching(p2+1,')');
if(p3
==NULL
) {unmatch
=1; p3
=p
+strlen(p
);}
else p3++;
string_modify(p,p3,p3,"%s",hatbuf+1);
goto dd2;
}
}
p3=p2;if(*p3=='+' || *p3=='-') p3++;
while(isalnum(*p3
) || *p3
=='*' || *p3
=='/' || *p3
=='.')
p3++;
for(p4
=p2
; p4
<p3
&& !isalnum(*p4
); p4
++);
if(p4>=p3) {
if(hatbuf[1]) string_modify(p,p2,p2,"%s",hatbuf+1);
}
else {
string_modify(p,p3,p3,"%s",hatbuf);
if(p1==p2) string_modify(p,p2,p2,"(");
else *p1='(';
}
dd2:
ambiguous=1;
}
p1--;continue;
}
i=search_list(mathname,mathname_no,sizeof(mathname[0]),buf);
if(i>=0) {
if(mathname[i].replace[0]!=0) {
string_modify(p,p1,p2,mathname[i].replace);
p2
=p1
+strlen(mathname
[i
].
replace);
p3=find_word_start(p2);
}
switch(mathname[i].style) {
case RM_FN:
goto fnname1;
case RM_VAR:
p1=p2;p2=p3; goto add_star;
case RM_PREFIX:
if(*p3!='c' && *p3!='s' && *p3!='t' &&
*p3!='C' && *p3!='S' && *p3!='T') break;
ambiguous=1;
ovlstrcpy(p2,p3); p1--; continue;
}
}
i=search_list(hmname,hmname_no,sizeof(hmname[0]),buf);
if(i>=0) {
p1=p2; p2=p3; goto add_star;
}
for(i
=0;i
<rm_uservars
&& strcmp(buf
,rm_uservar
[i
]);i
++);
if(i<rm_uservars) {
p1=p2;p2=p3;goto add_star;
}
for(i
=0;i
<rm_userfns
&& strcmp(buf
,rm_userfn
[i
]);i
++);
if(i<rm_userfns) goto fnname1;
if(p2-p1>8) goto ambig;
if(mathname_split(buf)!=NULL) {
ambiguous=1;
string_modify(p,p1,p2,"%s",buf);
p1--; continue;
}
/* unknown name */
ambig: p1=p2;p2=p3;
for(p3=buf;*p3!=0 && !myisdigit(*p3);p3++);
if(*p3!=0 && flatpower!=0) flatpower=1;
else {
unknown=1;
force_setvar("wims_warn_rawmath_parm",buf);
}
}
else {
if(*p2=='(') ambiguous=1;
}
if(p2>p1) *p1='*';
else string_modify(p,p1,p1,"*");
}
p1--;continue;
}
}
warnbuf[0]=0;
if(ambiguous
) strcat(warnbuf
," ambiguous");
if(unknown
) strcat(warnbuf
," unknown");
if(flatpower
>0) strcat(warnbuf
," flatpower");
if(badprec
>0) strcat(warnbuf
," badprec");
if(unmatch
>0) strcat(warnbuf
," unmatched_parentheses");
if(warnbuf[0]) {
char buf[MAX_LINELEN+1],*p;
p=getvar("wims_warn_rawmath");
if(p!=NULL && *p!=0) {
snprintf(buf
,sizeof(buf
),"%s %s",p
,warnbuf
);
force_setvar("wims_warn_rawmath",buf);
}
else force_setvar("wims_warn_rawmath",warnbuf);
}
}
/* replace < and > by html code if htmlmath_gtlt=yes
* is only used in deduc - not documented
*/
void __replace_htmlmath_gtlt (char *p)
{
char *pp;
char *p1=getvar("htmlmath_gtlt");
if(p1
!=NULL
&& strcmp(p1
,"yes")==0) {
string_modify(p,pp,pp+1,"<");
string_modify(p,pp,pp+1,">");
}
}
/* exponents or indices :
* all digits or + or - following a ^ or _ are considered as in exponent/subscript
* expression with ( ) following a ^ or _ are considered as in exponent/subscript
* the parenthesis are suppressed except in case of exponent and only digits.
* if int n != 0, use html code, else use tex code
*/
void __replace_exponent(char *p, int n)
{
char *p1;
char *SUPBEG, *SUPEND;
if (n) { SUPBEG = "<sup>"; SUPEND = "</sup>";}
else { SUPBEG = "^{"; SUPEND = "}";}
char *p2, *p3, *pp;
char c;
p3 = p2 = find_word_start(p1+1);
if(*p2=='+' || *p2=='-') p2++;
p2 = find_word_start(p2);
/* add '}' to recognized parenthesis in exponent
* !mathmlmath 2 \cdot x^{3} will now produce correct exponent...
* !mathmlmath should convert LaTeX input into correct MathML
*/
if(*p2=='(' || *p2 == '{') { /* ^[+-]( */
if(*p2 == '('){ p2 = find_matching(p2+1,')');}else { if(*p2 == '{'){ p2 = find_matching(p2+1,'}');}}
/* no matching ')' : p2 = end of line; otherwise just after ')' */
if (p2
==NULL
) p2
=p
+strlen(p
); else p2
++;
/* ^( followed by any number of digits/letters, up to p2
* [FIXME: no sign?] */
/* do we remove parentheses containing exponent group ? */
if (*p3=='(') for(pp=p3+1;pp<p2-1;pp++) {
/* not a digit/letter. Remove (). */
p3++;*(p2-1)=0;break;
}
/* x^(2), parentheses not removed */
}
/* p3: start of word after ^
* matching parentheses from exponent group. : f^(4) 4-derivative
* don't ignore / remove a leading + sign in exponent group : Cu^+
*/
}
else { /* ^[+-] */
char *ptt=p2;
p2=find_word_start(find_mathvar_end(p2));
/* ^[+-]var( */
char *p2t;
p2t=find_matching(p2+1,')'); if(p2t!=NULL) p2=p2t+1;
/* FIXME: what if no matching ) ? */
}
/* ^[+-]var(...): p2 points after closing ')'
* FIXME: I don't think this 'else' branch is sensible. One
* should NOT accept x^b(c+1) as meaning x^[b(c+1)]. I would
* remove it altogether.
*/
}
/* p1 points at ^ before exponent group
* p2 points at end of exponent group
* p3 = exponent group (sometimes stripped, without parentheses)
*
* truncate string p at p2 [ c = char deleted by truncation ]
*/
c = *p2;if(c!=0) *p2++=0;
/* replace ^<exponent group>. Add back missing character 'c' */
string_modify(p,p1,p2, "%s%s%s%c",SUPBEG,p3,SUPEND,c);
}
}
/* if int n != 0, use html code, else use tex code */
void __replace_subscript(char *p, int n)
{
char *p1, *p2;
char *SUBBEG, *SUBEND;
if (n) {SUBBEG = "<sub>"; SUBEND = "</sub>";}
else {SUBBEG = "_{"; SUBEND = "}";}
char buff[256];
p2=p1+1;
if(*p2=='(') p2=find_matching(p2+1,')');
else p2=find_mathvar_end(p2);
if(p2==NULL || p2>p1+64) continue;
if(*(p1+1)=='(') p2++;
memmove(buff
,p1
+1,p2
-p1
-1); buff
[p2
-p1
-1]=0;
strip_enclosing_par(buff);
string_modify(p,p1,p2,"%s%s%s",SUBBEG,buff,SUBEND);}
}
/* get rid of 1*.. ..*1 exemple : 1 * x, x/1 */
void __replace_getrid1 (char *p)
{
char *p1, *p2, *p3 ;
for(p1=p;*p1;p1++) {
if(*p1!='1') continue;
if(myisdigit(*(p1+1)) || *(p1+1)=='.' ||
(p1
>p
&& (isalnum(*(p1
-1)) || *(p1
-1)=='.')) ) continue;
p2=find_word_start(p1+1);
if(p1>p+2 && (*(p1-1)=='-' || *(p1-1)=='+')) {
for(p3
=p1
-2; p3
>p
&& isspace(*p3
); p3
--);
if(p3>p+1 && (*p3=='E' || *p3=='e')) { /* ??? */
p3
--; while(p3
>p
&& isspace(*p3
)) p3
--;
if(myisdigit(*p3) || *p3=='.') continue;
}
}
if(p1==p) p3="+";
else for(p3
=p1
-1;p3
>p
&& isspace(*p3
);p3
--);
if(*p2=='*' && *p3!='/') {/* delete 1 if 1* or /1 */
ovlstrcpy(p1,p2+1);continue;
}
ovlstrcpy(p1,p2);continue;
}
if(*p3=='/' && *p2!='<') ovlstrcpy(p3,p2);
}
}
/* get rid of '*' */
void __replace_getridstar (char *p)
{
char *p1 ;
char *pq;
pq=find_word_start(p1+1);
if(myisdigit(*pq)) {
string_modify(p,p1,pq,"×");
continue;
}
if(p1
>p
&& (isalpha(*(p1
-1)) || *(p1
-1)==')' || *(p1
-1)=='>')
&& (isalnum(*pq
) || *pq
=='$')) *p1
=' ';
else {
ovlstrcpy(p1,p1+1);p1--;
}
}
}
/* <=, >=, ->, =>, <=>, !=, <-> <-->, <-
* if int n != 0, use html code, else use tex code
*/
void __replace_arrow ( char *p, int n)
{
char *p1, *p2, *m_prefix;
if (n) m_prefix="$m_"; else m_prefix="\\";
for(p1
=strstr(p
,"<="); p1
!=NULL
; p1
=strstr(p1
+1,"<=")) {
if(*(p1+5)!='&' && *(p1+5)!='=')
string_modify(p,p1,p1+5, "%sle",m_prefix);
else {
for(p2=p1+5; *p2=='='; p2++);
if(p2>p1+5) { string_modify(p,p1,p2+4,"%sLongleftrightarrow",m_prefix);}
else { string_modify(p,p1,p2+4,"%sLeftrightarrow",m_prefix);}
}
else { string_modify(p,p1,p2,"%sLongleftarrow",m_prefix);}
}
}
for(p1
=strstr(p
,">="); p1
!=NULL
; p1
=strstr(p1
+1,">=")) {
if(*(p1+5)!='=') { string_modify(p,p1,p1+5,"%sge",m_prefix);}
}
for(p2=p1; p2>p && *(p2-1)=='-'; p2--);
if(p2>p && *(p2-1)==';') continue;
if(p2<p1) { string_modify(p,p2,p1+5,"%slongrightarrow",m_prefix);}
else { string_modify(p,p1,p1+5,"%srightarrow",m_prefix);}
}
for(p2=p1; p2>p && *(p2-1)=='='; p2--);
if(p2>p && *(p2-1)==';') continue;
if(p2<p1) { string_modify(p,p2,p1+5,"%sLongrightarrow",m_prefix);}
else { string_modify(p,p1,p1+5,"%sRightarrow",m_prefix) ;}
}
/* <->, <-->, <- */
/* <-- not implemented because -- is replaced by + elsewhere */
for(p1
=strstr(p
,"<-"); p1
!=NULL
; p1
=strstr(p1
+1,"<-")) {
for(p2=p1+5; *p2=='-'; p2++);
if ((p2-p1)%2)
string_modify(p,p1,p2+4,(p2>p1+5) ? "%slongleftrightarrow" : "%sleftrightarrow",m_prefix);
else
string_modify(p,p1,p2+4,(p2>p1+6) ? "%sleftrightharpoons" : "%sleftrightharpoons",m_prefix);
else
string_modify(p,p1,p2,(p2>p1+5) ? "%slongleftarrow " : "%sleftarrow ",m_prefix);
}
/* Not equal */
if(p1
>p
&& !isspace(*(p1
-1))) continue;
string_modify(p,p1,p1+2,"%sneq",m_prefix);
}
}
/* why <tt> is used sometimes ? replace single characters by italics one
* is it useful in mathml ?
*/
void __replace_italics (char *p, int n)
{
char *p1, *p2, *p3, pbuf[16];
char *ITBEG, *ITEND, *ITtBEG, *ITtEND;
if (n) {
ITBEG = "<i>";ITtBEG = "<i><tt>";
ITEND = "</i>";ITtEND = "</tt></i>";
} else {;
ITBEG = "" ; ITtBEG = "";
ITEND = ""; ITtEND = "";
}
for(p1=p;*p1;p1++) {
if(*p1=='<') {
if(p1==NULL) break; //recognize an html tag < >
else continue;
}
if(*p1=='=' && *(p1+1)=='-') {
string_modify(p,p1+1,p1+1," "); p1+=2; continue;
}
if(*p1=='\'') {
for(p2=p1+1;*p2=='\'';p2++);
memmove(pbuf
,p1
,p2
-p1
); pbuf
[p2
-p1
]=0;
string_modify(p,p1,p2,"%s%s%s",ITtBEG,pbuf,ITtEND);
continue;
}
/* unique letter.*/
p3=find_word_start(p2);
if(p2>p1+5 ||
(p2>p1+1 && (*p3==';' || *p3=='(' || myisdigit(*p2))))
{p1=p2-1; continue;}
if(strncasecmp
(p3
,"</i>",strlen("</i>"))==0) continue;
memmove(pbuf
,p1
,p2
-p1
); pbuf
[p2
-p1
]=0;
string_modify(p,p1,p2,"%s%s%s",ITBEG,pbuf,ITEND);
}
}
/* float (1.2 E-03) : 3E+021 -> 3 × 10^{21} - 3E-21 -> 3 × 10^{-21}
* or replace variable name (alpha)
* if int n != 0, use html code, else use tex code
*/
void __replace_mathvar(char *p,int n)
{
char *p1, *p2, *p3;
char *EXPBEG, *EXPEND, *EXPBEGMINUS, *SUBBEG, *SUBEND, *m_prefix;
if ( n ) {
EXPBEG = " × 10<sup>";
EXPBEGMINUS = " × 10<sup>-";
EXPEND = "</sup>";
SUBBEG = "<sub>";
SUBEND = "</sub>";
m_prefix="$m_";
} else {
EXPBEG = " \\times 10^{" ;
EXPBEGMINUS = " \\times 10^{-" ;
EXPEND = "}";
SUBBEG = "_{";
SUBEND = "}";
m_prefix="\\";
}
for (p1=find_mathvar_start(p);*p1!=0;p1=find_mathvar_start(p2)) {
char buf[MAX_LINELEN+1];
/* if the variable is preceded by \ do nothing
* in fact this should not arrive
*/
if (p1>p && *(p1-1) == '\\' ) break ;
p2 = find_mathvar_end(p1);
if (p1 == p2) break;
memmove(buf
,p1
,p2
-p1
);buf
[p2
-p1
]=0;
if(myisdigit(buf[0])) {
/* number : 3E+021 -> 3 x 10^{21} - 3E-21 -> 3 x 10^{-21} */
int k = 1, minus = 0;
/* see putnumber in texmath.c*/
if( (p3
= strpbrk(buf
, "Ee")) == NULL
) continue;
p1 += p3-buf;
//count the number of 0, +, -
if (*(p1+k) == '-') { minus = 1; k++; }
while(*(p1+k)=='0' || *(p1+k)=='+') k++;
string_modify(p,p1,p1+k, minus? EXPBEGMINUS: EXPBEG);
p2
+= strlen(minus
? EXPBEGMINUS
: EXPBEG
)-k
;
string_modify(p,p2,p2, EXPEND);
}
else {
/* alphabetic name, replace greek letters and symbols in hmname
* not done in texmath.c
*/
int i = search_list(hmname,hmname_no,sizeof(hmname[0]),buf);
char *n, *r;
if(i<0) { /* not in list */
if(myisdigit(buf[k])) {
while(k>0 && myisdigit(buf[k-1])) k--;
string_modify(buf,buf+k,buf+k,SUBBEG);
string_modify(p,p1,p2,"%s%s",buf,SUBEND);
}
continue;
}
n = hmname[i].name;
r = mathalign_base < 2? hmname[i].replace: hmname[i].replacem;
if(r[0]==0) { /* replace = "" */
string_modify(p,p1,p2,"%s%s",m_prefix, n);
} else {
string_modify(p,p1,p2,"%s",r);
}
}
}
}
/* translate raw math expression coming from calculators into best html way
* if int n != 0, use html code, else use tex code
*/
void __htmlmath(char *p,int n)
{
if(!rawmath_easy) { rawmath_easy=1; rawmath(p); rawmath_easy=0;}
__replace_htmlmath_gtlt(p); //only used in deductio
__replace_exponent(p,n);
__replace_subscript(p,n);
__replace_getrid1(p);
__replace_mathvar(p,n);
__replace_getridstar(p);
__replace_arrow(p,n);
/* Now make substitutions */
substit(p);
/* Make single names italic - done automatically by mathml */
__replace_italics(p,n);
strip_trailing_spaces(p);
}
void htmlmath(char *p)
{
__htmlmath(p,1) ;
}
/* if mathml is closed, it will be just htmlmath*/
void mathmlmath(char *p)
{
/*
if force_mathml variable is set to "yes", do not (never) use 'htmlmath'
in output, so command: !mathmlmath some_LaTeX_string will produce mathml
(mathml \input inputfields may be included)
*/
if( strcmp( getvar
("force_mathml"),"yes") == 0 ){ mathalign_base
= 2;mathml
(p
,1);return; }
if (mathalign_base == 2) { __htmlmath(p,0) ; mathml(p,1);} else { __htmlmath(p,1) ;}
}