Subversion Repositories wimsdev

Rev

Rev 7415 | 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
 
18
/* internal variable */
19
int rawmath_easy=0;
20
 
21
#include "hmname.c"
22
enum {RM_UNKNOWN, RM_FN, RM_VAR, RM_PREFIX};
23
 
24
struct {
25
    char *name;
26
    int style;
27
    char *replace;
28
} mathname[]={
5503 bpr 29
      {"Arc",     RM_PREFIX, "arc"},
30
      {"Arg",     RM_PREFIX, "arg"},
31
      {"Ci",      RM_FN,        ""},
32
      {"E",       RM_VAR,       ""},
33
      {"Euler",   RM_VAR,       ""},
34
      {"I",       RM_VAR,       ""},
35
      {"Int",     RM_FN,        ""},
36
      {"PI",      RM_VAR,       ""},
37
      {"Pi",      RM_VAR,       ""},
38
      {"Prod",    RM_FN,        ""},
39
      {"Si",      RM_FN,        ""},
40
      {"Sum",     RM_FN,        ""},
41
      {"arc",     RM_PREFIX,    ""},
42
      {"arg",     RM_PREFIX,    ""},
43
      {"binomial",RM_FN,        ""},
44
      {"diff",    RM_FN,        ""},
45
      {"e",       RM_VAR,       ""},
46
      {"erf",     RM_FN,        ""},
47
      {"euler",   RM_VAR,       ""},
48
      {"i",       RM_VAR,       ""},
49
      {"infinity",RM_VAR,       ""},
50
      {"int",     RM_FN,        ""},
51
      {"integrate",RM_FN,       ""},
52
      {"neq",     RM_VAR,       ""},
53
      {"pi",      RM_VAR,       ""},
54
      {"prod",    RM_FN,        ""},
55
      {"product", RM_FN,        ""},
56
      {"psi",     RM_FN,        ""},
57
      {"sum",     RM_FN,        ""},
58
      {"theta",   RM_FN,        ""},
59
      {"x",       RM_VAR,       ""},
60
      {"y",       RM_VAR,       ""},
61
      {"z",       RM_VAR,       ""},
62
      {"zeta",    RM_FN,        ""},
10 reyssat 63
};
64
#define mathname_no (sizeof(mathname)/sizeof(mathname[0]))
65
char rm_vbuf[MAX_LINELEN+1],rm_fbuf[MAX_LINELEN+1];
66
char *rm_uservar[MAX_LINELEN+1],*rm_userfn[MAX_LINELEN+1];
67
int  rm_uservars,rm_userfns;
68
 
5503 bpr 69
/* add user-defined variables and function names,
70
 * internal, only called by rawmath(). */
10 reyssat 71
void getuservar(void)
72
{
73
    char *p1, *p2, *p;
74
    rm_uservars=rm_userfns=0;
75
    p=getvar("wims_rawmath_variables");
76
    if(p!=NULL && *p!=0) {
5503 bpr 77
       ovlstrcpy(rm_vbuf,p);
78
       for(p=rm_vbuf;*p;p++) if(*p==',') *p=' ';
79
       for(p1=find_word_start(rm_vbuf);*p1;p1=find_word_start(p2)) {
80
          rm_uservar[rm_uservars++]=p1;
81
          p2=find_word_end(p1);
82
          if(*p2!=0) *(p2++)=0;
83
       }
10 reyssat 84
    }
85
    p=getvar("wims_rawmath_functions");
86
    if(p!=NULL && *p!=0) {
5503 bpr 87
      ovlstrcpy(rm_fbuf,p);
88
      for(p=rm_fbuf;*p;p++) if(*p==',') *p=' ';
89
      for(p1=find_word_start(rm_fbuf);*p1;p1=find_word_start(p2)) {
90
        rm_userfn[rm_userfns++]=p1;
91
        p2=find_word_end(p1);
92
        if(*p2!=0) *(p2++)=0;
93
      }
10 reyssat 94
    }
95
}
96
 
5503 bpr 97
/* Try to split a word into recognizable variables */
10 reyssat 98
char *mathname_split(char *p)
99
{
100
    int c,i,j,type;
101
 
102
    c=0;
103
    beg: for(i=get_evalcnt()-1;
5503 bpr 104
    i>=0 && strncmp(p,get_evalname(i),strlen(get_evalname(i)))!=0;
105
    i--);
10 reyssat 106
    if(i>=0 && get_evaltype(i)>0) {
5503 bpr 107
      type=RM_FN;
108
      j=strlen(get_evalname(i));
109
      gotit:
110
      if(!*(p+j)) return p;
111
      if(myisdigit(*(p+j)) && type!=RM_FN) return NULL;
112
      if(!c) {string_modify(p,p+j,p+j," "); p+=j+1;}
113
      else p+=j;
114
      c++; goto beg;
10 reyssat 115
    }
116
    for(i=mathname_no-1;
7673 bpr 117
      i>=0 &&
5503 bpr 118
      (strncmp(p,mathname[i].name,strlen(mathname[i].name))!=0
119
      || mathname[i].style==RM_PREFIX);
120
      i--);
10 reyssat 121
    if(i>=0) {
5503 bpr 122
      type=mathname[i].style;
123
      j=strlen(mathname[i].name);
124
      goto gotit;
10 reyssat 125
    }
7673 bpr 126
    for(i=0;i<rm_uservars &&
5503 bpr 127
      strncmp(rm_uservar[i],p,strlen(rm_uservar[i]));i++);
10 reyssat 128
    if(i<rm_uservars) {
5503 bpr 129
      type=RM_VAR;
130
      j=strlen(rm_uservar[i]); goto gotit;
10 reyssat 131
    }
7673 bpr 132
    for(i=0;i<rm_userfns &&
5503 bpr 133
      strncmp(p,rm_userfn[i],strlen(rm_userfn[i]));i++);
10 reyssat 134
    if(i<rm_userfns) {
5503 bpr 135
      type=RM_FN;
136
      j=strlen(rm_userfn[i]); goto gotit;
10 reyssat 137
    }
7673 bpr 138
    return NULL;
10 reyssat 139
}
140
 
5465 bpr 141
int __replace_badchar (char *p, char *old, char *new)
142
{ int cnt = 0;
143
  char *p1 ;
144
  while((p1=strstr(p,old))!=NULL) {
5503 bpr 145
    string_modify(p,p1,p1+strlen(old),"%s",new);
7673 bpr 146
    cnt++;
5465 bpr 147
  }
148
  return cnt ;
149
}
10 reyssat 150
 
5517 bpr 151
/* translate |x| into abs(x)*/
5465 bpr 152
int __replace_abs ( char *p )
7673 bpr 153
{
5465 bpr 154
    char *p1, *p2 ;
10 reyssat 155
    while((p1=strchr(p,'|'))!=NULL) {
5503 bpr 156
      p2=find_matching(p1+1,'|');
157
      if(p2==NULL) { return 1; break;} /* error; drop it. */
158
      *p2=')'; string_modify(p,p1,p1+1,"abs(");
10 reyssat 159
    }
5465 bpr 160
    return 0;
161
}
162
 
163
/* signs: translate ++, +-, -+, ... into one sign. */
5491 kbelabas 164
void __replace_plusminus ( char *p )
7673 bpr 165
{
5465 bpr 166
   char *p1, *p2;
167
   for(p1=p;*p1!=0;p1++) {
5503 bpr 168
     int sign, redundant;
169
     if(*p1!='+' && *p1!='-') continue;
170
     if(*p1=='+') sign=1; else sign=-1;
171
     redundant=0;
172
     for(p2=find_word_start(p1+1);*p2=='+' || *p2=='-';
173
        p2=find_word_start(p2+1)) {
174
         if(*p2=='-') sign*=-1;
175
         redundant=1;
176
     }
177
     if(redundant && *p2!='>' && strncmp(p2,"&gt;",4)!=0) {
178
        if(sign==1) *p1='+'; else *p1='-';
179
        ovlstrcpy(p1+1,p2);
180
     }
5465 bpr 181
   }
182
}
183
 
184
/* dangling decimal points
185
4. --> 4.0  4.x -> 4.0x
186
.5 -> 0.5
187
another treatment is done in insmath (will replace .. by , )
188
*/
189
void __treat_decimal(char *p)
190
{ char *p1 ;
191
  for(p1=strchr(p,'.'); p1!=NULL; p1=strchr(p1+1,'.')) {
5503 bpr 192
        /* multiple .. is conserved */
193
    if(*(p1+1)=='.') {
194
        do p1++; while(*p1=='.'); continue;
10 reyssat 195
    }
5503 bpr 196
    if(p1>p && myisdigit(*(p1-1)) && myisdigit(*(p1+1))) continue;
197
        /* Non-digit dangling '.' is removed */
198
    if((p1<=p || !myisdigit(*(p1-1))) && !myisdigit(*(p1+1))) {
199
        ovlstrcpy(p1,p1+1); p1--; continue;
200
    }
201
    if(p1==p || !myisdigit(*(p1-1))) { // nondigit.digit
202
        string_modify(p,p1,p1,"0"); p1++; //add zero before point
203
    }
204
    if(!myisdigit(*(p1+1))) string_modify(p,p1+1,p1+1,"0"); //add zero after point
205
  }
5465 bpr 206
}
207
 
5517 bpr 208
/* replace new-lines, tabs, " */
5465 bpr 209
void __replace_space(char *p)
7673 bpr 210
{
5465 bpr 211
 char *p1 ;
5503 bpr 212
 for(p1=p;*p1!=0; p1++) {
5517 bpr 213
    if(*p1=='\\' || isspace(*p1)) *p1=' ';// replace \ and all spaces by a simple space -
214
    if(*p1=='\"') string_modify(p,p1,p1+1,"''"); p1++; // replace " by ''
5465 bpr 215
  }
216
}
217
 
7673 bpr 218
    /* Error-tolerante raw math translation routine
5517 bpr 219
     * Translate error-laden raw math into machine-understandable form.
7673 bpr 220
     * do nothing if there is some { or \\
221
     */
5465 bpr 222
void rawmath(char *p)
223
{
224
    char *p1, *p2, *p3, *p4;
225
    char warnbuf[1024];
226
    int ambiguous=0,unknown=0,flatpower=0,badprec=0,unmatch=0;// for warning
227
 
5517 bpr 228
    /* looks like a TeX source : do nothing */
229
    if( (strchr(p,'\\')!=NULL || strchr(p,'{')!=NULL)) return;
5465 bpr 230
    if(strchr(p,'^')==NULL) flatpower=-1;
231
    if(strlen(p)>=MAX_LINELEN) {*p=0; return;}
232
    p1=find_word_start(p);if(*p1==0) return;
233
    while(*p1=='+') p1++;
234
    if(p1>p) ovlstrcpy(p,p1);
5491 kbelabas 235
    (void)__replace_badchar(p,"**", "^");
236
    if (__replace_badchar(p,"²", "^2 ")) flatpower=1;
237
    if (__replace_badchar(p,"³", "^3 ")) flatpower=1;
5517 bpr 238
    unmatch=__replace_abs(p);
7673 bpr 239
    __replace_plusminus(p) ;
5465 bpr 240
    __replace_space(p);
241
    __treat_decimal(p);
5491 kbelabas 242
    if (rawmath_easy) return;
5465 bpr 243
 
5503 bpr 244
        /* Principal translation: justapositions to multiplications */
10 reyssat 245
    if(strstr(p,"^1/")!=NULL) badprec=1;
246
    getuservar();
247
    for(p1=p;*p1;p1++) {
5503 bpr 248
      if(!isalnum(*p1) && *p1!=')' && *p1!=']') continue;
249
      if(*p1==')' || *p1==']') {
250
        p2=find_word_start(++p1);
251
        add_star:
252
        if(isalnum(*p2) || *p2=='(' || *p2=='[') {
253
        if(*p2=='(' && *p1==')') ambiguous=1;
254
        if(p2>p1) *p1='*';
255
        else string_modify(p,p1,p1,"*");
256
        }
257
        p1--;continue;
10 reyssat 258
    }
5503 bpr 259
    p2=find_mathvar_end(p1); p3=find_word_start(p2);
260
    if(myisdigit(*p1)) {
261
        p1=p2; p2=p3; goto add_star;
262
    }
263
    else {
264
        char buf[MAX_LINELEN+1];
265
        int i;
266
        if(p2-p2>30) goto ambig;
267
        memcpy(buf,p1,p2-p1);buf[p2-p1]=0;
268
        i=search_evaltab(buf);
269
        if(i>=0 && get_evaltype(i)>0) {
270
          fnname1:
271
          p1=p2;p2=p3;
272
        /*fnname:*/
273
          if(*p2 && *p2!='(' && *p2!='*' && *p2!='/') {
274
            char hatbuf[MAX_LINELEN+1];
275
            hatbuf[0]=')'; hatbuf[1]=0;
276
            if(*p2=='^') {
277
              p3=p2+1;while(*p3==' ' || *p3=='+' || *p3=='-') p3++;
278
              if(*p3=='(') {
279
                p3=find_matching(p3+1,')');
280
                if(p3==NULL) {unmatch=1; p3=p+strlen(p);}
281
                else p3++;
282
              }
283
              else p3=find_mathvar_end(p3);
284
              memmove(hatbuf+1,p2,p3-p2);hatbuf[p3-p2+1]=0;
285
              ovlstrcpy(p2,p3);
286
              while(*p2==' ') p2++;
287
              if(*p2=='*' || *p2=='/') {
288
                p1--;continue;
289
              }
290
              if(*p2=='(') {
291
                p3=find_matching(p2+1,')');
292
                if(p3==NULL) {unmatch=1; p3=p+strlen(p);}
293
                else p3++;
294
                string_modify(p,p3,p3,"%s",hatbuf+1);
295
                goto dd2;
296
              }
297
            }
298
            p3=p2;if(*p3=='+' || *p3=='-') p3++;
299
            while(isalnum(*p3) || *p3=='*' || *p3=='/' || *p3=='.')
300
              p3++;
301
            for(p4=p2; p4<p3 && !isalnum(*p4); p4++);
302
            if(p4>=p3) {
303
              if(hatbuf[1]) string_modify(p,p2,p2,"%s",hatbuf+1);
304
            }
305
            else {
306
              string_modify(p,p3,p3,"%s",hatbuf);
307
              if(p1==p2) string_modify(p,p2,p2,"(");
308
              else *p1='(';
309
            }
310
            dd2:
311
            ambiguous=1;
312
          }
313
          p1--;continue;
314
        }
315
        i=search_list(mathname,mathname_no,sizeof(mathname[0]),buf);
316
        if(i>=0) {
317
          if(mathname[i].replace[0]!=0) {
318
            string_modify(p,p1,p2,mathname[i].replace);
319
            p2=p1+strlen(mathname[i].replace);
320
            p3=find_word_start(p2);
321
          }
322
          switch(mathname[i].style) {
323
            case RM_FN:
324
              goto fnname1;
7673 bpr 325
 
5503 bpr 326
            case RM_VAR:
327
              p1=p2;p2=p3; goto add_star;
7673 bpr 328
 
5503 bpr 329
            case RM_PREFIX:
7673 bpr 330
              if(*p3!='c' && *p3!='s' && *p3!='t' &&
5503 bpr 331
             *p3!='C' && *p3!='S' && *p3!='T') break;
332
              ambiguous=1;
333
              ovlstrcpy(p2,p3); p1--; continue;
334
          }
335
        }
336
        i=search_list(hmname,hmname_no,sizeof(hmname[0]),buf);
337
        if(i>=0) {
338
          p1=p2; p2=p3; goto add_star;
339
        }
340
        for(i=0;i<rm_uservars && strcmp(buf,rm_uservar[i]);i++);
341
        if(i<rm_uservars) {
342
          p1=p2;p2=p3;goto add_star;
343
        }
344
        for(i=0;i<rm_userfns && strcmp(buf,rm_userfn[i]);i++);
345
        if(i<rm_userfns) goto fnname1;
346
        if(p2-p1>8) goto ambig;
347
        if(mathname_split(buf)!=NULL) {
348
          ambiguous=1;
349
          string_modify(p,p1,p2,"%s",buf);
350
          p1--; continue;
351
        }
352
         /* unknown name */
353
        ambig: p1=p2;p2=p3;
354
        if(strlen(buf)>1) {
355
          for(p3=buf;*p3!=0 && !myisdigit(*p3);p3++);
7673 bpr 356
          if(*p3!=0 && flatpower!=0) flatpower=1;
5503 bpr 357
          else {
358
            unknown=1;
359
            force_setvar("wims_warn_rawmath_parm",buf);
360
          }
361
        }
362
        else {
363
          if(*p2=='(') ambiguous=1;
364
        }
365
        if(isalnum(*p2)) {
366
          if(p2>p1) *p1='*';
367
          else string_modify(p,p1,p1,"*");
368
        }
369
        p1--;continue;
370
      }
371
    }
10 reyssat 372
    warnbuf[0]=0;
373
    if(ambiguous) strcat(warnbuf," ambiguous");
374
    if(unknown) strcat(warnbuf," unknown");
375
    if(flatpower>0) strcat(warnbuf," flatpower");
376
    if(badprec>0) strcat(warnbuf," badprec");
377
    if(unmatch>0) strcat(warnbuf," unmatched_parentheses");
378
    if(warnbuf[0]) {
5503 bpr 379
    char buf[MAX_LINELEN+1],*p;
380
    p=getvar("wims_warn_rawmath");
381
    if(p!=NULL && *p!=0) {
382
        snprintf(buf,sizeof(buf),"%s %s",p,warnbuf);
383
        force_setvar("wims_warn_rawmath",buf);
10 reyssat 384
    }
5503 bpr 385
    else force_setvar("wims_warn_rawmath",warnbuf);
386
    }
10 reyssat 387
}
388
 
5517 bpr 389
 /*  replace < and > by html code if htmlmath_gtlt=yes - is only used in deduc - not documented*/
7673 bpr 390
void __replace_htmlmath_gtlt (char *p)
5465 bpr 391
{   char *pp;
7673 bpr 392
    char *p1=getvar("htmlmath_gtlt");
5503 bpr 393
    if(p1!=NULL && strcmp(p1,"yes")==0) {
394
      for(pp=strchr(p,'<'); pp!=NULL; pp=strchr(pp+1,'<'))
395
      string_modify(p,pp,pp+1,"&lt;");
396
      for(pp=strchr(p,'>'); pp!=NULL; pp=strchr(pp+1,'>'))
397
      string_modify(p,pp,pp+1,"&gt;");
5465 bpr 398
   }
399
}
400
 
7673 bpr 401
/* exponents or indices :
5551 bpr 402
 *  all digits or + or - following a ^ or _ are considered as in exponent/subscript
403
 *  expression with ( ) following a ^ or _ are  considered as in exponent/subscript
404
 *  the parenthesis are suppressed except in case of exponent and only digits.
405
 *  if int n != 0, use html code, else use tex code */
406
void __replace_exponent(char *p, int n)
5465 bpr 407
{
5503 bpr 408
   char *p1;
409
   char *SUPBEG, *SUPEND;
7673 bpr 410
   if (n) { SUPBEG = "<sup>"; SUPEND = "</sup>";}
5503 bpr 411
   else { SUPBEG = "^{"; SUPEND = "}";}
5465 bpr 412
 
10 reyssat 413
    for(p1=strchr(p,'^');p1!=NULL;p1=strchr(p1+1,'^')) {
5465 bpr 414
        char *p2, *p3, *pp;
415
        char c;
416
        p3 = p2 = find_word_start(p1+1);
417
        if(*p2=='+' || *p2=='-') p2++;
418
        p2 = find_word_start(p2);
7673 bpr 419
/* jm.evers 31.1.2014
420
 * add '}' to recognized parenthesis in exponent
421
 * !mathmlmath 2 \cdot x^{3} will now produce correct exponent...
422
 * !mathmlmath should convert LaTeX input into correct MathML
423
 */
7415 schaersvoo 424
        if(*p2=='(' || *p2 == '{') { /* ^[+-]( */
7673 bpr 425
             if(*p2 == '('){ p2 = find_matching(p2+1,')');}else { if(*p2 == '{'){ p2 = find_matching(p2+1,'}');}}
5465 bpr 426
            /* no matching ')' : p2 = end of line; otherwise just after ')' */
427
            if (p2==NULL) p2=p+strlen(p); else p2++;
428
            /* ^( followed by any number of digits/letters, up to p2
429
             * [FIXME: no sign?] */
430
            /* do we remove parentheses containing exponent group ? */
431
            if (*p3=='(') for(pp=p3+1;pp<p2-1;pp++) {
432
                if(!isalnum(*pp)) {
7673 bpr 433
                    /* not a digit/letter. Remove (). */
5465 bpr 434
                    p3++;*(p2-1)=0;break;
435
                }
5517 bpr 436
                /* x^(2), parentheses not removed */
5465 bpr 437
            }
438
            /* p3: start of word after ^ */
5517 bpr 439
            /* matching parentheses from exponent group. : f^(4) 4-derivative */
440
            /* don't  ignore / remove a leading + sign in exponent group : Cu^+ */
5465 bpr 441
        } else { /* ^[+-] */
442
            char *ptt=p2;
443
            p2=find_word_start(find_mathvar_end(p2));
444
            if(*p2=='(' && isalpha(*ptt)) {
445
                /* ^[+-]var( */
446
                char *p2t;
447
                p2t=find_matching(p2+1,')'); if(p2t!=NULL) p2=p2t+1;
448
                /* FIXME: what if no matching ) ? */
449
            }
450
            /* ^[+-]var(...): p2 points after closing ')' */
451
            /* FIXME: I don't think this 'else' branch is sensible. One
452
             * should NOT accept x^b(c+1) as meaning x^[b(c+1)]. I would
5517 bpr 453
             * remove it altogether. */
5465 bpr 454
        }
455
        /* p1 points at ^ before exponent group */
456
        /* p2 points at end of exponent group */
457
        /* p3 = exponent group (sometimes stripped, without parentheses) */
458
 
459
        /* truncate string p at p2 [ c = char deleted by truncation ] */
460
        c = *p2;if(c!=0) *p2++=0;
461
        /* replace ^<exponent group>. Add back missing character 'c' */
5503 bpr 462
        string_modify(p,p1,p2, "%s%s%s%c",SUPBEG,p3,SUPEND,c);
10 reyssat 463
    }
5465 bpr 464
}
465
 
5551 bpr 466
/* if int n != 0, use html code, else use tex code */
467
void __replace_subscript(char *p, int n)
5465 bpr 468
{
469
   char *p1, *p2;
5503 bpr 470
   char *SUBBEG, *SUBEND;
7673 bpr 471
   if (n) {SUBBEG = "<sub>"; SUBEND = "</sub>";}
5503 bpr 472
   else {SUBBEG = "_{"; SUBEND = "}";}
5465 bpr 473
   for(p1=strchr(p,'_');p1!=NULL;p1=strchr(p1+1,'_')) {
5503 bpr 474
     char buff[256];
475
     p2=p1+1;
476
     if(*p2=='(') p2=find_matching(p2+1,')');
477
     else p2=find_mathvar_end(p2);
478
     if(p2==NULL || p2>p1+64) continue;
479
     if(*(p1+1)=='(') p2++;
480
     memmove(buff,p1+1,p2-p1-1); buff[p2-p1-1]=0;
481
     strip_enclosing_par(buff);
482
     string_modify(p,p1,p2,"%s%s%s",SUBBEG,buff,SUBEND);}
5465 bpr 483
}
484
 
5517 bpr 485
/* get rid of 1*.. ..*1  exemple : 1 * x, x/1 */
5465 bpr 486
void __replace_getrid1 (char *p)
7673 bpr 487
{   char *p1, *p2, *p3 ;
10 reyssat 488
    for(p1=p;*p1;p1++) {
5503 bpr 489
      if(*p1!='1') continue;
490
      if(myisdigit(*(p1+1)) || *(p1+1)=='.' ||
491
       (p1>p && (isalnum(*(p1-1)) || *(p1-1)=='.')) ) continue;
492
      p2=find_word_start(p1+1);
493
      if(p1>p+2 && (*(p1-1)=='-' || *(p1-1)=='+')) {
494
        for(p3=p1-2; p3>p && isspace(*p3); p3--);
7673 bpr 495
        if(p3>p+1 && (*p3=='E' || *p3=='e')) { /* ??? */
5503 bpr 496
        p3--; while(p3>p && isspace(*p3)) p3--;
497
        if(myisdigit(*p3) || *p3=='.') continue;
498
        }
499
      }
7673 bpr 500
      if(p1==p) p3="+";
5503 bpr 501
      else for(p3=p1-1;p3>p && isspace(*p3);p3--);
502
      if(*p2=='*' && *p3!='/') {/* delete 1 if 1* or /1 */
503
        ovlstrcpy(p1,p2+1);continue;
504
      }
505
      if(isalpha(*p2) && *p3!='/') {
506
        ovlstrcpy(p1,p2);continue;
507
      }
508
      if(*p3=='/' && *p2!='<') ovlstrcpy(p3,p2);
10 reyssat 509
 
510
    }
5465 bpr 511
}
512
 
513
/* get rid of '*' */
514
void __replace_getridstar (char *p)
515
{ char *p1 ;
516
 for(p1=strchr(p,'*');p1!=NULL;p1=strchr(p1+1,'*')) {
5503 bpr 517
    char *pq;
518
    pq=find_word_start(p1+1);
519
    if(myisdigit(*pq)) {
520
        string_modify(p,p1,pq,"&times;");
521
        continue;
10 reyssat 522
    }
5503 bpr 523
    if(p1>p && (isalpha(*(p1-1)) || *(p1-1)==')' || *(p1-1)=='>')
524
       && (isalnum(*pq) || *pq=='$')) *p1=' ';
525
    else {
526
        ovlstrcpy(p1,p1+1);p1--;
527
    }
528
  }
5465 bpr 529
}
530
 
7673 bpr 531
/* <=, >=, ->, =>, <=>
5551 bpr 532
 * if int n != 0, use html code, else use tex code */
533
 
534
void __replace_arrow ( char *p, int n)
5503 bpr 535
{   char *p1, *p2, *m_prefix;
5551 bpr 536
    if (n) m_prefix="$m_"; else m_prefix="\\";
7673 bpr 537
 
10 reyssat 538
    for(p1=strstr(p,"&lt;="); p1!=NULL; p1=strstr(p1+1,"&lt;=")) {
7673 bpr 539
      if(*(p1+5)!='&' && *(p1+5)!='=')
5503 bpr 540
        string_modify(p,p1,p1+5, "%sle",m_prefix);
541
      else {
542
          for(p2=p1+5; *p2=='='; p2++);
543
          if(strncmp(p2,"&gt;",4)==0) {
7673 bpr 544
            if(p2>p1+5) { string_modify(p,p1,p2+4,"%sLongleftrightarrow",m_prefix);}
545
            else { string_modify(p,p1,p2+4,"%sLeftrightarrow",m_prefix);}
5503 bpr 546
          }
547
          else { string_modify(p,p1,p2,"%sLongleftarrow",m_prefix);}
548
      }
10 reyssat 549
    }
550
    for(p1=strstr(p,"&gt;="); p1!=NULL; p1=strstr(p1+1,"&gt;=")) {
5503 bpr 551
      if(*(p1+5)!='=') { string_modify(p,p1,p1+5,"%sge",m_prefix);}
10 reyssat 552
    }
553
    for(p1=strstr(p,"-&gt;"); p1; p1=strstr(p1+1,"-&gt;")) {
5503 bpr 554
      for(p2=p1; p2>p && *(p2-1)=='-'; p2--);
555
      if(p2>p && *(p2-1)==';') continue;
556
      if(p2<p1) { string_modify(p,p2,p1+5,"%slongrightarrow",m_prefix);}
557
      else {  string_modify(p,p1,p1+5,"%srightarrow",m_prefix);}
10 reyssat 558
    }
559
    for(p1=strstr(p,"=&gt;"); p1; p1=strstr(p1+1,"=&gt;")) {
5503 bpr 560
      for(p2=p1; p2>p && *(p2-1)=='='; p2--);
561
      if(p2>p && *(p2-1)==';') continue;
562
      if(p2<p1) { string_modify(p,p2,p1+5,"%sLongrightarrow",m_prefix);}
563
      else { string_modify(p,p1,p1+5,"%sRightarrow",m_prefix) ;}
10 reyssat 564
    }
5503 bpr 565
/* Not equal */
10 reyssat 566
    for(p1=strstr(p,"!="); p1; p1=strstr(p1+1,"!=")) {
5503 bpr 567
      if(p1>p && !isspace(*(p1-1))) continue;
568
       string_modify(p,p1,p1+2,"%sneq",m_prefix);
10 reyssat 569
    }
5465 bpr 570
}
571
 
5503 bpr 572
/* why <tt> is used sometimes ? replace single characters by italics one
573
 * is it useful in mathml ?
574
*/
5551 bpr 575
void __replace_italics (char *p, int n)
5465 bpr 576
{ char *p1, *p2, *p3, pbuf[16];
5503 bpr 577
  char *ITBEG, *ITEND, *ITtBEG, *ITtEND;
5551 bpr 578
   if (n) {
5503 bpr 579
     ITBEG = "<i>";ITtBEG = "<i><tt>";
580
     ITEND = "</i>";ITtEND = "</tt></i>";
581
  } else {;
582
     ITBEG = "" ; ITtBEG = "";
583
     ITEND = ""; ITtEND = "";
584
  }
7673 bpr 585
 
5503 bpr 586
  for(p1=p;*p1;p1++) {
587
    if(*p1=='<') {
588
        p1=strchr(p1,'>'); if(p1==NULL) break; //recognize an html tag < >
589
        else continue;
10 reyssat 590
    }
5503 bpr 591
    if(*p1=='=' && *(p1+1)=='-') {
592
        string_modify(p,p1+1,p1+1," "); p1+=2; continue;
593
    }
594
    if(*p1=='\'') {
595
        for(p2=p1+1;*p2=='\'';p2++);
596
        memmove(pbuf,p1,p2-p1); pbuf[p2-p1]=0;
597
        string_modify(p,p1,p2,"%s%s%s",ITtBEG,pbuf,ITtEND);
598
        p1=p2+strlen(ITtBEG)+strlen(ITtEND)-1;
599
        continue;
600
    }
601
    if(!isalpha(*p1)) continue;
602
/* unique letter.*/
603
    for(p2=p1+1;isalpha(*p2);p2++);
604
    p3=find_word_start(p2);
605
    if(p2>p1+5 ||
606
       (p2>p1+1 && (*p3==';' || *p3=='(' || myisdigit(*p2))))
607
        {p1=p2-1; continue;}
608
    if(strncasecmp(p3,"</i>",strlen("</i>"))==0) continue;
609
    memmove(pbuf,p1,p2-p1); pbuf[p2-p1]=0;
610
    string_modify(p,p1,p2,"%s%s%s",ITBEG,pbuf,ITEND);
611
    p1=p2+strlen(ITBEG)+strlen(ITEND)-1;
612
    }
10 reyssat 613
}
5466 bpr 614
 
5551 bpr 615
/* float (1.2 E-03) : 3E+021 -> 3 × 10^{21} - 3E-21 -> 3 × 10^{-21}
616
 * or replace variable name (alpha)
617
 * if int n != 0, use html code, else use tex code */
618
void __replace_mathvar(char *p,int n)
5466 bpr 619
{ char *p1, *p2, *p3;
5503 bpr 620
  char *EXPBEG, *EXPEND, *EXPBEGMINUS, *SUBBEG, *SUBEND, *m_prefix;
7673 bpr 621
 
5551 bpr 622
  if ( n ) {
5503 bpr 623
     EXPBEG = " &times; 10<sup>";
624
     EXPBEGMINUS = " &times; 10<sup>-";
625
     EXPEND = "</sup>";
626
     SUBBEG = "<sub>";
627
     SUBEND = "</sub>";
628
     m_prefix="$m_";
629
  } else {
630
     EXPBEG = " \\times 10^{" ;
631
     EXPBEGMINUS = " \\times 10^{-" ;
632
     EXPEND = "}";
633
     SUBBEG = "_{";
634
     SUBEND = "}";
635
     m_prefix="\\";
5466 bpr 636
  }
5503 bpr 637
  for (p1=find_mathvar_start(p);*p1!=0;p1=find_mathvar_start(p2)) {
638
    char buf[MAX_LINELEN+1];
5523 bpr 639
    /* if the variable is preceded by \ do nothing - in fact this should not arrive
7673 bpr 640
    */
641
    if (p1>p && *(p1-1) == '\\' ) break ;
5503 bpr 642
    p2 = find_mathvar_end(p1);
643
        if (p1 == p2) break;
644
    memmove(buf,p1,p2-p1);buf[p2-p1]=0;
5466 bpr 645
 
5503 bpr 646
    if(myisdigit(buf[0])) {
647
            /* number : 3E+021 -> 3 x 10^{21} - 3E-21 -> 3 x 10^{-21} */
648
        int k = 1, minus = 0;
649
 
650
/* see putnumber in texmath.c*/
651
        if( (p3 = strpbrk(buf, "Ee")) == NULL) continue;
652
        p1 += p3-buf;
653
            //count the number of 0, +, -
5517 bpr 654
        if (*(p1+k) == '-') { minus = 1; k++; }
5503 bpr 655
        while(*(p1+k)=='0' || *(p1+k)=='+') k++;
656
 
5517 bpr 657
        string_modify(p,p1,p1+k, minus? EXPBEGMINUS: EXPBEG);
658
        p2 += strlen(minus? EXPBEGMINUS: EXPBEG)-k;
659
        string_modify(p,p2,p2, EXPEND);
660
        p2 += strlen(EXPEND);
5503 bpr 661
    } else {
662
            /* alphabetic name, replace greek letters and symbols in hmname*/
663
            /* not done in texmath.c*/
664
        int i = search_list(hmname,hmname_no,sizeof(hmname[0]),buf);
665
        char *n, *r;
666
        if(i<0) { /* not in list */
667
                int k = strlen(buf)-1;
668
            if(myisdigit(buf[k])) {
669
               while(k>0 && myisdigit(buf[k-1])) k--;
670
               string_modify(buf,buf+k,buf+k,SUBBEG);
671
               string_modify(p,p1,p2,"%s%s",buf,SUBEND);
672
               p2+=strlen(SUBBEG)+strlen(SUBEND);
673
            }
674
            continue;
675
        }
676
        n = hmname[i].name;
677
        r = mathalign_base < 2? hmname[i].replace: hmname[i].replacem;
678
        if(r[0]==0) { /* replace = "" */
679
                string_modify(p,p1,p2,"%s%s",m_prefix, n);
680
                p2 = p1+strlen(n)+strlen(m_prefix);
681
        } else {
682
                string_modify(p,p1,p2,"%s",r);
683
                p2 = p1+strlen(r);
684
            }
685
        }
686
  }
5465 bpr 687
}
688
 
7673 bpr 689
/* translate raw math expression coming from calculators into best html way
5551 bpr 690
 * if int n != 0, use html code, else use tex code */
691
void __htmlmath(char *p,int n)
5465 bpr 692
{
5503 bpr 693
    if(!rawmath_easy) { rawmath_easy=1; rawmath(p); rawmath_easy=0;}
5466 bpr 694
    __replace_htmlmath_gtlt(p); //only used in deductio
5551 bpr 695
    __replace_exponent(p,n);
696
    __replace_subscript(p,n);
5517 bpr 697
    __replace_getrid1(p);
5551 bpr 698
    __replace_mathvar(p,n);
5517 bpr 699
    __replace_getridstar(p);
5551 bpr 700
    __replace_arrow(p,n);
5503 bpr 701
/* Now make substitutions */
5465 bpr 702
    substit(p);
5503 bpr 703
/* Make single names italic - done automatically by mathml */
5551 bpr 704
   __replace_italics(p,n);
5465 bpr 705
   strip_trailing_spaces(p);
706
}
707
 
7673 bpr 708
void htmlmath(char *p)
5465 bpr 709
{
5551 bpr 710
 __htmlmath(p,1) ;
5544 bpr 711
}
712
 
713
/* if mathml is closed, it will be just htmlmath*/
714
 
7673 bpr 715
void mathmlmath(char *p)
716
{
5551 bpr 717
    if (mathalign_base == 2) { __htmlmath(p,0) ; mathml(p,1);} else { __htmlmath(p,1) ;}
5465 bpr 718
}