00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00031
00032
00033
00034
00035 #ifdef __GNUG__
00036 #pragma implementation "ExpElement.cpp"
00037 #endif
00038
00039
00040 #include "mc/mcprec.h"
00041 #ifdef __BORLANDC__
00042 #pragma hdrstop
00043 #endif
00044
00045 #ifndef mcPRECOMP
00046
00047 #include "mc/ExpElement.h"
00048 #include "mc/Bracket.h"
00049 #include "mc/Number.h"
00050 #include "mc/Radical.h"
00051 #include "mc/Monomial.h"
00052 #endif
00053
00054
00055 mcIMPLEMENT_ABSTRACT_CLASS(mcExpElement, mcElement);
00056
00057
00058
00059 bool mcExpElementHelpers::smath_bConvertToRadicalWhenPossible = FALSE;
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #ifdef __MCDEBUG__
00070
00071 wxString mcExpElementHelpers::data_Debug(long flags) const
00072 {
00073 wxString str = data_BaseDebug(flags);
00074
00075
00076
00077
00078
00079
00080 if (data_GetExp() != NULL)
00081 str += data_ExpDebug(flags);
00082
00083
00084 if (this->data_hasProperty(mcEP_HASSUBSCRIPT))
00085 str += data_SubDebug(flags);
00086
00087
00088 return str;
00089 }
00090
00091 void mcExpElementHelpers::data_Check() const
00092 {
00093
00094 mcElementHelpers::data_Check();
00095
00096
00097 mcASSERT((data_GetExp() != mcEmptyElement && data_hasProperty(mcEP_HASEXPONENT)) ||
00098 (data_GetExp() == mcEmptyElement && !data_hasProperty(mcEP_HASEXPONENT)),
00099 wxT("The mcEP_HASEXPONENT flag is not synchronized with the exponent variable !"));
00100
00101
00102 const mcElement &e = data_GetExp();
00103 if (e == mcEmptyElement) return;
00104
00105
00106
00107
00108 mcASSERT(e.data_GetType() == mcET_POLYNOMIAL,
00109 wxT("mcExpElementMath can work only on mcPolynomials as exp"));
00110 }
00111
00112 #define mcEXPELEM_HEADER 0
00113
00114 wxString mcExpElementHelpers::data_ExpDebug(long flags) const
00115 {
00116 int step = mcMathCore::Get()->m_nIndentationStep;
00117
00118
00119 return wxString(wxT('*'), mcEXPELEM_HEADER) + wxT(" EXPONENT [\n") +
00120 data_GetExp().data_GetDebug(step, flags) +
00121 wxString(wxT('*'), mcEXPELEM_HEADER) + wxT(" EXPONENT ]");
00122 }
00123
00124 wxString mcExpElementHelpers::data_SubDebug(long flags) const
00125 {
00126 int step = mcMathCore::Get()->m_nIndentationStep;
00127
00128
00129 return wxString(wxT('*'), mcEXPELEM_HEADER) + wxT(" SUBSCRIPT [\n") +
00130 data_GetSub().data_GetDebug(step, flags) +
00131 wxString(wxT('*'), mcEXPELEM_HEADER) + wxT(" SUBSCRIPT ]");
00132 }
00133
00134 #endif // __MCDEBUG__
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 void mcExpElementHelpers::data_CreateExpSub(bool exp)
00145 {
00146 data_DestroyExpSub(exp);
00147
00148 if (exp) {
00149
00150
00151 mcASSERT(mdata_bExpEnabled, wxT("Exponent creation is disabled"));
00152
00153 if (!mdata_pExp.data_isOk())
00154 mdata_pExp.data_SetRefData(new mcPolynomialHelpers());
00155 else
00156 ((mcPolynomial &)mdata_pExp).data_DeleteAll();
00157
00158 } else {
00159
00160
00161 mcASSERT(mdata_bSubEnabled, wxT("Subscript creation is disabled"));
00162
00163 if (!mdata_pSub.data_isOk())
00164 mdata_pSub.data_SetRefData(new mcTextHelpers());
00165 else
00166 ((mcText &)mdata_pSub).data_SetText(wxT(""));
00167
00168 }
00169
00170
00171 data_Get(exp).gui_SetAsExpOf(this);
00172
00173
00174 data_AddProperty(mcEP_HAS(exp));
00175 mcLOG(wxT("mcExpElementHelpers::data_CreateExpSub [%s] - created the "),
00176 mcTXTTHIS, (exp ? wxT("exponent") : wxT("subscript")));
00177 }
00178
00179 void mcExpElementHelpers::data_SetExpSub(bool exp, const mcElement &p)
00180 {
00181
00182 data_CreateExpSub(exp);
00183
00184
00185 data_Get(exp).data_DeepCopy(p);
00186 }
00187
00188 void mcExpElementHelpers::data_DestroyExpSub(bool exp)
00189 {
00190 data_RemoveProperty(mcEP_HAS(exp));
00191
00192 if (exp)
00193 mdata_pExp = mcEmptyElement;
00194 else
00195 mdata_pSub = mcEmptyElement;
00196
00197
00198
00199
00200 }
00201
00202 void mcExpElementHelpers::data_DeepCopyExpSub(bool exp, const mcExpElementHelpers *d)
00203 {
00204 if (d->data_Get(exp) != mcEmptyElement) {
00205
00206
00207 data_CreateExpSub(exp);
00208 data_Get(exp).data_DeepCopy(d->data_Get(exp));
00209
00210 } else {
00211
00212
00213 data_DestroyExpSub(exp);
00214 }
00215 }
00216
00217 void mcExpElementHelpers::data_DeepCopy(const mcElementHelpers *p)
00218 {
00219 const mcExpElementHelpers *d = (const mcExpElementHelpers *)p;
00220
00221
00222 mgui_bExpRight = d->mgui_bExpRight;
00223 mgui_bSubRight = d->mgui_bSubRight;
00224 mdata_bExpEnabled = d->mdata_bExpEnabled;
00225 mdata_bSubEnabled = d->mdata_bSubEnabled;
00226
00227 mgui_nCursorLoc = d->mgui_nCursorLoc;
00228 mgui_szBase = d->mgui_szBase;
00229
00230
00231 data_DeepCopyExpSub(TRUE, d);
00232 data_DeepCopyExpSub(FALSE, d);
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 void mcExpElementHelpers::gui_CreateExpSub(bool exp)
00255 {
00256 data_CreateExpSub(exp);
00257
00258 if (data_Get(exp).data_GetType() == mcET_POLYNOMIAL)
00259 ((mcPolynomial &)data_Get(exp)).gui_AddNewEmptyMonomial();
00260 }
00261
00262 bool mcExpElementHelpers::gui_isEndKey(const mcKey &ev) const
00263 {
00264 if (gui_isCursorInExpSub(TRUE))
00265 return gui_isExpSubEndKey(TRUE, ev);
00266 if (gui_isCursorInExpSub(FALSE))
00267 return gui_isExpSubEndKey(FALSE, ev);
00268
00269
00270 bool b = gui_isBaseEndKey(ev);
00271
00272
00273 if (b == TRUE && gui_GetBaseCursorPos().isEnd() && gui_hasBaseSthOnRightSide())
00274 return FALSE;
00275 if (b == TRUE && gui_GetBaseCursorPos().isBegin() && gui_hasBaseSthOnLeftSide())
00276 return FALSE;
00277
00278 return b;
00279 }
00280
00281 void mcExpElementHelpers::gui_DoRecalcSize()
00282 {
00283 gui_DoRecalcBaseSize();
00284
00285
00286
00287 gui_RecalcExpSubSize(TRUE);
00288 gui_RecalcExpSubSize(FALSE);
00289
00290
00291
00292 int maxw = mcMAX(gui_GetExpSubOffsetx(TRUE)+gui_GetExpSubSize(TRUE).GetWidth(),
00293 gui_GetExpSubOffsetx(FALSE)+gui_GetExpSubSize(FALSE).GetWidth());
00294
00295
00296 int maxh = gui_GetBaseOffsety() + gui_GetBaseAndSubSize().GetHeight();
00297
00298
00299 mgui_sz.SetWidth(mcMAX(maxw, gui_GetBaseSize().GetWidth()));
00300 mgui_sz.SetHeight(maxh);
00301 }
00302
00303 void mcExpElementHelpers::gui_DrawActivationRect(wxDC &dc, int x, int y) const
00304 {
00305
00306 dc.SetBrush(*mcElementHelpers::sgui_pActivationBrush);
00307 dc.SetPen(*wxBLACK_PEN);
00308
00309
00310
00311 dc.DrawRectangle(x-sgui_nAdditionalActivationSpaceLeftRight, y,
00312 gui_GetSize().GetWidth()+sgui_nAdditionalActivationSpaceLeftRight*2,
00313 gui_GetSize().GetHeight());
00314 }
00315
00316 void mcExpElementHelpers::gui_DrawNonActive(wxDC &dc, wxPoint &base, wxPoint &exp, wxPoint &sub) const
00317 {
00318
00319
00320 gui_DrawBase(dc, base.x, base.y, mcDRW_NONACTIVE, wxDefaultPosition);
00321 gui_ExpSubDraw(TRUE, dc, exp.x, exp.y, mcDRW_NONACTIVE, wxDefaultPosition);
00322 gui_ExpSubDraw(FALSE, dc, sub.x, sub.y, mcDRW_NONACTIVE, wxDefaultPosition);
00323 }
00324
00325 void mcExpElementHelpers::gui_DrawAllActive(wxDC &dc, wxPoint &orig, wxPoint &base, wxPoint &exp, wxPoint &sub) const
00326 {
00327
00328 gui_DrawActivationRect(dc, orig.x, orig.y);
00329
00330
00331 gui_DrawNonActive(dc, base, exp, sub);
00332 }
00333
00334 int mcExpElementHelpers::gui_Draw(wxDC &dc, int x, int y, long flags, const wxPoint &pt) const
00335 {
00336
00337 wxPoint orig(x, y);
00338 wxPoint b(x+gui_GetBaseOffsetx(), y+gui_GetBaseOffsety()),
00339 e(x+gui_GetExpSubOffsetx(TRUE), y+gui_GetExpSubOffsety(TRUE)),
00340 s(x+gui_GetExpSubOffsetx(FALSE), y+gui_GetExpSubOffsety(FALSE));
00341 int r = mcDRW_NOACTIVEELEM;
00342
00343
00344 if (flags & mcDRW_NONACTIVE) {
00345
00346
00347 gui_DrawNonActive(dc, b, e, s);
00348 mcGUILOG(wxT("mcExpElementHelpers::gui_Draw [%s] - just drawn everything as inactive"), mcTXTTHIS);
00349 return mcDRW_NOACTIVEELEM;
00350
00351 } else if (flags & mcDRW_ALLACTIVE) {
00352
00353
00354 gui_DrawAllActive(dc, orig, b, e, s);
00355 mcGUILOG(wxT("mcExpElementHelpers::gui_Draw [%s] - just drawn everything as active"), mcTXTTHIS);
00356
00357 } else {
00358
00359 mcASSERT(flags & mcDRW_USEPOINT, wxT("Invalid flags"));
00360
00361
00362 if (!data_hasProperty(mcEP_HASEXPONENT)) {
00363
00364
00365
00366
00367
00368
00369 r = gui_DrawBase(dc, b.x, b.y, flags, pt);
00370
00371
00372 if (data_hasProperty(mcEP_HASSUBSCRIPT))
00373 gui_ExpSubDraw(TRUE, dc, s.x, s.y, mcDRW_NONACTIVE, wxDefaultPosition);
00374
00375 return r;
00376
00377
00378 }
00379
00380
00381 wxRect exp(e, data_GetExp().gui_GetSize());
00382 wxRect base(b, gui_GetBaseSize());
00383
00384
00385
00386
00387 int expflags = flags & ~mcDRW_ALLOW_TOTAL_SELECTION;
00388
00389
00390
00391
00392
00393 bool bInsideExp = exp.Inside(pt);
00394 if (!bInsideExp && !base.Inside(pt)) {
00395
00396
00397 gui_DrawAllActive(dc, orig, b, e, s);
00398 mcGUILOG(wxT("mcExpElementHelpers::gui_Draw [%s] - just drawn everything as active"), mcTXTTHIS);
00399
00400 } else if (bInsideExp) {
00401
00402
00403
00404
00405 gui_DrawBase(dc, b.x, b.y, mcDRW_NONACTIVE, wxDefaultPosition);
00406
00407 if (data_hasProperty(mcEP_HASSUBSCRIPT))
00408 gui_ExpSubDraw(FALSE, dc, s.x, s.y, mcDRW_NONACTIVE, wxDefaultPosition);
00409
00410 return gui_ExpSubDraw(TRUE, dc, e.x, e.y, expflags, pt);
00411
00412 } else {
00413
00414
00415
00416 mcASSERT(base.Inside(pt), wxT("The given cursor position is wrong"));
00417
00418 if (gui_DrawAsActiveOverBase()) {
00419
00420
00421
00422 gui_DrawAllActive(dc, orig, b, e, s);
00423
00424 } else {
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 r = gui_DrawBase(dc, b.x, b.y, flags, pt);
00435
00436 if (data_hasProperty(mcEP_HASSUBSCRIPT))
00437 gui_ExpSubDraw(FALSE, dc, s.x, s.y, mcDRW_NONACTIVE, wxDefaultPosition);
00438
00439 gui_ExpSubDraw(TRUE, dc, e.x, e.y, mcDRW_NONACTIVE, wxDefaultPosition);
00440
00441 return r;
00442 }
00443 }
00444 }
00445
00446
00447 return data_GetID();
00448 }
00449
00450 mcInputRes mcExpElementHelpers::gui_Input(const mcKey &ev, mcElement *newelem)
00451 {
00452 if (gui_isCursorInExpSub(TRUE))
00453 return gui_ExpSubInput(TRUE, ev, newelem);
00454 else if (gui_isCursorInExpSub(FALSE))
00455 return gui_ExpSubInput(FALSE, ev, newelem);
00456 return gui_BaseInput(ev, newelem);
00457 }
00458
00459 mcInsertRes mcExpElementHelpers::gui_Insert(const mcElement &toinsert, mcElement *newelem)
00460 {
00461 if (gui_isCursorInExpSub(TRUE)){
00462 return data_GetExp().gui_Insert(toinsert, newelem);
00463 }
00464 else if (gui_isCursorInExpSub(FALSE)) {
00465 return data_GetSub().gui_Insert(toinsert, newelem);
00466 }
00467
00468 return gui_BaseInsert(toinsert, newelem);
00469 }
00470
00471 void mcExpElementHelpers::gui_OnSelect(wxDC &dc, wxRect &rc)
00472 {
00473
00474 gui_DeSelect();
00475
00476
00477 if (!data_hasProperty(mcEP_HASEXPONENT)) {
00478 gui_OnBaseSelect(dc, rc);
00479 return;
00480 }
00481
00482 int w = gui_GetExpSubOffsetx(TRUE), h = gui_GetBaseOffsety();
00483 wxRect exprc(wxPoint(w, 0), data_GetExp().gui_GetSize());
00484 wxRect baserc(wxPoint(0, h), mgui_szBase);
00485
00486 bool base = baserc.Intersects(rc);
00487 bool exp = exprc.Intersects(rc);
00488
00489
00490 if (exp && !base) {
00491
00492
00493 rc.Offset(-exprc.x, -exprc.y);
00494 data_GetExp().gui_OnSelect(dc, rc);
00495
00496
00497 if (data_GetExp().gui_isSelected())
00498 gui_Select();
00499 return;
00500 }
00501
00502
00503
00504 if (exp && base) {
00505 this->gui_SelectAll();
00506 return;
00507 }
00508
00509
00510
00511 if (base)
00512 gui_OnBaseSelect(dc, rc);
00513 }
00514
00515 mcElement mcExpElementHelpers::gui_GetSelection() const
00516 {
00517 if (gui_isAllSelected())
00518 return mcElement(this);
00519
00520
00521
00522 if (!data_hasProperty(mcEP_HASEXPONENT))
00523 return gui_GetBaseSelection();
00524
00525
00526 if (data_GetExp().gui_isSelected())
00527 return data_GetExp().gui_GetSelection();
00528
00529 return gui_GetBaseSelection();
00530 }
00531
00532 mcMoveCursorRes mcExpElementHelpers::gui_MoveCursor(mcMoveCursorFlag flag, long modifiers)
00533 {
00534 mcMoveCursorRes n = mcMCR_OKAY;
00535
00536
00537
00538
00539
00540 if (gui_isCursorInExpSub(TRUE)) {
00541
00542
00543 n = gui_ExpSubMoveCursor(TRUE, flag, modifiers);
00544
00545 } else if (gui_isCursorInExpSub(FALSE)) {
00546
00547
00548 n = gui_ExpSubMoveCursor(FALSE, flag, modifiers);
00549
00550 } else if (gui_isCursorInBase()) {
00551
00552
00553 mcMoveCursorRes r = gui_BaseMoveCursor(flag, modifiers);
00554
00555 switch (r) {
00556 case mcMCR_OKAY:
00557 case mcMCR_CANNOT_SETFOCUS:
00558 break;
00559
00560 case mcMCR_SETFOCUS_NEXT:
00561
00562
00563 if (gui_isOnRight(TRUE) && data_hasProperty(mcEP_HASEXPONENT))
00564 gui_EditExpSub(TRUE);
00565 else if (data_hasProperty(mcEP_HASSUBSCRIPT))
00566 gui_EditExpSub(FALSE);
00567 else
00568 return mcMCR_SETFOCUS_NEXT;
00569 break;
00570
00571 case mcMCR_SETFOCUS_PREVIOUS:
00572
00573
00574 if (gui_isOnRight(TRUE) || !data_hasProperty(mcEP_HASEXPONENT))
00575 return mcMCR_SETFOCUS_PREVIOUS;
00576 else
00577 gui_EditExpSub(TRUE);
00578 break;
00579
00580 case mcMCR_SETFOCUS_BELOW:
00581
00582
00583 if (data_hasProperty(mcEP_HASSUBSCRIPT))
00584 gui_EditExpSub(FALSE);
00585 else
00586 return mcMCR_SETFOCUS_BELOW;
00587 break;
00588
00589 case mcMCR_SETFOCUS_ABOVE:
00590
00591
00592 if (data_hasProperty(mcEP_HASEXPONENT))
00593 gui_EditExpSub(TRUE);
00594 else
00595 return mcMCR_SETFOCUS_ABOVE;
00596 break;
00597 }
00598 }
00599
00600 return n;
00601 }
00602
00603 int mcExpElementHelpers::gui_MoveCursorUsingPoint(wxDC &dc, const wxPoint &p)
00604 {
00605
00606
00607 wxRect rc(wxPoint(0, gui_GetBaseOffsety()), gui_GetBaseSize());
00608 wxPoint pt(p);
00609
00610 if (rc.Inside(p)) {
00611
00612
00613 pt.y -= gui_GetBaseOffsety();
00614 int r = gui_BaseMoveCursorUsingPoint(dc, pt);
00615
00616 if (r == mcMCR_CANNOT_SETFOCUS)
00617 return mcMCR_CANNOT_SETFOCUS;
00618
00619
00620 mgui_nCursorLoc = mcECL_INSIDEBASE;
00621 return mcMCR_OKAY;
00622
00623 } else if (data_hasProperty(mcEP_HASEXPONENT)) {
00624
00625
00626
00627
00628
00629 wxRect exp(wxPoint(this->gui_GetExpSubOffsetx(TRUE), 0),
00630 data_GetExp().gui_GetSize());
00631
00632 if (exp.Inside(p)) {
00633
00634 int r = gui_ExpSubMoveCursorUsingPoint(TRUE, dc, p);
00635
00636 if (r == mcMCR_CANNOT_SETFOCUS)
00637 return mcMCR_CANNOT_SETFOCUS;
00638
00639
00640 mgui_nCursorLoc = mcECL_INSIDEEXPONENT;
00641 return mcMCR_OKAY;
00642 }
00643
00644
00645
00646 } else {
00647
00648
00649
00650 }
00651
00652 return mcMCR_OKAY;
00653 }
00654
00655 void mcExpElementHelpers::gui_SetCursorPos(const mcCursorPos &code)
00656 {
00657 if (code.isBegin()) {
00658
00659
00660 if (gui_hasBaseSthOnLeftSide())
00661 gui_SetExpSubCursorPos(TRUE, code);
00662 else
00663 gui_SetBaseCursorPos(code);
00664
00665 } else {
00666
00667 mcASSERT(code.isEnd(), wxT("gui_SetCursorPos can handle only mcCP_BEGIN, mcCP_END"));
00668
00669
00670 if (gui_hasBaseSthOnRightSide())
00671 gui_SetExpSubCursorPos(TRUE, code);
00672
00673
00674
00675
00676 if (!data_hasProperty(mcEP_HASEXPONENT) || !gui_isOnRight(TRUE)) {
00677
00678
00679
00680 if (data_hasProperty(mcEP_HASSUBSCRIPT))
00681 gui_SetExpSubCursorPos(FALSE, code);
00682 else
00683 gui_SetBaseCursorPos(code);
00684 }
00685 }
00686 }
00687
00688 void mcExpElementHelpers::gui_GetCursorPos(mcCursorPos &cp) const
00689 {
00690 if (gui_isCursorInExpSub(TRUE))
00691 gui_GetExpSubCursorPos(TRUE, cp);
00692 else if (gui_isCursorInExpSub(FALSE))
00693 gui_GetExpSubCursorPos(FALSE, cp);
00694 else {
00695
00696
00697 mcCursorPos r(gui_GetBaseCursorPos());
00698
00699
00700
00701 if (r.isBegin() && !gui_hasBaseSthOnLeftSide())
00702 cp.gui_Push(mcCP_BEGIN);
00703 else if (r.isEnd() && !gui_hasBaseSthOnRightSide())
00704 cp.gui_Push(mcCP_END);
00705 else
00706
00707
00708 cp.gui_Push(mgui_nCursorLoc);
00709 }
00710 }
00711
00712 int mcExpElementHelpers::gui_GetRelCursorPos(wxDC &dc, wxPoint *pt) const
00713 {
00714 int n;
00715 if (gui_isCursorInExpSub(TRUE))
00716 return gui_GetExpSubRelCursorPos(TRUE, dc, pt);
00717 else if (gui_isCursorInExpSub(FALSE))
00718 return gui_GetExpSubRelCursorPos(FALSE, dc, pt);
00719
00720
00721 n = gui_GetBaseRelCursorPos(dc, pt);
00722
00723
00724 pt->y += gui_GetBaseOffsety();
00725 pt->x += gui_GetBaseOffsetx();
00726
00727 return n;
00728 }
00729
00730 int mcExpElementHelpers::gui_GetYAnchor() const
00731 {
00732
00733
00734
00735
00736 return gui_GetBaseSize().GetHeight()/2 + gui_GetBaseOffsety();
00737 }
00738
00739 void mcExpElementHelpers::gui_UpdateExpDepth()
00740 {
00741
00742 if (data_GetExp() != mcEmptyElement)
00743 data_GetExp().gui_SetAsExpOf(this);
00744
00745
00746 if (data_GetSub() != mcEmptyElement)
00747 data_GetSub().gui_SetAsExpOf(this);
00748
00749
00750 mcElementHelpers::gui_UpdateExpDepth();
00751 }
00752
00753 bool mcExpElementHelpers::gui_isCursorInBase() const
00754 {
00755
00756 if (mgui_nCursorLoc == mcECL_INSIDEBASE)
00757 return TRUE;
00758 return FALSE;
00759 }
00760
00761 bool mcExpElementHelpers::gui_hasBaseSthOnRightSide() const
00762 {
00763 if ((gui_isOnRight(TRUE) && data_hasProperty(mcEP_HASEXPONENT))
00764 || data_hasProperty(mcEP_HASSUBSCRIPT))
00765 return TRUE;
00766 return FALSE;
00767 }
00768
00769 bool mcExpElementHelpers::gui_hasBaseSthOnLeftSide() const
00770 {
00771 if (!gui_isOnRight(TRUE) && data_hasProperty(mcEP_HASEXPONENT))
00772 return TRUE;
00773 return FALSE;
00774 }
00775
00776 int mcExpElementHelpers::gui_HandleSubExpEditKeys(const mcKey &key)
00777 {
00778
00779 if (mcMathCore::Get()->m_pEditExpKey->MatchKey(key)
00780 && mdata_bExpEnabled) {
00781 gui_EditExpSub(TRUE);
00782 return mcIR_OKAY;
00783 }
00784
00785
00786 if (mcMathCore::Get()->m_pEditSubscriptKey->MatchKey(key)
00787 && mdata_bSubEnabled) {
00788 gui_EditExpSub(FALSE);
00789 return mcIR_OKAY;
00790 }
00791
00792
00793
00794 return !mcIR_OKAY;
00795 }
00796
00797 wxSize mcExpElementHelpers::gui_GetBaseAndSubSize() const
00798 {
00799 int h = gui_GetBaseSize().GetHeight();
00800
00801
00802 if (data_hasProperty(mcEP_HASSUBSCRIPT))
00803 h = mcMAX(gui_GetExpSubOffsety(FALSE) - gui_GetBaseOffsety()
00804 + gui_GetExpSubSize(FALSE).GetHeight(), h);
00805
00806 return wxSize(gui_GetBaseSize().GetWidth()+gui_GetExpSubSize(FALSE).GetWidth(), h);
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820 bool mcExpElementHelpers::gui_isCursorInExpSub(bool exp, bool bCheckBeginEndExp) const
00821 {
00822
00823 if (!data_hasProperty(mcEP_HAS(exp)))
00824 return FALSE;
00825
00826
00827 if (mgui_nCursorLoc == mcECL_INSIDE(exp))
00828 return TRUE;
00829
00830
00831 if (bCheckBeginEndExp && mgui_nCursorLoc == mcECL_END(exp))
00832 return TRUE;
00833
00834 if (bCheckBeginEndExp && exp && mgui_nCursorLoc == mcECL_EXPONENTBEGIN)
00835 return TRUE;
00836
00837 return FALSE;
00838 }
00839
00840 bool mcExpElementHelpers::gui_isExpSubEndKey(bool exp, const mcKey &ev) const
00841 {
00842 if (mgui_nCursorLoc == mcECL_BEGIN(exp)) {
00843
00844
00845
00846 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(ev))
00847 return FALSE;
00848
00849
00850 return TRUE;
00851
00852 } else if (mgui_nCursorLoc == mcECL_INSIDE(exp)) {
00853
00854
00855
00856
00857 return data_Get(exp).gui_isEndKey(ev);
00858
00859 } else if (mgui_nCursorLoc == mcECL_END(exp)) {
00860
00861
00862
00863 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(ev))
00864 return FALSE;
00865 if (mcGetEditKey(exp)->MatchKey(ev))
00866 return FALSE;
00867
00868
00869 return TRUE;
00870 }
00871
00872
00873
00874 return FALSE;
00875 }
00876
00877 int mcExpElementHelpers::gui_ExpSubDraw(bool exp, wxDC &dc, int x, int y,
00878 long flags, const wxPoint &pt) const
00879 {
00880
00881 if (!data_hasProperty(mcEP_HAS(exp)))
00882 return mcDRW_NOACTIVEELEM;
00883
00884
00885 return data_Get(exp).gui_Draw(dc, x, y, flags, pt);
00886 }
00887
00888 wxSize mcExpElementHelpers::gui_GetExpSubSize(bool exp)
00889 {
00890 if (data_hasProperty(mcEP_HAS(exp)))
00891 return data_Get(exp).gui_GetSize();
00892
00893
00894
00895 return wxSize(0, 0);
00896 }
00897
00898
00899
00900
00901 wxSize mcExpElementHelpers::gui_GetExpSubSize(bool exp) const
00902 {
00903 if (data_hasProperty(mcEP_HAS(exp)))
00904 return data_Get(exp).gui_GetSize();
00905
00906
00907
00908 return wxSize(0, 0);
00909 }
00910
00911 void mcExpElementHelpers::gui_RecalcExpSubSize(bool exp)
00912 {
00913
00914 if (data_Get(exp) == mcEmptyElement)
00915 return;
00916
00917
00918 data_Get(exp).gui_RecalcSize();
00919 }
00920
00921
00922
00923
00924 int mcExpElementHelpers::gui_GetBaseOffsety() const
00925 { return mcElementHelpers::gui_GetBaseOffsety(gui_GetExpSubSize(TRUE).GetHeight()); }
00926
00927 int mcExpElementHelpers::gui_GetBaseOffsetx() const
00928 {
00929
00930 return 0;
00931 }
00932
00933
00934
00935 int mcExpElementHelpers::gui_GetExpSubOffsety(bool exp) const
00936 {
00937 if (!exp)
00938 return gui_GetBaseOffsety() +
00939 mcElementHelpers::gui_GetSubscriptOffsety(gui_GetBaseSize().GetHeight());
00940
00941
00942 return 0;
00943 }
00944
00945 int mcExpElementHelpers::gui_GetExpSubOffsetx(bool exp) const
00946 {
00947
00948
00949 if (exp && gui_isOnRight(exp))
00950 return gui_GetBaseSize().GetWidth();
00951 if (exp)
00952 return 0;
00953
00954
00955 return gui_GetBaseSize().GetWidth();
00956 }
00957
00958
00959
00960
00961 int mcExpElementHelpers::gui_GetExpSubRelCursorPos(bool exp, wxDC &dc, wxPoint *pt) const
00962 {
00963 if (mgui_nCursorLoc == mcECL_BEGIN(exp)) {
00964
00965
00966
00967 pt->x = 0;
00968 pt->y = 0;
00969
00970 return gui_GetHeight();
00971
00972 } else if (mgui_nCursorLoc == mcECL_INSIDE(exp)) {
00973
00974
00975 pt->x = 0;
00976 pt->y = 0;
00977
00978
00979 int n = data_Get(exp).gui_GetRelCursorPos(dc, pt);
00980
00981
00982
00983 pt->x += gui_GetExpSubOffsetx(exp);
00984 pt->y += gui_GetExpSubOffsety(exp);
00985 return n;
00986
00987 } else if (mgui_nCursorLoc == mcECL_END(exp)) {
00988
00989
00990
00991
00992
00993
00994 pt->x = gui_GetWidth();
00995 pt->y = gui_GetExpSubOffsety(exp);
00996 return gui_GetHeight() - pt->y;
00997 }
00998
00999
01000 return mcNotInside(exp);
01001 }
01002
01003 mcMoveCursorRes mcExpElementHelpers::gui_ExpSubMoveCursor(bool exp,
01004 mcMoveCursorFlag flags,
01005 long modifiers)
01006 {
01007 mcMoveCursorRes r;
01008 if (mgui_nCursorLoc == mcECL_INSIDE(exp)) {
01009
01010
01011
01012 r = data_Get(exp).gui_MoveCursor(flags, modifiers);
01013
01014 switch (r) {
01015 case mcMCR_SETFOCUS_NEXT:
01016 if (gui_isOnRight(exp))
01017 mgui_nCursorLoc = mcECL_END(exp);
01018 else
01019 gui_EditBaseAndSetPos(mcCP_BEGIN);
01020 break;
01021
01022 case mcMCR_SETFOCUS_PREVIOUS:
01023 if (gui_isOnRight(exp))
01024 gui_EditBaseAndSetPos(mcCP_END);
01025 else
01026 mgui_nCursorLoc = mcECL_BEGIN(exp);
01027 break;
01028
01029 case mcMCR_SETFOCUS_BELOW:
01030 gui_EditBase();
01031 break;
01032
01033 case mcMCR_SETFOCUS_ABOVE:
01034 return mcMCR_SETFOCUS_ABOVE;
01035
01036 default:
01037 return r;
01038 }
01039
01040 } else if (mgui_nCursorLoc == mcECL_END(exp)) {
01041
01042
01043
01044
01045 switch (flags) {
01046 case mcMCF_LEFT:
01047 case mcMCF_UP:
01048 gui_EditExpSub(exp);
01049 data_Get(exp).gui_SetCursorPos(mcCP_END);
01050 break;
01051
01052 case mcMCF_RIGHT:
01053 return mcMCR_SETFOCUS_NEXT;
01054
01055 case mcMCF_DOWN:
01056 return mcMCR_SETFOCUS_BELOW;
01057 }
01058
01059 } else if (mgui_nCursorLoc == mcECL_BEGIN(exp)) {
01060
01061
01062
01063
01064 switch (flags) {
01065 case mcMCF_LEFT:
01066 return mcMCR_SETFOCUS_PREVIOUS;
01067
01068 case mcMCF_DOWN:
01069 return mcMCR_SETFOCUS_BELOW;
01070
01071 case mcMCF_RIGHT:
01072 case mcMCF_UP:
01073 gui_EditExpSub(exp);
01074 data_Get(exp).gui_SetCursorPos(mcCP_BEGIN);
01075 break;
01076 }
01077
01078 } else {
01079
01080 mcASSERT(0, wxT("unhandled cursor pos"));
01081 }
01082
01083
01084 return mcMCR_OKAY;
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 int mcExpElementHelpers::gui_ExpSubMoveCursorUsingPoint(bool exp, wxDC &dc, const wxPoint &p)
01144 {
01145 if (!gui_isCursorInExpSub(exp))
01146 return mcNotInside(exp);
01147
01148
01149 return data_Get(exp).gui_MoveCursorUsingPoint(dc, p);
01150 }
01151
01152 mcInputRes mcExpElementHelpers::gui_ExpSubInput(bool exp, const mcKey &ev, mcElement *pnew)
01153 {
01154 if (mgui_nCursorLoc == mcECL_BEGIN(exp)) {
01155
01156 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(ev)) {
01157
01158
01159 return mcIR_DELETE_PREVIOUS;
01160
01161 } else {
01162
01163
01164
01165 mcASSERT(0, wxT("Code should never get here"));
01166 }
01167
01168 } else if (mgui_nCursorLoc == mcECL_INSIDE(exp)) {
01169
01170
01171 mcInputRes result = data_Get(exp).gui_Input(ev, pnew);
01172 if (result == mcIR_DELETE_PREVIOUS || result == mcIR_DELETE_THIS) {
01173
01174
01175 gui_DeleteExpSub(exp);
01176 }
01177
01178 gui_RecalcSize();
01179
01180 } else if (mgui_nCursorLoc == mcECL_END(exp)) {
01181
01182 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(ev)) {
01183
01184
01185 gui_ExpSubMoveCursor(exp, mcMCF_LEFT, mcMCF_NOMODIFIERS);
01186
01187 } else if (mcGetEditKey(exp)->MatchKey(ev)) {
01188
01189
01190 gui_EditExpSub(exp);
01191
01192 } else {
01193
01194 mcASSERT(0, wxT("All the other input should have been blocked ")
01195 wxT("by isSub/ExpEndKey() functions"));
01196 }
01197 }
01198
01199
01200 return mcIR_OKAY;
01201 }
01202
01203 void mcExpElementHelpers::gui_EditExpSub(bool exp)
01204 {
01205
01206 mgui_nCursorLoc = mcECL_INSIDE(exp);
01207
01208
01209 if (data_Get(exp) == mcEmptyElement) {
01210
01211 bool allowed;
01212
01213 if (exp)
01214 allowed = mcElementHelpers::math_isExpAllowed(this);
01215 else
01216 allowed = mcElementHelpers::math_isSubAllowed(this);
01217
01218 if (allowed) {
01219
01220 gui_CreateExpSub(exp);
01221 gui_RecalcSize();
01222
01223 } else {
01224
01225
01226 mcMathCore::Get()->SyntaxError(wxT("Cannot nest another exp/sub"));
01227 return;
01228 }
01229 }
01230
01231
01232 gui_CheckExpSub(exp);
01233
01234
01235 bool old = data_hasProperty(mcEP_HAS(exp));
01236
01237
01238
01239 data_AddProperty(mcEP_HAS(exp));
01240
01241
01242
01243
01244 if (old == FALSE) {
01245 gui_RecalcSize();
01246 data_Get(exp).gui_SetCursorPos(mcCP_END);
01247 }
01248 }
01249
01250
01251
01252
01253 void mcExpElementHelpers::gui_EditBaseAndSetPos(const mcCursorPos &cp)
01254 {
01255 gui_EditBase();
01256 gui_SetBaseCursorPos(cp);
01257 }
01258
01259
01260
01261
01262
01263 void mcExpElementHelpers::gui_CheckExpSub(bool exp)
01264 {
01265 if (exp) {
01266 mcPolynomial p(data_GetExp());
01267 if (p.data_isArrayEmpty()) {
01268 p.gui_AddNewEmptyMonomial();
01269
01270
01271 gui_RecalcSize();
01272 }
01273 } else {
01274
01275 }
01276 }
01277
01278 void mcExpElementHelpers::gui_SetExpSubCursorPos(bool exp, const mcCursorPos &code)
01279 {
01280 if (!data_hasProperty(mcEP_HAS(exp)))
01281 return;
01282
01283 if (code.isEnd() && gui_isOnRight(exp))
01284 mgui_nCursorLoc = mcECL_END(exp);
01285 if (code.isBegin() && !gui_isOnRight(exp))
01286 mgui_nCursorLoc = mcECL_BEGIN(exp);
01287 }
01288
01289 void mcExpElementHelpers::gui_GetExpSubCursorPos(bool exp, mcCursorPos &cp) const
01290 {
01291 if (!data_hasProperty(mcEP_HAS(exp))) {
01292 cp.gui_Push(mcCP_UNDEFINED);
01293 return;
01294 }
01295
01296 if (mgui_nCursorLoc == mcECL_BEGIN(exp))
01297 cp.gui_Push(mcCP_BEGIN);
01298 else if (mgui_nCursorLoc == mcECL_INSIDE(exp))
01299 data_Get(exp).gui_GetCursorPos(cp);
01300 else if (mgui_nCursorLoc == mcECL_END(exp))
01301 cp.gui_Push(mcCP_END);
01302 else
01303 cp.gui_Push(mcCP_UNDEFINED);
01304 }
01305
01306 void mcExpElementHelpers::gui_DeleteExpSub(bool exp)
01307 {
01308
01309 gui_EditBase();
01310
01311
01312
01313
01314
01315 gui_SetBaseCursorPos(mcCP_END);
01316
01317
01318 data_DestroyExpSub(exp);
01319 data_RemoveProperty(mcEP_HAS(exp));
01320 }
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334 wxXml2Node mcExpElementHelpers::io_GetMathML(bool bGetPresentation) const
01335 {
01336 bool expv = data_hasProperty(mcEP_HASEXPONENT);
01337 bool subv = data_hasProperty(mcEP_HASSUBSCRIPT);
01338 wxString nodename;
01339
01340
01341
01342 if (expv && !subv)
01343 nodename = wxT("msup");
01344 else if (!expv && subv)
01345 nodename = wxT("msub");
01346 else if (expv && subv)
01347 nodename = wxT("msubsup");
01348 else {
01349
01350
01351 return io_GetBaseMathML(bGetPresentation);
01352 }
01353
01354
01355 wxXml2Node base = io_GetBaseMathML(bGetPresentation);
01356 wxXml2Node maintag(wxXML_ELEMENT_NODE, wxXml2EmptyDoc, nodename);
01357
01358
01359 if (bGetPresentation) {
01360
01361
01362 maintag.AddChild(base);
01363
01364
01365 if (subv) {
01366
01367 wxXml2Node node(data_GetSub().io_GetMathML(bGetPresentation));
01368 maintag.AddChild(node);
01369 }
01370
01371
01372 if (expv) {
01373
01374 wxXml2Node node(data_GetExp().io_GetMathML(bGetPresentation));
01375 maintag.AddChild(node);
01376 }
01377
01378 } else {
01379
01380 mcASSERT(0, wxT("still to implement"));
01381 }
01382
01383
01384 return maintag;
01385 }
01386
01387
01388 wxString mcExpElementHelpers::io_GetInlinedExpr() const
01389 {
01390 bool expv = data_hasProperty(mcEP_HASEXPONENT);
01391 bool subv = data_hasProperty(mcEP_HASSUBSCRIPT);
01392 bool bracketize = FALSE;
01393 wxString str = io_GetBaseInlinedExpr();
01394
01395 if (subv) {
01396
01397
01398 str += wxT("_") + data_GetSub().io_GetInlinedExpr();
01399 }
01400
01401 if (expv) {
01402
01403 str += wxT("^");
01404
01405 if (data_GetExp().data_GetChildrenCount() > 1 &&
01406 data_GetExp().data_GetType() != mcET_BRACKET)
01407 bracketize = TRUE;
01408
01409
01410
01411 if (bracketize) str += wxT("(");
01412 str += data_GetExp().io_GetInlinedExpr();
01413 if (bracketize) str += wxT(")");
01414 }
01415
01416
01417 return str;
01418 }
01419
01420 int GetLastRightBracketIdx(const wxString &str, int nest = 0)
01421 {
01422 int i=0, max=str.Len();
01423 do {
01424 if (i >= max) return -1;
01425
01426 if (mcBracketHelpers::gui_isLeftParenthesis(str.GetChar(i)))
01427 nest++;
01428 else if (mcBracketHelpers::gui_isRightParenthesis(str.GetChar(i)))
01429 nest--;
01430 i++;
01431 } while (nest > 0);
01432
01433 return i;
01434 }
01435
01436 void mcExpElementHelpers::io_GetExpSubInlinedToken(wxString &subexp)
01437 {
01438
01439 subexp.Remove(0, 1);
01440
01441
01442 if (mcBracketHelpers::gui_isLeftParenthesis(subexp.GetChar(0))) {
01443
01444
01445
01446 int i = GetLastRightBracketIdx(subexp);
01447
01448
01449 subexp.Truncate(i);
01450
01451 } else {
01452
01453 subexp = subexp.BeforeFirst(wxT('+'));
01454 subexp = subexp.BeforeFirst(wxT('-'));
01455
01456
01457 int i = GetLastRightBracketIdx(subexp, 1);
01458
01459
01460 if (i > 0) subexp.Truncate(i-1);
01461 }
01462 }
01463
01464 bool mcExpElementHelpers::io_ImportInlinedExpr(const wxString &str, int *count, wxString &pErr)
01465 {
01466
01467
01468
01469 if (!io_ImportBaseInlinedExpr(str, count, pErr))
01470 return FALSE;
01471
01472
01473
01474
01475
01476
01477 wxString subexp = str.Right(str.Len()-*count);
01478 bool bexp, bsub;
01479 int n = 0;
01480
01481
01482
01483 bexp = (subexp.GetChar(0) == wxT('^'));
01484 bsub = (subexp.GetChar(0) == wxT('_'));
01485 if (bexp || bsub) {
01486
01487 io_GetExpSubInlinedToken(subexp);
01488
01489 } else {
01490
01491
01492 return TRUE;
01493 }
01494
01495
01496 if (bexp) {
01497
01498 mcIOLOG(wxT("mcExpElementHelpers::io_ImportInlinedExpr - importing the exp [%s]"), subexp.c_str());
01499
01500
01501
01502 data_CreateExpSub(TRUE);
01503
01504 if (!data_GetExp().io_ImportInlinedExpr(subexp, &n, pErr)) {
01505
01506 *count += n+1;
01507 return FALSE;
01508 }
01509 }
01510
01511
01512 if (bsub) {
01513
01514 mcIOLOG(wxT("mcExpElementHelpers::io_ImportInlinedExpr - importing the subscript [%s]"), subexp.c_str());
01515
01516
01517
01518 data_CreateExpSub(FALSE);
01519
01520 if (!data_GetSub().io_ImportInlinedExpr(subexp, &n, pErr)) {
01521 *count += n;
01522 return FALSE;
01523 }
01524 }
01525
01526 *count += n+1;
01527 return TRUE;
01528 }
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538 bool mcExpElementHelpers::math_hasExp() const
01539 {
01540
01541
01542 return (data_GetExp() != mcEmptyElement) && data_hasProperty(mcEP_HASEXPONENT);
01543 }
01544
01545 bool mcExpElementHelpers::math_hasSub() const
01546 {
01547
01548
01549 return (data_GetSub() != mcEmptyElement) && data_hasProperty(mcEP_HASSUBSCRIPT);
01550 }
01551
01552 const mcPolynomial &mcExpElementHelpers::math_GetConstExp() const
01553 {
01554 const mcElement &e = data_GetExp();
01555
01556
01557 if (e == mcEmptyElement) {
01558
01559 return *mcPolynomialHelpers::smath_pOne;
01560
01561 }
01562
01563
01564 mcASSERT(e.data_GetType() == mcET_POLYNOMIAL,
01565 wxT("mcExpElementMath can work only on mcPolynomials as exp"));
01566 return (const mcPolynomial &)data_GetExp();
01567 }
01568
01569 mcPolynomial &mcExpElementHelpers::math_GetExp()
01570 {
01571 if (data_GetExp() == mcEmptyElement) {
01572 data_CreateExpSub(TRUE);
01573 data_SetExpSub(TRUE, *mcPolynomialHelpers::smath_pOne);
01574 }
01575 return (mcPolynomial &)data_GetExp();
01576 }
01577
01578 const mcText &mcExpElementHelpers::math_GetConstSub() const
01579 {
01580 const mcElement &e = data_GetSub();
01581
01582
01583 if (e == mcEmptyElement)
01584 return *mcTextHelpers::smath_pEmpty;
01585
01586
01587 mcASSERT(e.data_GetType() == mcET_TEXT,
01588 wxT("mcExpElementMath can work only on mcText as sub"));
01589 return (const mcText &)e;
01590 }
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 mcRealValue mcExpElementHelpers::math_EvaluateExp() const
01610 {
01611
01612
01613
01614
01615
01616 if (!math_hasExp())
01617 return 1.0;
01618 return data_GetExp().math_Evaluate();
01619 }
01620
01621 mcRealValue mcExpElementHelpers::math_Evaluate() const
01622 {
01623 mcRealValue base = math_EvaluateBase();
01624 mcRealValue exp = math_EvaluateExp();
01625
01626
01627
01628 if (base.isNAN() ||
01629 exp.isNAN())
01630 return *mcRealValue::pNAN;
01631 return base.pow(exp);
01632 }
01633
01634 mcExpSimRes mcExpElementHelpers::math_Simplify(long flags, mcElement *pnew)
01635 {
01636
01637 if (!math_hasExp())
01638 return math_SimplifyBase(flags, pnew);
01639
01640
01641 mcMATHLOG(wxT("mcExpElementHelpers::math_Simplify [%s]"), mcTXTTHIS);
01642 mcExpSimRes r = data_GetExp().math_Simplify(mcEXPSIM_NOFLAGS, NULL);
01643
01644 switch (r) {
01645 case mcESR_DONE:
01646 return math_SimplifyExp(flags, pnew);
01647
01648 case mcESR_INVALID_DATA:
01649 case mcESR_NOTFINISHED:
01650 return r;
01651
01652 case mcESR_DELETE_THIS:
01653
01654
01655 data_DestroyExpSub(TRUE);
01656 break;
01657
01658 case mcESR_REPLACE_THIS:
01659 case mcESR_DISTRIBUTE:
01660 break;
01661
01662 default:
01663 mcASSERT(0, wxT("Unhandled return flag"));
01664 }
01665
01666 return mcESR_DONE;
01667 }
01668
01669 mcExpSimRes mcExpElementHelpers::math_Expand(long flags, mcElement *newelem)
01670 {
01671 return math_ExpandBase(flags, newelem);
01672
01673
01674 }
01675
01676 mcExpSimRes mcExpElementHelpers::math_SimplifyExp(long flags, mcElement *pnew)
01677 {
01678
01679 mcRealValue d = data_GetExp().math_Evaluate();
01680
01681 if (d == 0.0) {
01682
01683
01684 mcNumber replacement(*mcNumberHelpers::smath_pOne);
01685 (*pnew) = replacement;
01686 return mcESR_REPLACE_THIS;
01687 }
01688
01689 if (d > 0.0 && d < 1.0 && smath_bConvertToRadicalWhenPossible) {
01690
01691 mcRadical replacement;
01692 mcExpElement copy(this);
01693
01694
01695 copy.data_DestroyExpSub(TRUE);
01696 replacement.data_GetContent().math_WrapSimple(copy);
01697
01698 (*pnew) = replacement;
01699 return mcESR_REPLACE_THIS;
01700 }
01701
01702 if (d == 1.0) {
01703
01704
01705
01706
01707 if (math_GetConstExp().data_GetCount() == 1) {
01708 mcMonomial m(math_GetConstExp().data_GetElemOfType(0, mcET_MONOMIAL));
01709
01710 if (m.data_GetCount() == 1 &&
01711 m.data_Get(0).data_GetType() == mcET_NUMBER)
01712 data_DestroyExpSub(TRUE);
01713 }
01714
01715 return mcESR_DONE;
01716 }
01717
01718
01719
01720
01721 return math_SimplifyBaseExp(flags, pnew);
01722 }
01723
01724 mcBasicOpRes mcExpElementHelpers::math_RaiseTo(const mcPolynomial &p)
01725 {
01726 mcMATHLOG(wxT("mcExpElementHelpers::math_RaiseTo [%s] - raising to [%s]"),
01727 mcTXTTHIS, mcTXT(p));
01728 math_GetExp().math_SimpleMultiplyBy(p);
01729
01730 return mcBOR_REMOVE_OPERAND;
01731 }
01732
01733 bool mcExpElementHelpers::math_CompareExp(const mcExpElement &p, long flags) const
01734 {
01735 if (!this->math_hasExp() && !p.math_hasExp())
01736 return TRUE;
01737
01738
01739 const mcPolynomial &exp = p.math_GetConstExp();
01740 return math_GetExp().math_Compare(exp, flags);
01741 }
01742
01743 bool mcExpElementHelpers::math_CompareSub(const mcExpElement &p, long flags) const
01744 {
01745 if (!this->math_hasSub() && !p.math_hasSub())
01746 return TRUE;
01747
01748
01749 return data_GetSub().math_Compare(p.data_GetSub(), flags);
01750 }
01751
01752 bool mcExpElementHelpers::math_Compare(const mcElement &p, long flags) const
01753 {
01754
01755 if (data_GetType() != p.data_GetType())
01756 return FALSE;
01757
01758 mcExpElement e(p);
01759
01760
01761 if (!math_CompareThisOnly(e, flags))
01762 return FALSE;
01763
01764
01765 if (!math_CompareSub(e, flags))
01766 return FALSE;
01767
01768
01769 if (!math_CompareExp(e, flags))
01770 return FALSE;
01771
01772
01773
01774 return TRUE;
01775 }
01776
01777 mcBasicOpRes mcExpElementHelpers::math_MakeReciprocal(mcElement *)
01778 {
01779
01780
01781 math_GetExp().math_ChangeAllSigns();
01782
01783 return mcBOR_REMOVE_OPERAND;
01784 }
01785
01786 mcBasicOpRes mcExpElementHelpers::math_MultOrDiv(const mcElement &e, mcElement *pp, bool mult)
01787 {
01788 mcMATHLOG(wxT("mcExpElementHelpers::math_MultOrDiv - %s [%s] by [%s]"),
01789 (mult ? wxT("multiplying") : wxT("dividing")), mcTXTTHIS, mcTXT(e));
01790 mcExpElement p(e);
01791
01792
01793 const mcPolynomial &exp1 = math_GetConstExp();
01794 const mcPolynomial &exp2 = p.math_GetConstExp();
01795 mcASSERT(exp1.math_CanBeAddedWith(exp2),
01796 wxT("Two polynomials that cannot be added ?!?"));
01797
01798
01799
01800
01801
01802
01803 if (math_CompareThisOnly(p, FALSE)) {
01804
01805
01806
01807
01808
01809 if ((!this->math_hasExp() && !p.math_hasExp()) ||
01810 exp1.math_Compare(exp2, FALSE)) {
01811
01812
01813
01814
01815
01816
01817 if (mult)
01818 math_GetExp().math_SimpleMultiplyBy(*mcNumberHelpers::smath_pTwo);
01819 else
01820 math_GetExp().math_ResetToZero();
01821
01822 mcMATHLOG(wxT("mcExpElementHelpers::math_MultOrDiv - result is [%s]"), mcTXTTHIS);
01823 return mcBOR_REMOVE_OPERAND;
01824 }
01825
01826
01827
01828 if (mult)
01829 data_GetExp().math_SimpleAdd(exp2);
01830 else
01831 data_GetExp().math_SimpleSubtract(exp2);
01832
01833 mcMATHLOG(wxT("mcExpElementHelpers::math_MultOrDiv - result is [%s]"), mcTXTTHIS);
01834 return mcBOR_REMOVE_OPERAND;
01835 }
01836
01837
01838
01839
01840
01841 if (exp1.math_Compare(exp2, FALSE)) {
01842
01843
01844 if (mult)
01845 return math_MultiplyBaseOnlyBy(p, pp);
01846 else
01847 return math_DivideBaseOnlyBy(p, pp);
01848 }
01849
01850
01851 if (mult)
01852 return math_MultiplyBaseBy(p, pp);
01853 return math_DivideBaseBy(p, pp);
01854 }
01855
01856 mcBasicOpRes mcExpElementHelpers::math_DivideBy(const mcElement &e, mcElement *pp)
01857 {
01858 mcASSERT(math_CanBeDivBy(e),
01859 wxT("This element cannot be divided by the given one"));
01860 return math_MultOrDiv(e, pp, FALSE);
01861 }
01862
01863 mcBasicOpRes mcExpElementHelpers::math_MultiplyBy(const mcElement &e, mcElement *pp)
01864 {
01865 mcASSERT(math_CanBeMultWith(e),
01866 wxT("This element cannot be multiplied by the given one"));
01867 return math_MultOrDiv(e, pp, TRUE);
01868 }
01869
01870 mcMathType mcExpElementHelpers::math_GetMathType() const
01871 {
01872
01873
01874
01875
01876 if (!math_hasExp())
01877 return math_GetBaseMathType();
01878
01879 mcMathType res = math_GetExp().math_GetMathType();
01880 return math_GetBaseMathType().math_RaiseTo(res);
01881 }
01882
01883 mcMonomial mcExpElementHelpers::math_GetBaseLCM(const mcElement &p) const
01884 {
01885
01886 mcExpElement res(this);
01887 mcMonomial m;
01888
01889 m.data_AddElements(&res, 1);
01890 res.math_SimpleMultiplyBy(p);
01891
01892 return m;
01893 }
01894
01895 mcMonomial mcExpElementHelpers::math_GetLCM(const mcElement &p) const
01896 {
01897 mcExpElement e(p);
01898
01899 if (!math_CompareThisOnly(p, FALSE)) {
01900
01901
01902
01903 return math_GetBaseLCM(p);
01904 }
01905
01906 mcMonomial m;
01907 if (!this->math_hasExp()) {
01908 mcExpElement res(p);
01909 m.data_AddElements(&res, 1);
01910 return m;
01911 }
01912
01913 if (!e.math_hasExp()) {
01914 mcExpElement res(this);
01915 m.data_AddElements(&res, 1);
01916 return m;
01917 }
01918
01919
01920 mcElement exp = math_GetExp().math_GetLCM(e.data_GetExp());
01921 mcExpElement res(this);
01922
01923 res.data_SetExpSub(TRUE, exp);
01924 m.data_AddElements(&res, 1);
01925
01926 mcMATHLOG(wxT("mcExpElementHelpers::math_GetLCM - the lcm between [%s] and [%s] is [%s]"),
01927 mcTXTTHIS, mcTXT(p), mcTXT(res));
01928
01929 return m;
01930 }
01931
01932 mcMonomial mcExpElementHelpers::math_GetGCD(const mcElement &p) const
01933 {
01934 mcExpElement e(p);
01935
01936 if (data_GetType() != p.data_GetType())
01937 return *mcMonomialHelpers::smath_pOne;
01938
01939 if (math_CompareThisOnly(p, FALSE)) {
01940
01941
01942
01943
01944 if (math_hasExp() && e.math_hasExp()) {
01945
01946 mcMonomial res;
01947
01948
01949
01950
01951 mcExpElement content(this);
01952 mcMonomial gcd(math_GetExp().math_GetGCD(e.math_GetExp()));
01953 content.data_CreateExpSub(TRUE);
01954 content.math_GetExp().data_AddElements(&gcd, 1);
01955
01956 res.data_AddElements(&content, 1);
01957 return res;
01958
01959 } else {
01960
01961
01962 return math_GetBaseGCD(p);
01963 }
01964 }
01965
01966 return *mcMonomialHelpers::smath_pOne;
01967 }
01968
01969 mcMonomial mcExpElementHelpers::math_GetBaseGCD(const mcElement &p) const
01970 {
01971 mcASSERT(!math_hasExp() || !mcExpElement(p).math_hasExp(),
01972 wxT("This case should have been handled by mcExpElementHelpers::math_GetGCD"));
01973 mcMonomial res;
01974
01975
01976
01977 if (math_hasExp())
01978 res.data_AddElements(&p, 1);
01979 else {
01980 mcElement tmp(this);
01981 res.data_AddElements(&tmp, 1);
01982 }
01983
01984 return res;
01985 }
01986
01987