Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Symbol.cpp

Go to the documentation of this file.
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 */


Documentation generated with Doxygen on Sun Feb 6 17:10:48 2005
Visit MathStudio home page for more info

[ Top ]