00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00030
00031
00032
00033
00034 #ifdef __GNUG__
00035 #pragma implementation "MathHelpers.h"
00036 #endif
00037
00038
00039 #include "mc/mcprec.h"
00040 #ifdef __BORLANDC__
00041 #pragma hdrstop
00042 #endif
00043
00044 #ifndef mcPRECOMP
00045 #include "mc/MathHelpers.h"
00046 #include "mc/MathCore.h"
00047 #include "mc/Element.h"
00048 #include "mc/Symbol.h"
00049 #include "mc/Range.h"
00050 #endif
00051
00052
00053
00054
00055
00056 mcRange *mcRange::pN = NULL;
00057 mcRange *mcRange::pZ = NULL;
00058 mcRange *mcRange::pR = NULL;
00059 mcRange *mcRange::pC = NULL;
00060 mcRange *mcRange::pEmpty = NULL;
00061
00062 mcExtRange *mcExtRange::pN = NULL;
00063 mcExtRange *mcExtRange::pZ = NULL;
00064 mcExtRange *mcExtRange::pR = NULL;
00065 mcExtRange *mcExtRange::pC = NULL;
00066 mcExtRange *mcExtRange::pEmpty = NULL;
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 void mcAbstractArray::data_Add(mcAbstractItem *pointer)
00077 {
00078 m_arr.Add(pointer);
00079 data_OnArrayChange();
00080 }
00081
00082 void mcAbstractArray::data_Insert(mcAbstractItem *pointer, int pos)
00083 {
00084
00085
00086 m_arr.Insert(pointer, pos);
00087 data_OnArrayChange();
00088 }
00089
00090 void mcAbstractArray::data_SetItem(mcAbstractItem *pointer, int n)
00091 {
00092 data_Insert(pointer, n);
00093 data_RemoveAt(n+1, 1);
00094 }
00095
00096 void mcAbstractArray::data_RemoveAt(int n, int count)
00097 {
00098
00099 if (n < 0 || n >= data_GetCount())
00100 return;
00101 if (n+count > data_GetCount())
00102 count = data_GetCount()-n;
00103
00104
00105 for (int i=n; i < n+count; i++)
00106 data_Delete(i);
00107
00108
00109 m_arr.RemoveAt(n, count);
00110 data_OnArrayChange();
00111 }
00112
00113 void mcAbstractArray::data_Remove(const mcAbstractItem *p)
00114 {
00115 int idx = data_Find(p);
00116 if (idx == -1) return;
00117
00118 data_RemoveAt(idx);
00119 }
00120
00121 mcAbstractItem *mcAbstractArray::data_Detach(int idx)
00122 {
00123 mcAbstractItem *toret = data_GetItem(idx);
00124
00125
00126
00127 m_arr.RemoveAt(idx, 1);
00128
00129 return toret;
00130 }
00131
00132 void mcAbstractArray::data_Clear()
00133 {
00134 data_RemoveAt(0, data_GetCount());
00135
00136
00137 m_arr.Clear();
00138 }
00139
00140 int mcAbstractArray::data_Find(const mcAbstractItem *pointer) const
00141 {
00142 for (int i=0; i < data_GetCount(); i++)
00143 if (data_GetItem(i) == pointer)
00144 return i;
00145 return -1;
00146 }
00147
00148 void mcAbstractArray::data_DeepCopy(const mcAbstractArray &arr)
00149 {
00150 data_Clear();
00151 for (int i=0, max=arr.data_GetCount(); i<max; i++)
00152 data_Add(arr.data_GetCopyOf(i));
00153 }
00154
00155 #ifdef __MCDEBUG__
00156 void mcAbstractArray::data_Check() const
00157 {
00158 mcASSERT(data_GetCount() >= 0, wxT("Invalid count index"));
00159
00160
00161 for (int i=0; i < data_GetCount(); i++)
00162 for (int j=0; j < data_GetCount(); j++)
00163 mcASSERT(data_GetItem(i) != data_GetItem(j) || i == j,
00164 wxT("The i-th pointer is stored twice (as i and as j) !!!"));
00165
00166 }
00167 #endif
00168
00169
00170
00171
00172
00173
00174
00175
00176 void mcTextSettings::Decode(const wxString &fnt)
00177 {
00178 long style, weight, pointsize, family;
00179 wxString todecode(fnt);
00180 wxString facename;
00181
00182
00183 todecode.AfterLast(wxT('-')).ToLong(&style, 0);
00184 if (style <= 0) style = wxNORMAL;
00185
00186
00187 todecode = todecode.BeforeLast(wxT('-'));
00188 todecode.AfterLast(wxT('-')).ToLong(&weight, 0);
00189 if (weight == 0) weight = wxNORMAL;
00190
00191
00192 todecode = todecode.BeforeLast(wxT('-'));
00193 todecode.AfterLast(wxT('-')).ToLong(&pointsize, 0);
00194 if (pointsize <= 0) pointsize = 16;
00195
00196
00197 todecode = todecode.BeforeLast(wxT('-'));
00198 facename = todecode.AfterLast(wxT('-'));
00199
00200
00201 todecode = todecode.BeforeLast(wxT('-'));
00202 todecode.AfterLast(wxT('-')).ToLong(&family, 0);
00203 if (family <= 0) family = wxSWISS;
00204
00205
00206 m_hFont.SetPointSize(pointsize);
00207 m_hFont.SetWeight(weight);
00208 m_hFont.SetStyle(style);
00209 m_hFont.SetFamily(family);
00210 if (!facename.IsEmpty())
00211 m_hFont.SetFaceName(facename);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221 bool mcStyle::Ok()
00222 {
00223 bool res = TRUE;
00224
00225
00226 for (int i=0; i < mcSTYLE_TEXTSETTINGS_NUM; i++)
00227 res &= m_pTextSettings[i].Ok();
00228
00229 return res;
00230 }
00231
00232 int mcStyle::GetIndexFor(mcElementType t) const
00233 {
00234 switch (t) {
00235
00236
00237 default:
00238 return 0;
00239
00240 case mcET_NUMBER:
00241 return 1;
00242
00243 case mcET_FUNCTION:
00244 return 2;
00245
00246 case mcET_TEXT:
00247 case mcET_MATHANDSYSTEM:
00248 case mcET_MATHORSYSTEM:
00249 case mcET_MATHMNG:
00250 return 3;
00251
00252 case mcET_SYMBOL:
00253 return 4;
00254 }
00255 }
00256
00257 int mcStyle::GetIndexFor(const mcElement &e) const
00258 {
00259
00260 if (e.data_GetType() == mcET_SYMBOL) {
00261 mcSymbol p(e);
00262 if (p.hlp()->data_isGreekSymbol())
00263 return mcSTYLE_SPECIAL_SETTINGS;
00264 }
00265
00266 return GetIndexFor(e.data_GetType());
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 mcStyleArray::~mcStyleArray()
00277 {
00278 if (m_pStyles)
00279 delete [] m_pStyles;
00280 m_pStyles = NULL;
00281 }
00282
00283 void mcStyleArray::CreateArray()
00284 {
00285 if (m_pStyles == NULL)
00286 m_pStyles = new mcStyle[mcELEMENTMATH_MAX_EXPDEPTH];
00287 }
00288
00289 void mcStyleArray::DeepCopy(const mcStyleArray *p)
00290 {
00291
00292 for (int i=0; i < mcELEMENTMATH_MAX_EXPDEPTH; i++)
00293 m_pStyles[i].DeepCopy(&p->m_pStyles[i]);
00294 }
00295
00296 void mcStyleArray::Set(const mcStyle *arr)
00297 {
00298
00299 for (int i=0; i < mcELEMENTMATH_MAX_EXPDEPTH; i++)
00300 m_pStyles[i].DeepCopy(&arr[i]);
00301 }
00302
00303 int mcStyleArray::GetCount()
00304 {
00305
00306
00307
00308 return mcELEMENTMATH_MAX_EXPDEPTH;
00309 }
00310
00311 int mcStyleArray::gui_GetStyleIndexFor(const mcElement &p) const
00312 {
00313
00314
00315
00316
00317
00318 return p.gui_GetExpDepth();
00319 }
00320
00321 void mcStyleArray::ScaleSize(float f)
00322 {
00323 for (int i=0; i < mcELEMENTMATH_MAX_EXPDEPTH; i++)
00324 m_pStyles[i].ScaleSize(f);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334 wxString mcMathType::io_GetDescString() const
00335 {
00336 wxString res;
00337
00338 switch (m_tMath1) {
00339 case mcMTL1_POLYNOMIAL:
00340 res += wxT("polynomial "); break;
00341 case mcMTL1_RATIONAL:
00342 res += wxT("rational "); break;
00343 case mcMTL1_NOT_RECOGNIZED:
00344 res += wxT("[not-recognized] "); break;
00345 }
00346
00347 switch (m_tMath2) {
00348 case mcMTL2_ALGEBRAIC:
00349 res += wxT("algebraic "); break;
00350 case mcMTL2_TRANSCENDENT:
00351 res += wxT("transcendental "); break;
00352 case mcMTL2_NOT_RECOGNIZED:
00353 res += wxT("[not-recognized] "); break;
00354 }
00355
00356 switch (m_tMath3) {
00357 case mcMTL3_CONSTANT:
00358 res += wxT("constant"); break;
00359 case mcMTL3_UNKNOWN:
00360 res += wxT("unknown"); break;
00361 case mcMTL3_PARAMETRIC:
00362 res += wxT("parametric"); break;
00363 case mcMTL3_NOT_RECOGNIZED:
00364 res += wxT("[not-recognized]"); break;
00365 }
00366
00367
00368 if (m_tMath4 & mcMTL4_LOGARITHMIC)
00369 res += wxT("logarithmic");
00370 if (m_tMath4 & mcMTL4_EXPONENTIAL)
00371 res += wxT("exponential");
00372 if (m_tMath4 & mcMTL4_TRIGONOMETRIC)
00373 res += wxT("trigonometric");
00374
00375
00376 if (res.IsEmpty())
00377 res = wxT("[invalid data]");
00378
00379 return res;
00380 }
00381
00382 mcMathType mcMathType::math_MultiplyBy(const mcMathType &t)
00383 {
00384
00385 return math_Add(t);
00386 }
00387
00388 mcMathType mcMathType::math_DivideBy(const mcMathType &t)
00389 {
00390 math_MultiplyBy(t);
00391
00392
00393 if (t.m_tMath3 != mcMTL3_CONSTANT)
00394 m_tMath1 = mcMTL1_RATIONAL;
00395
00396 return *this;
00397 }
00398
00399 mcMathType mcMathType::math_Add(const mcMathType &t)
00400 {
00401 m_tMath1 = mcMIN(m_tMath1, t.m_tMath1);
00402 m_tMath2 = mcMIN(m_tMath2, t.m_tMath2);
00403 m_tMath3 = mcMIN(m_tMath3, t.m_tMath3);
00404
00405 m_tMath4 = m_tMath4 | t.m_tMath4;
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 return *this;
00427 }
00428
00429 mcMathType mcMathType::math_RaiseTo(const mcMathType &t)
00430 {
00431 math_MultiplyBy(t);
00432
00433
00434 if (t.m_tMath3 != mcMTL3_CONSTANT) {
00435 m_tMath2 = mcMTL2_TRANSCENDENT;
00436 m_tMath4 = mcMTL4_EXPONENTIAL;
00437 }
00438
00439 return *this;
00440 }
00441
00442 mcMathType mcMathType::math_ApplyOp(mcElementType optype, const mcMathType &t)
00443 {
00444 if (optype == mcET_ADDOP || optype == mcET_SUBOP)
00445 math_Add(t);
00446 else if (optype == mcET_MULTOP)
00447 math_MultiplyBy(t);
00448 else if (optype == mcET_DIVOP)
00449 math_DivideBy(t);
00450
00451 return *this;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460 wxString mcMathSystemType::io_GetDescString(int nequ) const
00461 {
00462 wxString type;
00463
00464 switch (m_tMath1) {
00465 case mcMSTL1_NOT_RECOGNIZED:
00466 type = wxT("not recognized"); break;
00467 case mcMSTL1_EQUATIONS:
00468 type = wxString::Format(wxT(" %d-equations system"), nequ); break;
00469 case mcMSTL1_INEQUALITIES:
00470 type = wxString::Format(wxT(" %d-inequalities system"), nequ); break;
00471 case mcMSTL1_EXPRESSION:
00472 type += wxT(" expression"); break;
00473 case mcMSTL1_MIXED:
00474 type = wxT(" mixed system"); break;
00475 }
00476
00477 return type;
00478 }
00479
00480 mcMathSystemType mcMathSystemType::math_CombineWith(const mcMathSystemType &t)
00481 {
00482
00483
00484 if (m_tMath1 == mcMSTL1_NOT_RECOGNIZED ||
00485 t.m_tMath1 == mcMSTL1_NOT_RECOGNIZED) {
00486
00487 m_tMath1 = mcMSTL1_NOT_RECOGNIZED;
00488 return *this;
00489 }
00490
00491 if (m_tMath1 != t.m_tMath1)
00492 m_tMath1 = mcMSTL1_MIXED;
00493
00494 return *this;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504 mcRange::~mcRange()
00505 {
00506 }
00507
00508 void mcRange::math_Set(const mcRealValue &l, const mcRealValue &u)
00509 {
00510 if (!u.isNAN()) {
00511
00512
00513
00514 m_pUpper.math_WrapNumber(u);
00515 }
00516 if (!l.isNAN()) {
00517
00518
00519 m_pLower.math_WrapNumber(l);
00520 }
00521 }
00522
00523 void mcRange::math_Set(const mcPolynomial &l, const mcPolynomial &u)
00524 {
00525 if (u != mcEmptyElement) m_pUpper = u;
00526 if (l != mcEmptyElement) m_pLower = l;
00527 }
00528
00529 bool mcRange::math_isFinite() const
00530 {
00531 return m_pUpper.math_isFinite() &
00532 m_pLower.math_isFinite();
00533 }
00534
00535 mcRealValue mcRange::math_GetLowerLimitValue() const
00536 { return m_pLower.math_Evaluate(); }
00537
00538 mcRealValue mcRange::math_GetUpperLimitValue() const
00539 { return m_pUpper.math_Evaluate(); }
00540
00541
00542
00543 #define mcBM_INCLUDE_LCHAR wxT("[")
00544 #define mcBM_INCLUDE_RCHAR wxT("]")
00545
00546 #define mcBM_EXCLUDE_LCHAR wxT("(")
00547 #define mcBM_EXCLUDE_RCHAR wxT(")")
00548
00549
00550 wxString mcRange::io_GetInlinedExpr() const
00551 {
00552 wxString middle = m_pLower.io_GetInlinedExpr() + wxT(";") +
00553 m_pUpper.io_GetInlinedExpr();
00554
00555 switch (m_nBounds) {
00556 case mcBM_INCLUDE_BOTH:
00557 return mcBM_INCLUDE_LCHAR + middle + mcBM_INCLUDE_RCHAR;
00558 case mcBM_INCLUDE_LEFT:
00559 return mcBM_INCLUDE_LCHAR + middle + mcBM_EXCLUDE_RCHAR;
00560 case mcBM_INCLUDE_RIGHT:
00561 return mcBM_EXCLUDE_LCHAR + middle + mcBM_INCLUDE_RCHAR;
00562 case mcBM_INCLUDE_NONE:
00563 return mcBM_EXCLUDE_LCHAR + middle + mcBM_EXCLUDE_RCHAR;
00564 }
00565
00566
00567 return wxEmptyString;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577 bool mcExtRange::math_isFinite() const
00578 {
00579 bool finite = TRUE;
00580 for (int i=0; i < data_GetCount(); i++)
00581 finite &= data_GetRange(i)->math_isFinite();
00582 return finite;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592 mcSymbolProperties::mcSymbolProperties(int symtype,
00593 const wxString &name,
00594 wxFontEncoding encoding,
00595 const mcRealValue &value,
00596 const wxString &inlinedsym,
00597 const wxString &subscript,
00598 mcExtRange *domain,
00599 bool evaluating)
00600 {
00601 m_nSymbolType = symtype;
00602 m_fEncoding = encoding;
00603
00604 m_fValue = value;
00605 m_pDomain = NULL;
00606
00607
00608
00609
00610
00611 m_strSubscript = subscript;
00612 m_strInlinedSymbol = inlinedsym;
00613 m_strSymbol = name;
00614
00615 m_bEvaluating = evaluating;
00616
00617
00618 mcSymbolHelpers *safe = new mcSymbolHelpers;
00619 safe->data_LinkWith(this);
00620 }
00621
00622 mcSymbolProperties::~mcSymbolProperties()
00623 {
00624
00625
00626
00627 for (int i=0,max=(int)m_arrLinkedSymbol.GetCount(); i < max; i++) {
00628
00629 mcSymbolHelpers *p = (mcSymbolHelpers *)m_arrLinkedSymbol.Item(0);
00630
00631
00632
00633 mcASSERT(p != NULL, wxT("We are linked with a NULL symbol ??"));
00634 p->data_Unlink();
00635
00636 if (i == 0) {
00637
00638
00639
00640
00641
00642 delete p;
00643 }
00644 }
00645 }
00646
00647 bool mcSymbolProperties::data_isSameAs(const mcSymbolProperties &s) const
00648 {
00649
00650 if (s.m_strSymbol == m_strSymbol &&
00651 s.m_fEncoding == m_fEncoding &&
00652 s.m_strSubscript == m_strSubscript)
00653 return TRUE;
00654
00655
00656 if (s.io_GetInlinedSym() == io_GetInlinedSym() &&
00657 s.m_strSubscript == m_strSubscript)
00658 return TRUE;
00659
00660
00661
00662 return FALSE;
00663 }
00664
00665 int mcSymbolProperties::math_FindDuplicate(const mcSymbolArray *arr, int occ) const
00666 {
00667 int occurrence = 0;
00668 int n = arr->data_FindSymbol(mcSYMFIND_MATCH_NAME, *this, occurrence);
00669
00670 while (n != mcSYM_NOTFOUND) {
00671
00672 const mcSymbolProperties *found = arr->data_GetSymbol(n);
00673
00674
00675
00676 if (this != found && this->data_isSameAs(*found)) {
00677
00678
00679
00680 if (occ == 0)
00681 return n;
00682 occ--;
00683 }
00684
00685
00686 occurrence++;
00687 n = arr->data_FindSymbol(mcSYMFIND_MATCH_NAME, *this, occurrence);
00688 }
00689
00690 return mcSYM_NOTFOUND;
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700 int mcSymbolArray::data_FindSymbol(long flags, const wxString &name,
00701 wxFontEncoding enc, const mcRealValue &value,
00702 const wxString &subscript, const wxString &inlined,
00703 int occurrence) const
00704 {
00705
00706
00707 mcSymbolProperties tmp(mcSYM_NOTSET, name, enc, value, inlined, subscript);
00708
00709 return data_FindSymbol(flags, tmp, occurrence);
00710 }
00711
00712 int mcSymbolArray::data_FindSymbol(long flags, const mcSymbolProperties &sym, int occ) const
00713 {
00714
00715 for (int i=0; i < data_GetCount(); i++) {
00716
00717 bool match = TRUE;
00718
00719
00720 if (flags & mcSYMFIND_MATCH_NAME) match &= (data_GetSymbolName(i) == sym.m_strSymbol);
00721 if (flags & mcSYMFIND_MATCH_ENCODING) match &= (data_GetEncoding(i) == sym.m_fEncoding);
00722 if (flags & mcSYMFIND_MATCH_VALUE) match &= (math_GetValue(i) == sym.m_fValue);
00723 if (flags & mcSYMFIND_MATCH_INLINED) match &= (io_GetInlinedSymbol(i) == sym.io_GetInlinedSym());
00724 if (flags & mcSYMFIND_MATCH_SUBSCRIPT) match &= (data_GetSubscript(i) == sym.m_strSubscript);
00725
00726 if (match) {
00727 if (occ == 0)
00728 return i;
00729
00730
00731 occ--;
00732 }
00733 }
00734
00735
00736 return mcSYM_NOTFOUND;
00737 }
00738
00739 mcSymbolProperties *mcSymbolArray::data_AddSymbol(bool bRemovePrevious,
00740 const wxString &name,
00741 wxFontEncoding enc,
00742 const mcRealValue &value,
00743 const wxString &inlinedsym,
00744 const wxString &sub,
00745 mcExtRange *domain)
00746 {
00747 mcSymbolProperties sym(m_nSymbolArray, name, enc, value, inlinedsym, sub, domain);
00748
00749
00750 if (!data_AddSymbol(sym, bRemovePrevious))
00751 return NULL;
00752
00753
00754 return data_GetSymbol(data_GetCount()-1);
00755 }
00756
00757 bool mcSymbolArray::data_AddSymbol(const mcSymbolProperties &newsym, bool bRemovePrevious)
00758 {
00759 bool bpresent = FALSE;
00760 int i, n;
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 for (i=0; i < mcMAX_SYMBOL_ARRAY_NUM; i++) {
00774 if (m_pArr[i] == NULL) continue;
00775
00776 n = newsym.math_FindDuplicate(m_pArr[i], 0);
00777 if (n != mcSYM_NOTFOUND) bpresent = TRUE;
00778 }
00779
00780 if (bpresent && !bRemovePrevious)
00781 return FALSE;
00782
00783
00784
00785 mcSymbolProperties *added = newsym.data_Clone();
00786 added->m_nSymbolType = m_nSymbolArray;
00787 mcAbstractArray::data_Add(added);
00788
00789
00790
00791
00792
00793
00794
00795 if (!bpresent) {
00796
00797
00798 if (m_pAddSymbolCallback)
00799 (*m_pAddSymbolCallback)();
00800 return TRUE;
00801 }
00802
00803
00804
00805
00806 for (i=0; i < mcMAX_SYMBOL_ARRAY_NUM; i++) {
00807 if (m_pArr[i] == NULL) continue;
00808
00809
00810 n = newsym.math_FindDuplicate(m_pArr[i], 0);
00811
00812
00813 if (n != mcSYM_NOTFOUND) {
00814
00815 mcSymbolProperties *torem = (mcSymbolProperties *)m_pArr[i]->data_GetSymbol(n);
00816 if (torem == added) {
00817 n = newsym.math_FindDuplicate(m_pArr[i], 1);
00818 if (n == mcSYM_NOTFOUND) continue;
00819 }
00820
00821 mcASSERT(torem != added, wxT("math_FindDuplicate is broken"));
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 int j, max;
00836 for (j=1,max=torem->data_GetLinkedSymCount(); j < max; j++) {
00837
00838
00839
00840 mcSymbolHelpers *toupdate = torem->data_GetLinkedSym(1);
00841 toupdate->data_Unlink();
00842
00843
00844
00845
00846 toupdate->data_LinkWith(added);
00847 }
00848
00849 mcASSERT(max >= 1, wxT("The symbol to remove did not have a safe instance ")
00850 wxT("of a mcSymbolHelpers class ?"));
00851
00852
00853 m_pArr[i]->data_RemoveAt(n);
00854 }
00855 }
00856
00857
00858 if (m_pAddSymbolCallback) (*m_pAddSymbolCallback)();
00859 return TRUE;
00860 }
00861
00862 mcSymbolProperties *mcSymbolArray::data_MoveSymbols(int i, mcSymbolArray *parr)
00863 {
00864
00865
00866 mcSymbolProperties *p = data_GetSymbol(i)->data_Clone();
00867 bool okay = parr->data_AddSymbol(*p, TRUE);
00868 mcSAFE_DELETE(p);
00869
00870
00871 if (!okay) return NULL;
00872 return parr->data_GetSymbol(parr->data_GetCount()-1);
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 void mcCursorPos::gui_Pop()
00886 {
00887 for (int i=0; i<m_nUsed-1; i++)
00888 m_nPos[i] = m_nPos[i+1];
00889 if (!isSpecial(m_nPos[m_nUsed-1])) {
00890 m_nPos[m_nUsed-1] = m_nPos[m_nUsed];
00891 m_nUsed--;
00892 }
00893 }
00894
00895 void mcCursorPos::gui_Push(const mcCursorPos &c)
00896 {
00897
00898
00899
00900
00901
00902 }