00001 00002 // MathCore = a WYSIWYG equation editor + a powerful math engine // 00003 // Copyright (C) 2003 by Francesco Montorsi // 00004 // // 00005 // This library is free software; you can redistribute it and/or // 00006 // modify it under the terms of the GNU Lesser General Public // 00007 // License as published by the Free Software Foundation; either // 00008 // version 2.1 of the License, or (at your option) any later // 00009 // version. // 00010 // // 00011 // This library is distributed in the hope that it will be useful, // 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00014 // GNU Lesser General Public License for more details. // 00015 // // 00016 // You should have received a copy of the GNU Lesser General Public // 00017 // License along with this program; if not, write to the Free // 00018 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, // 00019 // MA 02111-1307, USA. // 00020 // // 00021 // For any comment, suggestion or feature request, please contact // 00022 // the administrator of the project at frm@users.sourceforge.net // 00023 // // 00031 00032 00033 00034 // optimization for GCC compiler 00035 #ifdef __GNUG__ 00036 #pragma implementation "Symbol.h" 00037 #endif 00038 00039 // Includes 00040 #include "mc/mcprec.h" 00041 #ifdef __BORLANDC__ 00042 #pragma hdrstop 00043 #endif 00044 00045 #ifndef mcPRECOMP 00046 #include <wx/dcscreen.h> 00047 #include "mc/Symbol.h" 00048 #endif 00049 00050 00051 00052 mcIMPLEMENT_MAIN_CLASS(mcSymbol, mcExpElement); 00053 00054 00055 // init customizable variables 00056 wxColour mcSymbolHelpers::sgui_clrUndefSymbols = wxColour(255, 0, 0); 00057 00058 mcSymbolArray mcSymbol::arrParameters(mcSYM_PARAMETER); 00059 mcSymbolArray mcSymbol::arrConstants(mcSYM_CONSTANT); 00060 mcSymbolArray mcSymbol::arrUnknowns(mcSYM_UNKNOWN); 00061 mcSymbolArray mcSymbol::arrUnregistered(mcSYM_UNREGISTERED); 00062 00063 // the default symbol order is: CONSTANTS-PARAMETERS-UNKNOWNS 00064 int mcSymbolHelpers::smath_nConstantOrderPos = 1; 00065 int mcSymbolHelpers::smath_nParameterOrderPos = 2; 00066 int mcSymbolHelpers::smath_nUnknownOrderPos = 3; 00067 00068 00069 00070 00071 // ---------------------------------------- 00072 // mcSYMBOL 00073 // ---------------------------------------- 00074 00075 // a little macro used to avoid repetition of specialized code in 00076 // mcSymbol::math_FindSymbol() function 00077 #define SEARCH_IN_ARRAY(x) \ 00078 n = x.data_FindSymbol(flags, name, enc, value, subscript, inlined, occ); \ 00079 if (n != mcSYM_NOTFOUND) { \ 00080 if (entry != NULL) *entry = n; \ 00081 return &x; \ 00082 } 00083 00084 mcSymbolArray *mcSymbol::math_FindSymbol(long flags, 00085 const wxString &name, 00086 wxFontEncoding enc, 00087 const mcRealValue &value, 00088 const wxString &subscript, 00089 const wxString &inlined, 00090 int occ, 00091 int *entry, 00092 int skipArr) 00093 { 00094 int n; 00095 00096 // search among the three arrays 00097 if (skipArr != mcSYM_UNKNOWN) { SEARCH_IN_ARRAY(arrUnknowns); } 00098 if (skipArr != mcSYM_PARAMETER) { SEARCH_IN_ARRAY(arrParameters); } 00099 if (skipArr != mcSYM_CONSTANT) { SEARCH_IN_ARRAY(arrConstants); } 00100 if (skipArr != mcSYM_UNREGISTERED) { SEARCH_IN_ARRAY(arrUnregistered); } 00101 00102 // we didn't find any symbol with that label 00103 return NULL; 00104 } 00105 00106 00107 #define SEARCH_IN_ARRAY2(x) \ 00108 n = x.data_FindSymbol(flags, sym, occ); \ 00109 if (n != mcSYM_NOTFOUND) { \ 00110 if (entry != NULL) *entry = n; \ 00111 return &x; \ 00112 } 00113 00114 mcSymbolArray *mcSymbol::math_FindSymbol(long flags, const mcSymbolProperties &sym, 00115 int occ, int *entry, int skipArr) 00116 { 00117 int n; 00118 00119 // search among the three arrays 00120 if (skipArr != mcSYM_UNKNOWN) { SEARCH_IN_ARRAY2(arrUnknowns); } 00121 if (skipArr != mcSYM_PARAMETER) { SEARCH_IN_ARRAY2(arrParameters); } 00122 if (skipArr != mcSYM_CONSTANT) { SEARCH_IN_ARRAY2(arrConstants); } 00123 if (skipArr != mcSYM_UNREGISTERED) { SEARCH_IN_ARRAY2(arrUnregistered); } 00124 00125 // we didn't find any symbol with that label 00126 return NULL; 00127 } 00128 00129 #define SEARCH_DUPLICATE_IN(arr) \ 00130 n = x->data_GetSymbol(i)->math_FindDuplicate(arr, 0); \ 00131 if (n != mcSYM_NOTFOUND) m = arr; 00132 00133 void mcSymbol::CheckArray(mcSymbolArray *x) 00134 { 00135 int i, n; 00136 00137 // VERY SLOW !!! 00138 for (i=0; i < x->data_GetCount(); i++) { 00139 00140 // begin to check the i-th symbol 00141 x->data_GetSymbol(i)->data_Check(); 00142 00143 // search for duplicates 00144 mcSymbolArray *m = NULL; 00145 SEARCH_DUPLICATE_IN(&arrParameters); 00146 SEARCH_DUPLICATE_IN(&arrUnknowns); 00147 SEARCH_DUPLICATE_IN(&arrConstants); 00148 SEARCH_DUPLICATE_IN(&arrUnregistered); 00149 00150 // remove this error... 00151 if (m != NULL) m->data_RemoveAt(n); 00152 } 00153 } 00154 00155 void mcSymbol::CheckSymbols() 00156 { 00157 00158 // scan each array, checking for symbols with the same name in all the three 00159 // arrays, skipping the character we are analyzing; if two homonyms are found, 00160 // delete the last one and repeat the check at the end 00161 CheckArray(&arrParameters); 00162 CheckArray(&arrConstants); 00163 CheckArray(&arrUnknowns); 00164 CheckArray(&arrUnregistered); 00165 } 00166 00167 void mcSymbol::InitSymbols() 00168 { 00169 // link the array all together: each array is linked to itself, 00170 // so, when trying to add new symbols, each array checks not 00171 // only all other arrays; it checks also itself... 00172 arrParameters.data_LinkWithArray(&arrParameters); 00173 arrParameters.data_LinkWithArray(&arrConstants); 00174 arrParameters.data_LinkWithArray(&arrUnknowns); 00175 arrParameters.data_LinkWithArray(&arrUnregistered); 00176 00177 arrConstants.data_LinkWithArray(&arrConstants); 00178 arrConstants.data_LinkWithArray(&arrParameters); 00179 arrConstants.data_LinkWithArray(&arrUnknowns); 00180 arrConstants.data_LinkWithArray(&arrUnregistered); 00181 00182 arrUnknowns.data_LinkWithArray(&arrUnknowns); 00183 arrUnknowns.data_LinkWithArray(&arrParameters); 00184 arrUnknowns.data_LinkWithArray(&arrConstants); 00185 arrUnknowns.data_LinkWithArray(&arrUnregistered); 00186 00187 arrUnregistered.data_LinkWithArray(&arrParameters); 00188 arrUnregistered.data_LinkWithArray(&arrConstants); 00189 arrUnregistered.data_LinkWithArray(&arrUnknowns); 00190 arrUnregistered.data_LinkWithArray(&arrUnregistered); 00191 } 00192 00193 void mcSymbol::CleanupSymbols() 00194 { 00195 arrParameters.data_Clear(); 00196 arrUnknowns.data_Clear(); 00197 arrConstants.data_Clear(); 00198 arrUnregistered.data_Clear(); 00199 } 00200 00201 bool mcSymbol::LoadSymbols(const wxXml2Node &root, bool rem) 00202 { 00203 bool ret = TRUE; 00204 00205 // just load all the nodes in the given XML tree 00206 wxXml2Node next = root.GetFirstChild(); 00207 while (next != wxXml2EmptyNode) { 00208 00209 // skip if not valid... 00210 if (next.GetType() == wxXML_ELEMENT_NODE) { 00211 00212 // load its properties, or default values if they are 00213 // not present... 00214 wxString name = next.GetPropVal(wxT("name"), wxT("INVALID")); 00215 wxString encodingstr = next.GetPropVal(wxT("encoding"), wxString::Format(wxT("%d"), wxFONTENCODING_DEFAULT)); 00216 wxString subscript = next.GetPropVal(wxT("subscript"), wxT("")); 00217 wxString inlined = next.GetPropVal(wxT("inlinedoutput"), wxT("")); 00218 wxString value = next.GetPropVal(wxT("value"), wxT("0.0")); 00219 00220 long tmp; 00221 encodingstr.ToLong(&tmp); 00222 wxFontEncoding encoding = (wxFontEncoding)tmp; 00223 00224 // check if there is an error 00225 if (name == wxT("INVALID")) { 00226 00227 // skip this node... 00228 next = next.GetNext(); 00229 ret = FALSE; // set error flag 00230 } 00231 00232 // check if a param/unknown/constant and then add it 00233 // overwriting eventually present old symbols with the same name 00234 if (next.GetName().IsSameAs(wxT("param"), FALSE)) { 00235 00236 // ...and add it 00237 arrParameters.data_AddSymbol(rem, name, encoding, value, inlined, subscript); 00238 00239 } else if (next.GetName().IsSameAs(wxT("unknown"), FALSE)) { 00240 00241 // ...and add it 00242 arrUnknowns.data_AddSymbol(rem, name, encoding, value, inlined, subscript); 00243 00244 } else if (next.GetName().IsSameAs(wxT("constant"), FALSE)) { 00245 00246 // ...and add it 00247 arrConstants.data_AddSymbol(rem, name, encoding, value, inlined, subscript); 00248 } 00249 } 00250 00251 next = next.GetNext(); 00252 } 00253 00254 return ret; 00255 } 00256 00257 void mcSymbol::LoadDefaultSymbols(bool rem) 00258 { 00259 // load default constants 00260 arrConstants.data_AddSymbol(rem, wxT("p"), wxFONTENCODING_ISO8859_7, 00261 3.1415926535897932384626433832795, wxT("PI")); 00262 arrConstants.data_AddSymbol(rem, wxT("e"), wxFONTENCODING_DEFAULT, 00263 2.7182818284590452353602874, wxT("E")); 00264 arrConstants.data_AddSymbol(rem, wxT("g"), wxFONTENCODING_ISO8859_7, 00265 0.5772156649015328606065120900824024310421593359399, wxT("G")); 00266 00267 // load default parameters 00268 arrParameters.data_AddSymbol(rem, wxString(wxT("a"))); 00269 arrParameters.data_AddSymbol(rem, wxString(wxT("b"))); 00270 arrParameters.data_AddSymbol(rem, wxString(wxT("c"))); 00271 00272 // load default unknowns 00273 arrUnknowns.data_AddSymbol(rem, wxString(wxT("x"))); 00274 arrUnknowns.data_AddSymbol(rem, wxString(wxT("y"))); 00275 arrUnknowns.data_AddSymbol(rem, wxString(wxT("z"))); 00276 00277 // now, check for repetitions... 00278 CheckSymbols(); 00279 } 00280 00281 00282 00283 00284 // ---------------------------------------- 00285 // mcSYMBOLDATA 00286 // ---------------------------------------- 00287 00288 #ifdef __MCDEBUG__ 00289 00290 wxString mcSymbolHelpers::data_BaseDebug(long flags) const 00291 { 00292 wxString str = wxT("mcSymbol ") + data_GetInlinedSymbol(); 00293 00294 if (data_isParameter()) 00295 str += wxT(" PARAMETER"); 00296 if (data_isConstant()) 00297 str += wxT(" CONSTANT"); 00298 if (data_isUnknown()) 00299 str += wxT(" UNKNOWN"); 00300 if (!data_isRegistered()) 00301 str += wxT(" UNREGISTERED"); 00302 00303 if (data_isGreekSymbol()) 00304 str += wxT(" (greek symbol)"); 00305 str += wxT("\n"); 00306 return str; 00307 } 00308 00309 #endif 00310 00311 void mcSymbolHelpers::data_SetSymbol(const wxString &name) 00312 { 00313 int n; 00314 00315 // get a pointer to our array 00316 mcSymbolArray *arr = mcSymbol::math_FindSymbol(mcSYMFIND_MATCH_NAME, name, 00317 wxFONTENCODING_DEFAULT, 0.0, wxEmptyString, 00318 wxEmptyString, 0, &n); 00319 00320 if (arr == NULL) { 00321 00322 // this symbol is new: add it to the unregistered symbols array 00323 data_LinkWith(mcSymbol::arrUnregistered.data_AddSymbol(TRUE, name)); 00324 00325 } else { 00326 00327 // this symbol is already registered in one of mcSymbol arrays 00328 // (which can be even mcSymbol::arrUnregistered). 00329 data_LinkWith(arr->data_GetSymbol(n)); 00330 } 00331 } 00332 00333 void mcSymbolHelpers::data_SetSubscript(const wxString &str) 00334 { 00335 // change mcSymbolProperties subscript 00336 data_GetProperties()->m_strSubscript = str; 00337 00338 // and then sync it with mcExpElement's subscript 00339 if (str.IsEmpty()) { 00340 data_DestroyExpSub(FALSE); 00341 return; 00342 } 00343 00344 // we must set the subscript... 00345 if (data_GetSub() == mcEmptyElement) 00346 data_CreateExpSub(FALSE); 00347 mcText txt(data_GetSub()); 00348 txt.data_SetText(str); 00349 } 00350 00351 void mcSymbolHelpers::data_Update() 00352 { 00353 int n; 00354 00355 // this symbol should be placed in at least one of mcSymbol 00356 // arrays (also mcSymbol::arrUnregistered is okay)... 00357 mcSymbolArray *arr = 00358 mcSymbol::math_FindSymbol(mcSYMFIND_MATCH_ALL, *data_GetProperties(), 0, &n); 00359 00360 mcASSERT(arr != NULL, wxT("This symbol should be always listed in at least one of ") 00361 wxT("the three arrays (maybe arrUnregistered) !!!")); 00362 00363 if (arr != NULL && !data_isRegistered() && 00364 arr->data_GetArrayId() != data_GetProperties()->m_nSymbolType) { 00365 00366 // we are linked to a mcSymbolProperties contained in the 00367 // mcSymbol::arrUnregistered, but a symbol identic to the 00368 // symbol we are linked to is contained also in another 00369 // array and arrUnregistered has the lowest possible 00370 // priority 00371 data_GetProperties()->data_Unlink(this); 00372 if (data_GetProperties()->data_isUnlinked()) 00373 mcSymbol::arrUnregistered.data_Remove(data_GetProperties()); 00374 00375 data_LinkWith(arr->data_GetSymbol(n)); 00376 } 00377 } 00378 00379 00380 00381 00382 // ---------------------------------------- 00383 // mcSYMBOLGUI 00384 // ---------------------------------------- 00385 00386 bool mcSymbolHelpers::gui_isBeginKey(const mcKey &ke) const 00387 { 00388 // just check c is in the right range; user can insert symbols not 00389 // registered, but they will appear with different color 00390 // (mcMathCore::Get()->sgui_clrUndefSymbols) and MathCore won't be able to 00391 // process data until they became registered symbols 00392 if (wxIsalpha(ke.GetKeyCode()) && ke.GetModifiers() == 0) { 00393 /*mcSymbolArray *arr = mcSymbolHelpers::isSymbolReg(ke.GetKeyCode(), wxT("")); 00394 00395 // if the symbol is registered, there are no problems 00396 if (arr != NULL) { 00397 // cannot set here m_nSymType because hlp() is a const 00398 // function; and hlp() is a const function because it 00399 // cannot modify object's data; and it cannot modify 00400 // object data because hlp() function is called by 00401 // MathCore on a special instance of the class, not 00402 // on the class that will represent the symbol 00403 return TRUE; 00404 } 00405 00406 // if the symbol is undefined, let the user type it, but draw 00407 // it with different color 00408 if (arr == NULL)*/ 00409 return TRUE; 00410 } 00411 00412 // not a valid char 00413 return FALSE; 00414 } 00415 00416 bool mcSymbolHelpers::gui_isBaseEndKey(const mcKey &key) const 00417 { 00418 // if user pressed one of the following keys: 00419 // EDITEXP, EDITSUBSCRIPT, DELETE, CANCEL 00420 // then, process it... 00421 if (mcMathCore::Get()->MatchEditKeys(key)) 00422 return FALSE; 00423 00424 return TRUE; 00425 } 00426 00427 void mcSymbolHelpers::gui_DoRecalcBaseSize() 00428 { 00429 mgui_szBase.Set(0, 0); 00430 if (!data_isLinked()) 00431 return; 00432 00433 // using correct font, retrieve the size of the symbol 00434 wxScreenDC dc; 00435 gui_SelectStyle(dc); 00436 mgui_szBase = gui_GetSizeOf(&dc, data_GetSymbol()); 00437 } 00438 00439 int mcSymbolHelpers::gui_DrawBase(wxDC &hDC, int x, int y, long flags, const wxPoint &pt) const 00440 { 00441 mcGUILOG(wxT("mcSymbolHelpers::gui_DrawBase")); 00442 00443 // if the given pointer is not == mcDRW_NONACTIVE, it must 00444 // be a valid pointer; thus, the cursor is inside the base and 00445 // we must draw all the element as active (included the 00446 // eventually present subscript)... 00447 if (!(flags & mcDRW_NONACTIVE)) { 00448 00449 // set the background color 00450 mcGUILOG(wxT("mcSymbolHelpers::gui_DrawBase [%s] - drawing me as active"), mcTXTTHIS); 00451 hDC.SetBrush(*mcElementHelpers::sgui_pActivationBrush); 00452 hDC.SetPen(*wxBLACK_PEN); 00453 hDC.DrawRectangle(x-sgui_nAdditionalActivationSpaceLeftRight, y, 00454 gui_GetBaseAndSubSize().GetWidth()+sgui_nAdditionalActivationSpaceLeftRight*2, 00455 gui_GetBaseAndSubSize().GetHeight()); 00456 } 00457 00458 // print the symbol using correct font and color 00459 gui_SelectStyle(hDC); 00460 00461 // if the symbol is an undefined symbol, draw it 00462 // with a different color 00463 //data_Update(); 00464 if (!data_isRegistered()) 00465 hDC.SetTextForeground(sgui_clrUndefSymbols); 00466 00467 // draw the symbol 00468 hDC.SetBackgroundMode(wxTRANSPARENT); 00469 hDC.DrawText(data_GetSymbol(), x, y); 00470 00471 return data_GetID(); 00472 } 00473 00474 void mcSymbolHelpers::gui_EditBase() 00475 { 00476 // cursor is now editing the base 00477 mgui_nCursorPos = mcSYMBOL_RIGHTMOST; 00478 mgui_nCursorLoc = mcECL_INSIDEBASE; 00479 } 00480 00481 mcInputRes mcSymbolHelpers::gui_BaseInput(const mcKey &key, mcElement *pnew) 00482 { 00483 // Special case for the first time this function is called 00484 if (!data_hasProperty(mcEP_INITIALIZED)) { 00485 00486 data_SetSymbol((wxChar)key.GetKeyCode()); 00487 00488 if (key.isSpecialKey()) 00489 data_SetAsGreek(TRUE); 00490 00491 data_AddProperty(mcEP_INITIALIZED); 00492 gui_RecalcSize(); 00493 00494 return mcIR_OKAY; 00495 } 00496 00497 // handle the EDITEXP and EDITSUBSCRIPT keypresses 00498 if (gui_HandleSubExpEditKeys(key) == mcIR_OKAY) 00499 return mcIR_OKAY; 00500 00501 // handle other keypresses basing on cursor position 00502 switch (mgui_nCursorPos) { 00503 case mcSYMBOL_LEFTMOST: 00504 00505 // the user wants to delete this symbol using CANC... 00506 if (mcMathCore::Get()->m_pCancelKey->MatchKey(key)) 00507 return mcIR_DELETE_THIS; 00508 00509 // the user wants to delete previous things 00510 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key)) 00511 return mcIR_DELETE_PREVIOUS; 00512 00513 mcMathCore::Get()->SyntaxError(wxT("Cannot type here")); 00514 break; 00515 00516 case mcSYMBOL_RIGHTMOST: 00517 00518 // handle delete requests 00519 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key)) 00520 return mcIR_DELETE_THIS; 00521 if (mcMathCore::Get()->m_pCancelKey->MatchKey(key)) 00522 return mcIR_DELETE_NEXT; 00523 00524 mcMathCore::Get()->SyntaxError(wxT("Cannot type here")); 00525 break; 00526 } 00527 00528 // everything's okay 00529 return mcIR_OKAY; 00530 } 00531 00532 mcInputRes mcSymbolHelpers::gui_SubInput(const mcKey &ev, mcElement *pnew) 00533 { 00534 // do default processing 00535 mcInputRes r = mcExpElementHelpers::gui_ExpSubInput(FALSE, ev, pnew); 00536 00537 // sync mcExpElement subscript with mcSymbolProperties subscript 00538 if (data_GetSub() != mcEmptyElement) 00539 data_GetProperties()->m_strSubscript = mcText(data_GetSub()).data_GetText(); 00540 00541 return r; 00542 } 00543 00544 mcInsertRes mcSymbolHelpers::gui_BaseInsert(const mcElement &toinsert, mcElement *newelem) 00545 { 00546 (*newelem) = mcElement(this); 00547 return mcINSR_REPLACE_THIS; 00548 } 00549 00550 void mcSymbolHelpers::gui_SetBaseCursorPos(const mcCursorPos &flag) 00551 { 00552 if (flag.isBegin()) 00553 mgui_nCursorPos = mcSYMBOL_LEFTMOST; 00554 if (flag.isEnd()) 00555 mgui_nCursorPos = mcSYMBOL_RIGHTMOST; 00556 } 00557 00558 void mcSymbolHelpers::gui_GetBaseCursorPos(mcCursorPos &cp) const 00559 { 00560 if (mgui_nCursorPos == mcSYMBOL_LEFTMOST) 00561 cp.gui_Push(mcCP_BEGIN); 00562 else if (mgui_nCursorPos == mcSYMBOL_RIGHTMOST) 00563 cp.gui_Push(mcCP_END); 00564 else 00565 cp.gui_Push(mgui_nCursorPos); 00566 } 00567 00568 mcMoveCursorRes mcSymbolHelpers::gui_BaseMoveCursor(mcMoveCursorFlag flag, long modifiers) 00569 { 00570 // up/down movements (don't care about actual cursor position) 00571 if (flag == mcMCF_UP) 00572 return mcMCR_SETFOCUS_ABOVE; 00573 if (flag == mcMCF_DOWN) 00574 return mcMCR_SETFOCUS_BELOW; 00575 00576 // handle cursor movements 00577 switch (mgui_nCursorPos) { 00578 case mcSYMBOL_LEFTMOST: 00579 00580 // left/right movements 00581 if (flag == mcMCF_LEFT) 00582 return mcMCR_SETFOCUS_PREVIOUS; 00583 if (flag == mcMCF_RIGHT) { 00584 mgui_nCursorPos = mcSYMBOL_RIGHTMOST; 00585 00586 if (modifiers & mcMCF_EXTEND_SELECTION) 00587 gui_Select(); 00588 } 00589 break; 00590 00591 case mcSYMBOL_RIGHTMOST: 00592 00593 // left/right movements 00594 if (flag == mcMCF_LEFT) 00595 mgui_nCursorPos = mcSYMBOL_LEFTMOST; 00596 if (flag == mcMCF_RIGHT) 00597 return mcMCR_SETFOCUS_NEXT; // mcExpElement will care of the exponent... 00598 break; 00599 } 00600 00601 // everything's okay 00602 return mcMCR_OKAY; 00603 } 00604 00605 int mcSymbolHelpers::gui_BaseMoveCursorUsingPoint(wxDC &dc, const wxPoint &pt) 00606 { 00607 // check if the point where user clicked was on the left or on 00608 // the right of the symbol... 00609 if (pt.x < gui_GetBaseSize().GetWidth()/2) 00610 mgui_nCursorPos = mcSYMBOL_LEFTMOST; 00611 else 00612 mgui_nCursorPos = mcSYMBOL_RIGHTMOST; 00613 return mcMCR_OKAY; 00614 } 00615 00616 int mcSymbolHelpers::gui_GetBaseRelCursorPos(wxDC &hDC, wxPoint *pt) const 00617 { 00618 // cursor is located at the top-left point of the base bounding box 00619 pt->x = 0; 00620 00621 // if the exponent is present, the gui_GetBaseOffsety() function 00622 // will return a positive value: the cursor must start from 00623 // the highest point 00624 #ifdef mcGUI_CURSOR_LONG_AS_POSSIBLE 00625 pt->y = -gui_GetBaseOffsety(); 00626 #else 00627 pt->y = 0; 00628 #endif 00629 00630 // if cursor is at the right of the symbol, adjust left coord. 00631 if (mgui_nCursorPos == mcSYMBOL_RIGHTMOST) 00632 pt->x = gui_GetBaseSize().GetWidth(); 00633 00634 #ifdef mcGUI_CURSOR_LONG_AS_POSSIBLE 00635 return gui_GetHeight(); 00636 #else 00637 return gui_GetBaseSize().GetHeight(); 00638 #endif 00639 } 00640 00641 00642 00643 00644 00645 // ---------------------------------------- 00646 // mcSYMBOLIO 00647 // ---------------------------------------- 00648 00649 wxXml2Node mcSymbolHelpers::io_GetBaseMathML(bool bGetPresentation) const 00650 { 00651 if (bGetPresentation) { 00652 00653 // create an <mi> tag 00654 return wxXml2Node(wxXML_TEXT_NODE, wxXml2EmptyDoc, wxT("mi"), data_GetSymbol()); 00655 } else { 00656 00657 // create a <ci> tag 00658 return wxXml2Node(wxXML_TEXT_NODE, wxXml2EmptyDoc, wxT("ci"), data_GetSymbol()); 00659 } 00660 } 00661 00662 wxString mcSymbolHelpers::io_GetBaseInlinedExpr() const 00663 { 00664 // too easy... 00665 if (data_GetInlinedSymbol().IsEmpty()) 00666 return data_GetSymbol(); 00667 return data_GetInlinedSymbol(); 00668 } 00669 00670 bool mcSymbolHelpers::io_ImportPresentationMathML(wxXml2Node tag, wxString &pErr) 00671 { 00672 mcASSERT(tag.GetName() == wxT("mi"), wxT("Error in mcSymbolHelpers::io_isBeginTag()")); 00673 00674 if (tag.GetChildren().GetType() != wxXML_TEXT_NODE) { 00675 00676 // ooooooops 00677 pErr = wxT("The MathML to import is not valid MathML 2.0\n") 00678 wxT("or there was an error while parsing it."); 00679 return FALSE; 00680 } 00681 00682 // extract data & check it 00683 data_GetSymbol() = tag.GetChildren().GetContent(); 00684 if (data_GetSymbol().Len() != 1) { 00685 00686 pErr = wxT("Found an invalid <MI> tag. Empty <MI> tags or indentifiers\n") 00687 wxT("longer than one character are not supported"); 00688 return FALSE; 00689 } 00690 00691 data_AddProperty(mcEP_INITIALIZED); 00692 return TRUE; 00693 } 00694 00695 bool mcSymbolHelpers::io_ImportBaseInlinedExpr(const wxString &str, int *count, wxString &pErr) 00696 { 00697 // check how many letters are placed at the beginning of the array 00698 int max = 0; 00699 for (int j=0; j < (int)str.Len(); j++) { 00700 if (wxIsalpha(str.GetChar(j))) 00701 max++; 00702 else 00703 break; 00704 } 00705 00706 // at least one letter should be present... 00707 mcASSERT(max > 0, wxT("Error in mcSymbolHelpers::io_isBeginChar")); 00708 00709 // check if the given string should be interpreted as a specific 00710 // symbol (for example, PI should be interpreted as one symbol only 00711 // if #LoadDefaultSymbols() has been called...) 00712 int n; 00713 for (int i=1; i <= max; i++) { 00714 00715 wxString sym = str.Left(i); 00716 mcSymbolArray *p = mcSymbol::math_FindSymbol(mcSYMFIND_MATCH_INLINED, 00717 wxEmptyString, wxFONTENCODING_DEFAULT, 0, wxEmptyString, sym, 0, &n); 00718 00719 // did we find a symbol that, exported as inlined expression, 00720 // is encoded as "sym" ? 00721 if (p) { 00722 00723 // yes !!! 00724 data_LinkWith(p->data_GetSymbol(n)); 00725 data_AddProperty(mcEP_INITIALIZED); 00726 *count = sym.Len(); 00727 return TRUE; 00728 } 00729 } 00730 00731 // extract data 00732 data_SetSymbol(str.GetChar(0)); 00733 data_AddProperty(mcEP_INITIALIZED); 00734 00735 // mcSymbol is always one char long, when expressed as inline expr... 00736 *count = 1; 00737 00738 return TRUE; 00739 } 00740 00741 00742 00743 00744 // ---------------------------------------- 00745 // mcSYMBOLMATH 00746 // ---------------------------------------- 00747 00748 mcExpSimRes mcSymbolHelpers::math_SimplifyBase(long flags, mcElement *pnew) 00749 { 00750 // base cannot be simplified... 00751 return mcESR_DONE; 00752 } 00753 00754 mcExpSimRes mcSymbolHelpers::math_ExpandBase(long flags, mcElement *pnew) 00755 { 00756 // base cannot be expanded ... 00757 return mcESR_DONE; 00758 } 00759 00760 mcExpSimRes mcSymbolHelpers::math_SimplifyBaseExp(long flags, mcElement *pnew) 00761 { 00762 // base cannot be simplified with the exponent... 00763 // we cannot do nothing because a^2 cannot be 00764 // expressed in other ways. 00765 return mcESR_DONE; 00766 } 00767 00768 mcMathType mcSymbolHelpers::math_GetBaseMathType() const 00769 { 00770 mcMathType res(mcMTL1_POLYNOMIAL, mcMTL2_ALGEBRAIC, mcMTL3_CONSTANT); 00771 00772 // by now, return PARAMETRIC even if this symbol is unregistered... 00773 // in future, an assert will be thrown because unregistered symbols 00774 // should not be present while working with math functions... 00775 if (!data_isRegistered() || data_isParameter()) 00776 res.m_tMath3 = mcMTL3_PARAMETRIC; 00777 else if (data_isUnknown()) 00778 res.m_tMath3 = mcMTL3_UNKNOWN; 00779 else 00780 mcASSERT(math_isConstant(), wxT("Something wrong")); 00781 00782 return res; 00783 } 00784 00785 bool mcSymbolHelpers::math_CompareThisOnly(const mcElement &p, long flags) const 00786 { 00787 if (!mcElementHelpers::math_CompareThisOnly(p, flags)) 00788 return FALSE; 00789 00790 // here we are sure that p is a mcSymbol 00791 mcSymbol sym(p); 00792 if (data_GetConstProperties()->data_isSameAs(*sym.data_GetConstProperties())) 00793 return TRUE; 00794 return FALSE; 00795 } 00796 00797 mcRealValue mcSymbolHelpers::math_EvaluateBase() const 00798 { 00799 // this is a very important routine: it will 00800 // block the evaluation process if this symbol 00801 // is not a constant (and the special evaluation 00802 // system, see mcSymbolProperties::m_bEvaluating 00803 // for more info, is not being used)... 00804 if (!data_isConstant() && !data_GetConstProperties()->math_isBeingEvaluated()) 00805 return *mcRealValue::pNAN; // ... returning to the caller a NAN 00806 00807 return data_GetValue(); 00808 } 00809 00810 bool mcSymbolHelpers::math_isListedBeforeOf(const mcElement &e) const 00811 { 00812 if (e.data_GetType() != mcET_SYMBOL) 00813 return mcElementHelpers::math_isListedBeforeOf(e); 00814 00815 mcSymbol s(e); 00816 00817 // first of all take in count the symboltype 00818 if (s.math_GetOrderPos() == this->math_GetOrderPos()) { 00819 00820 // then, take in count the symbolname 00821 return s.data_GetSymbol() > data_GetSymbol(); 00822 } 00823 00824 // the two types of the symbols are different; put before 00825 // the one that has the lowest order position 00826 return(s.math_GetOrderPos() - this->math_GetOrderPos() > 0); 00827 } 00828 /* 00829 mcPolynomial &mcSymbolHelpers::math_&math_GetFactors() const 00830 { 00831 mcPolynomial &pol = mcNewPolynomial(); 00832 pol.math_WrapSimple(Clone()); 00833 00834 return pol; 00835 } 00836 00837 00838 */
[ Top ] |