/* * MathPlanner 3.1 - Mathematical design tool. * Copyright(C) 2002 Jarmo Nikkanen * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation. * * You should have received a copy of the GNU General Public License with this program. * */ #include "Memory.h" #include "Datastore.h" #include "Error.h" #include "Function_object.h" #include "Object_string.h" #include "Datasymbol.h" #include "Operators.h" #include "ConfigReader.h" #include "AppControl.h" #include "DragDrop.h" #include #include #include void string_object::ChangeIndex(int ch) { index+=ch; IndexChk(); } void string_object::IndexChk() { int last=FindLast(sub); overlimits=false; if (index<0) index=0,overlimits=true; // overlimits are used in data input only if (index>last && last>=0) index=last; } bool string_object::IsLastObject(class m_base_object *obj) { if (obj==ObjectAt(FindLast(sub))) return(true); return(false); } int string_object::ObjectTypeAt(int i) { if (i<0 || i>=string_size) return(-1); return(sub[i%string_size].Type); } m_base_object *string_object::ObjectAt(int i) { if (i<0 || i>=string_size) ErrorReport("str:ObjectAt","out of renge"); return(sub[i%string_size].Object); } void string_object::SetInsertMode(int i) { InsertMode=i; } void string_object::SetRequired(bool i) { required=i; } layout_rect string_object::Bounds() { return(bounds); } void string_object::UnFocusAll() { Focused_object=NULL; } void string_object::FocusObject(m_base_object *no) { Focused_object=no; } m_base_object *string_object::GetFocus() { if (HasFocus()) return(Focused_object); return(NULL); } bool string_object::HasFocus() { if (function) { if (function->GetFocus()==this) return(true); } return(false); } void string_object::SetFocus() { if (function) function->FocusString(this); DataStorage *msg=MESSAGE(MSG_STATUS); msg->AddInt("size",GetFontSize()); PostMessage(msg,TO_MATHCONTROL); } // ********************************************************** void string_object::SendCall(int call) { int i; // Process Calls First if (call==CALL_MODIFY) build_flag=false; if (call==CALL_SYNTAXCHK) SyntaxChk(); for(i=0;iSendCall(call); } } } m_base_object *string_object::GetLeftSideObject(class m_base_object *obj) { int i; for(i=0;i0) if (pre[i-1].Object) return(pre[i-1].Object); else return(NULL); else return(NULL); } } return(NULL); } m_base_object *string_object::GetRightSideObject(class m_base_object *obj) { int i; for(i=0;i<(string_size-1);i++) { if (pre[i].Object==obj) { if (pre[i+1].Object) { return(pre[i+1].Object); } else return(NULL); } } return(NULL); } bool string_object::IsEmpty() { if (sub) { if (sub[0].Object!=NULL) return(false); } return(true); } QFont string_object::GetFont(int type) { int ty; if (type==FONT_TYPE_EXPONENT) ty=FONT_TYPE_NORMAL; else ty=type; QFont font=AppControl->GetFont(ty); if (type==FONT_TYPE_INDEX && fontsize==FONT_SIZE_NORMAL) font.setPointSize(AppControl->GetFontSize(FONT_SIZE_INDEX)); else if (type==FONT_TYPE_INDEX && fontsize==FONT_SIZE_SMALL) font.setPointSize(AppControl->GetFontSize(FONT_SIZE_INDEX_SMALL)); if (type==FONT_TYPE_INDEX) return(font); if (type==FONT_TYPE_EXPONENT && fontsize==FONT_SIZE_NORMAL) font.setPointSize(AppControl->GetFontSize(FONT_SIZE_SMALL)); else if (type==FONT_TYPE_EXPONENT && fontsize==FONT_SIZE_SMALL) font.setPointSize(AppControl->GetFontSize(FONT_SIZE_EXPONENT_SMALL)); if (type==FONT_TYPE_EXPONENT) return(font); font.setPointSize(AppControl->GetFontSize(fontsize)); return(font); } int string_object::GetFontSize(int id) { if (id!=(-1)) { if (id==FONT_TYPE_EXPONENT && fontsize==FONT_SIZE_NORMAL) return(FONT_SIZE_SMALL); if (id==FONT_TYPE_EXPONENT && fontsize==FONT_SIZE_SMALL) return(FONT_SIZE_EXPONENT_SMALL); } return(fontsize); } void string_object::SetFontSize(int id) { fontsize=id; int i,l=FindLast(sub); for(i=0;i<=l;i++) if (sub[i%string_size].Object) sub[i%string_size].Object->SetFontSize(id); } string_object::string_object(DataStorage *msg,ApplicationControl *Aplc,m_function_object *func) { int i; int bytes; DataStorage *ar; class m_base_object *obj; int siz; char *su,*sub_p; char name[40]; Reset(); Bug("START STRING CONSTRUCTOR"); AppControl=Aplc; function=func; margin=Aplc->Prefs->Int("String_margin"); spacing=Aplc->Prefs->Int("String_spacing"); fontsize=FONT_SIZE_NORMAL; list_size=msg->ReadInt("str:LS"); string_size=msg->ReadInt("str:SS"); fontsize=msg->ReadInt("str:FS"); AllocateListSpace(list_size+1); // New List Size is set AllocateStringSpace(string_size+1); // New String Size is set ResetTables(); required=msg->ReadInt("str:r"); if (msg->Contains("str:Str")) { msg->ReadData("str:Str",(void **)&su,&bytes); } else ErrorReport("String Constructor","No Str Data"); sub_p=(char *)sub; for(i=0;iContains(name)) { ar=new DataStorage(); msg->ReadDataStorage(name,ar); ar->AddPointer("function",(void *)function); ar->AddPointer("string",(void *)this); ar->AddPointer("appcontrol",(void *)AppControl); obj=(class m_base_object *)ConstructNewObject(ar); list[i].Object=obj; list[i].Type=obj->Type; list[i].MainType=obj->MainType; list[i].Delete=false; delete ar; } } } // NOTE String Must Be Corected.. There is illegal object pointer -> replace it with new one if (list && sub) { for(i=0;iReadInt("Object"); if (ty==OT_INTEGER_OBJECT) return(new integer_object(msg)); if (ty==OT_VALUE_OBJECT) return(new value_object(msg)); // Symbol Object Types if (ty==OT_SYMBOL_OBJECT) return(new symbol_object(msg)); if (ty==OT_ASSIGN_OBJECT) return(new symbol_object(msg)); if (ty==OT_PLUS_OBJECT) return(new symbol_object(msg)); if (ty==OT_MINUS_OBJECT) return(new symbol_object(msg)); if (ty==OT_MULTIBLY_OBJECT) return(new symbol_object(msg)); if (ty==OT_INLINE_DIVE_OBJECT) return(new symbol_object(msg)); if (ty==OT_CROSS_OBJECT) return(new symbol_object(msg)); if (ty==OT_CONJUGANT_OBJECT) return(new symbol_object(msg)); if (ty==OT_FACTORIAL_OBJECT) return(new symbol_object(msg)); // Other objects if (ty==OT_IMAGINARY_OBJECT) return(new imaginary_object(msg)); if (ty==OT_DIVE_OBJECT) return(new dive_object(msg)); if (ty==OT_TRIGONO_OBJECT) return(new trigono_object(msg)); if (ty==OT_EXPONENT_OBJECT) return(new exp_object(msg)); if (ty==OT_PARENTHESIS_OBJECT) return(new par_object(msg)); if (ty==OT_COMPLEX_OBJECT) return(new complex_object(msg)); if (ty==OT_MINMAX_OBJECT) return(new minmax_object(msg)); if (ty==OT_SQRT_OBJECT) return(new sqrt_object(msg)); if (ty==OT_SIGMA_OBJECT) return(new sigma_object(msg)); if (ty==OT_FUNCTION_DEFINATION_OBJECT) return(new function_defination_object(msg)); if (ty==OT_FUNCTION_HEADER_OBJECT) return(new function_header_object(msg)); if (ty==OT_UNIT_OBJECT) return(new unit_object(msg)); if (ty==OT_MATRIX_OBJECT) return(new matrix_object(msg)); ErrorReport("ConstructNewObject()","This version of MathPlanner can not load this"); return(NULL); } DataStorage *string_object::BuildStorage() { int i,k,last,count; DataStorage *ar,*msg; char name[40]; msg=new DataStorage(); count=0; if (list) { for (i=0;iBuildStorage(); msg->AddDataStorage(name,ar,false); delete ar; count++; } } } last=1; if (sub) last=FindLast(sub)+1; if (sub) msg->AddData("str:Str",(void *)sub,last*sizeof(index_obj)); msg->AddInt("str:SS",last); msg->AddInt("str:LS",count); msg->AddInt("str:r",required); msg->AddInt("str:FS",fontsize); return(msg); } // ************************************************* void string_object::AllocateStringSpace(int no) { int i; int size=(no+1)*3*sizeof(index_obj); char *p=(char *)malloc(size); if (p) { index_obj* n_sub=(index_obj *)p; index_obj* n_pre=(index_obj *)(p+no*sizeof(index_obj)); index_obj* n_mid=(index_obj *)(p+2*no*sizeof(index_obj)); for(i=0;iPrefs->Int("String_margin"); spacing=Aplc->Prefs->Int("String_spacing"); fontsize=FONT_SIZE_NORMAL; AllocateStringSpace(no); // List & subs must be NULL AllocateListSpace(no); ResetTables(); function=f; AppControl=Aplc; // Check that everything is OK if (sub==NULL || pre==NULL || list==NULL) ErrorReport("string::Constructor","Allocation error"); if (AppControl==NULL || function==NULL) ErrorReport("string::Constructor","Inportant class is NULL"); } string_object::~string_object() { // must delete chield objects FIRST if (function) { function->RemoveString(this); } int i; for(i=0;iCalculateBounds(); wi+=ob->bounds.width; a=ob->bounds.ascent; d=ob->bounds.descent; if (a>as) as=a; if (d>de) de=d; count++; } } if (as==0 && de==0) { QFontMetrics met(GetFont(FONT_TYPE_NORMAL)); as=met.ascent(); de=met.descent(); wi=(as+de)/2; } if (count>1) wi+=(count-1)*spacing; bounds.ascent=as+margin; bounds.descent=de+margin; bounds.width=wi+(2*margin); } void string_object::MoveTo(QPoint point) { m_base_object *ob; int i; int x,y; bounds.SetPosition(point); x=bounds.x+margin; y=bounds.y; for(i=0;iMoveTo(QPoint(x,y)); x+=ob->bounds.width+spacing; } } } void string_object::DrawRQ() { if (function) function->DrawRQ(); } void string_object::Draw(QPainter *paint) { index_obj in; QRect bo; int i; bool pf; // If some object inside this string is focused... focuse string if (function->HasFocus()) { if (IsEmpty() && HasFocus()==false) { if (required==true) paint->setPen(QPen(QColor(200,0,0),0,Qt::DashLine)); else paint->setPen(QPen(QColor(235,235,0),0,Qt::DashLine)); paint->drawRect(bounds.Rect()); } if (HasFocus()) { paint->setPen(QPen(QColor(0,200,0),0,Qt::DashDotDotLine)); paint->drawRect(bounds.Rect()); } } // function focus pf=false; if (parent) pf=parent->HasFocus(); if (Error_flag && (HasFocus()==false && pf==false)) { paint->setPen(QPen(QColor(255,0,0),0,Qt::SolidLine)); paint->drawRect(bounds.Rect()); } for(i=0;iDraw(paint); } } if (multible) { if (sub[selection.start%string_size].Object) bo=sub[selection.start%string_size].Object->bounds.Rect(); for(i=selection.start+1;i<=selection.end;i++) { in=sub[i%string_size]; if (in.Object) bo=bo|in.Object->bounds.Rect(); } if (function->HasFocus() && HasFocus()) { paint->setPen(QPen(QColor(0,0,255),0,Qt::DashLine)); paint->drawRect(bo); } } } // String Analyzis ******************************************************************** void string_object::FindRanges(int ot,str_range r,str_range *rl,int *no) { int i,st,ri,s=r.start,e=r.end; if (s==e) { *no=0; return; } else if (ot==PRIORITY_POWER) { // Operator will effect only one object on left side rl[0].start=s; rl[0].end=e; *no=1; return; } else if (ot==PRIORITY_TRIGONO) { // Special Case if (e>s) for(i=s;i<=(e-1);i++) { if (pre[i].Priority==ot && pre[i+1].Priority!=ot) { rl[0].start=i+1; rl[0].end=e; *no=1; return; } } *no=0; return; } st=s; ri=0; for(i=s;i<=e;i++) { // This case is used with +,-,*,/ operations if (pre[i].Priority==ot) { if (i>r.start) { rl[ri].start=st; rl[ri++].end=i-1; } st=i+1; if (ri>=RANGE_LIST_SIZE) ErrorReport("FindRanges()","Out Of Index Space Critical Error"); } } if (st<=e) { rl[ri].start=st; rl[ri++].end=e; } *no=ri; } void string_object::CheckErrors(str_range r) { int i,j,A,B,AA,BB,SA,SB; class m_base_object *BO,*AO; QString err=QObject::tr("Syntax error"); SA=0; AO=NULL; SB=0; BO=NULL; if(r.start>=string_size || r.start<0) ErrorReport("PreProcess","Range start"); if(r.end>=string_size || r.end<0) ErrorReport("PreProcess","Range start"); if (IsEmpty()) { NBug(1,"Err: Empty"); AppControl->AddError(err); Error_flag=true; return; } bool main=function->IsMainString(this); if (r.start==r.end) { A=sub[0].Type; if (sub[0].Object) AO=sub[0].Object,SA=AO->SubObject; if (A==OT_PLUS_OBJECT) { NBug(1,"Err: 1a"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (A==OT_MULTIBLY_OBJECT) { NBug(1,"Err: 1b"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (A==OT_INLINE_DIVE_OBJECT) { NBug(1,"Err: 1c"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (A==OT_FUNCTION_DEFINATION_OBJECT && !main) { NBug(1,"Err: xx"); AppControl->AddError(QObject::tr("Syntax error - Can not define function in here")); if (AO) AO->Error_flag=true; else Error_flag=true; return; } return; } for(i=r.start;iSubObject; SB=0; BO=NULL; if (sub[j].Object) BO=sub[j].Object,SB=BO->SubObject; AA=sub[i].MainType; BB=sub[j].MainType; if (A==OT_FUNCTION_DEFINATION_OBJECT) { NBug(1,"Err: yy"); AppControl->AddError(QObject::tr("Syntax error - Illegal function defination")); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (i==0) { // if the first object is : if (A==OT_PLUS_OBJECT) { NBug(1,"Err: 2a"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (A==OT_MULTIBLY_OBJECT) { NBug(1,"Err: 2b"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (A==OT_INLINE_DIVE_OBJECT) { NBug(1,"Err: 2c"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } } if (A==OT_PLUS_OBJECT) { if (B==OT_PLUS_OBJECT) { NBug(1,"Err: 3a"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_MULTIBLY_OBJECT) { NBug(1,"Err: 3b"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_INLINE_DIVE_OBJECT) { NBug(1,"Err: 3c"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } } if (A==OT_MINUS_OBJECT) { if (B==OT_PLUS_OBJECT) { NBug(1,"Err: 4a"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_MULTIBLY_OBJECT) { NBug(1,"Err: 4b"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_INLINE_DIVE_OBJECT) { NBug(1,"Err: 4c"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } } if (A==OT_MULTIBLY_OBJECT) { if (B==OT_PLUS_OBJECT) { NBug(1,"Err: 5a"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_MULTIBLY_OBJECT) { NBug(1,"Err: 5b"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_INLINE_DIVE_OBJECT) { NBug(1,"Err: 5c"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } } if (A==OT_INLINE_DIVE_OBJECT) { if (B==OT_PLUS_OBJECT) { NBug(1,"Err: 6a"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_MULTIBLY_OBJECT) { NBug(1,"Err: 6b"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } if (B==OT_INLINE_DIVE_OBJECT) { NBug(1,"Err: 6c"); AppControl->AddError(err); if (AO) AO->Error_flag=true; else Error_flag=true; return; } } if (SA==SUB_RIGHT) { // no string operator after sub_right if (SB==SUB_LEFT) { NBug(1,"Err: 7"); AppControl->AddError(err); if (AO && BO) AO->Error_flag=BO->Error_flag=true; else Error_flag=true; return; } } if (SB==SUB_LEFT) { // no string operator after sub_right if (AA==OMT_STRING_OPERATOR) { NBug(1,"Err: 8"); AppControl->AddError(err); if (BO) BO->Error_flag=true; else Error_flag=true; return; } if (SA==SUB_RIGHT) { NBug(1,"Err: 9"); AppControl->AddError(err); if (AO && BO) AO->Error_flag=BO->Error_flag=true; else Error_flag=true; return; } } } } //*************************************** // FindLast // // Input: Object string sub or pre // Return: Last object in string // Or -1 if empty string //*************************************** int string_object::FindLast(index_obj *st) { int i; for(i=0;iBuild(); // Call Build for every object if (x.Type==OT_MINUS_OBJECT) { if (i>0) { y=sub[i-1]; if (y.MainType==OMT_STRING_OPERATOR) { // Minus after "+-*/" operator x.Priority=PRIORITY_TRIGONO; // This is negation -> Set to higher priority } if (y.Priority==PRIORITY_TRIGONO) { // Minus after trigono object x.Priority=PRIORITY_TRIGONO; // This is negation -> Set to higher priority } } else x.Priority=PRIORITY_TRIGONO; // Fisrt obj in line-> This is negation "-" Set to higher priority } mid[i]=x; } } // Process 2x -> 2*x, 2sqrt -> 2*sqrt low.Object=NULL; // These objects are not visual low.Type=OT_MULTIBLY_OBJECT; low.Sub=0; low.Priority=PRIORITY_MUL_LOW; low.MainType=OMT_STRING_OPERATOR; low.Index=(-1); high.Object=NULL; high.Type=OT_MULTIBLY_OBJECT; high.Sub=0; high.Priority=PRIORITY_MUL_HIGH; high.MainType=OMT_STRING_OPERATOR; high.Index=(-1); j=0; for(i=range.start;i<=range.end;i++) { a=mid[i].MainType; if (irange.start) p=mid[i-1].MainType; else p=0; AddToPre(mid[i],j); j++; if (a==OMT_DATA && b==OMT_DATA) AddToPre(high,j), j++; else if (a==OMT_DATA && b==OMT_OPERATOR && s!=SUB_LEFT) AddToPre(low,j), j++; else if (b==OMT_DATA && a==OMT_OPERATOR && mid[i].Priority==PRIORITY_POWER && p==OMT_DATA) AddToPre(high,j), j++; else if (b==OMT_DATA && a==OMT_OPERATOR && mid[i].Sub!=SUB_RIGHT) AddToPre(low,j), j++; else if (b==OMT_OPERATOR && a==OMT_OPERATOR && mid[i].Sub!=SUB_RIGHT && s!=SUB_LEFT) AddToPre(low,j), j++; // ok } // Clear Last entry Clear(pre,j); } math_node string_object::CalculateRange(str_range range) { bool go; int ot; int count; int i,x,s,e,k,n,type=0; math_node val,va; str_range ran; str_range range_list[RANGE_LIST_SIZE]; m_base_object *ob=NULL; #ifdef BUG_REPORT NBug(2,"Range Data :"); BugRange(range,pre); #endif ot=0; x=range.end; for(i=range.start;i<=x;i++) ot|=pre[i%string_size].Priority; if (ot&PRIORITY_ASSIGN) ot=PRIORITY_ASSIGN; else if (ot&PRIORITY_PLUS) ot=PRIORITY_PLUS; else if (ot&PRIORITY_MULTIBLY) ot=PRIORITY_MULTIBLY; else if (ot&PRIORITY_MUL_LOW) ot=PRIORITY_MUL_LOW; else if (ot&PRIORITY_TRIGONO) ot=PRIORITY_TRIGONO; else if (ot&PRIORITY_MUL_HIGH) ot=PRIORITY_MUL_HIGH; else if (ot&PRIORITY_POWER) ot=PRIORITY_POWER; if (ot) { // ************************************************* // Assing Processing // ************************************************* if (ot==PRIORITY_ASSIGN) { FindRanges(ot,range,range_list,&count); k=0; // clear count of assignments for(i=0;iType==OT_INTEGER_OBJECT) assign_list[k++]=ob; val=ob->Calculate(); } } else val=CalculateRange(ran); } // for loop ends while (k>0) { assign_list[k-1]->SetValue(val); k--; } return(val); } // section ends // ************************************************* // Plus & Minus Processing // ************************************************* if (ot==PRIORITY_PLUS) { FindRanges(ot,range,range_list,&count); for(i=0;iCalculate(); } else va=CalculateRange(ran); if (s>0) type=pre[s-1].Type; if (i==0) val=va; else if (type==OT_MINUS_OBJECT) val=mpl_sub(val,va); else if (type==OT_PLUS_OBJECT) val=mpl_add(val,va); } return(val); } // ************************************************* // Mul, Dive Processing // ************************************************* if (ot==PRIORITY_MULTIBLY || ot==PRIORITY_MUL_LOW || ot==PRIORITY_MUL_HIGH) { FindRanges(ot,range,range_list,&count); for(i=0;iCalculate(); } else va=CalculateRange(ran); if (s>0) type=pre[s-1].Type; if (i==0) val=va; else if (type==OT_MULTIBLY_OBJECT) val=mpl_mul(val,va); else if (type==OT_INLINE_DIVE_OBJECT) val=mpl_div(val,va); else if (type==OT_CROSS_OBJECT) val=mpl_cross(val.Vector(),va.Vector()); } return(val); } // ************************************************* // Log, Sin... Negation... Processing // ************************************************* if (ot==PRIORITY_TRIGONO) { FindRanges(ot,range,range_list,&count); if (count) { ran=range_list[0]; // Only one range s=ran.start; if (s==ran.end) { // Single symbol ob=pre[s].Object; if (ob) val=ob->Calculate(); } else val=CalculateRange(ran); go=true; s--; while (go && s>=0) { if (pre[s].Priority==PRIORITY_TRIGONO) { // There may be another minus with lower priority type=pre[s].Type; if (type==OT_MINUS_OBJECT) val=mpl_neg(val); else if (type==OT_TRIGONO_OBJECT) val=pre[s].Object->Calculate(val); else go=false; } else go=false; s--; } } return(val); } // ************************************************* // Power.... Processing // ************************************************* if (ot==PRIORITY_POWER) { FindRanges(ot,range,range_list,&count); if (count) { e=range_list[0].end; s=range_list[0].start; if (e>s) { ob=pre[s].Object; if (ob) val=ob->Calculate(); n=s+1; while(n<=e) { if (pre[n].Object) { type=pre[n].Type; if (type==OT_EXPONENT_OBJECT) val=pre[e].Object->Calculate(val); else if (type==OT_CONJUGANT_OBJECT) val=mpl_ckunjugant(val.Complex()); else if (type==OT_FACTORIAL_OBJECT) val=mpl_factorial(val.Real()); } n++; } } } return(val); } // section ends } // if (ot) else { // (Only One object in this string) With out priority setting if (pre[0].Object) val=pre[0].Object->Calculate(); } return(val); } bool string_object::RequiresParenthesis(str_range ran) { int i,ot=0; for(i=ran.start;i<=ran.end;i++) ot|=pre[i%string_size].Priority; if (ot&PRIORITY_PLUS) return(true); else if (ot&PRIORITY_MULTIBLY) return(true); else if (ot&PRIORITY_MUL_LOW) return(true); return(false); } // Check if there is any error_flags assigned bool string_object::HasErrors() { int i; if (Error_flag==true) return(true); for(i=0;iError_flag==true) return(true); } return(false); } void string_object::ResetErrorFlags() { int i; for(i=0;iError_flag=false; } Error_flag=false; } void string_object::SyntaxChk() { int i,k; str_range ran; // Add multibly mark betveen two numbers for(i=0;i<(string_size-1);i++) { if (sub[i].Type==OT_VALUE_OBJECT && sub[i+1].Type==OT_VALUE_OBJECT) { k=index; index=i; SetStringOperator(OT_MULTIBLY_OBJECT,MODE_ADD_RIGHT); index=k; function->SetModify(); } } for(i=0;i<(string_size-1);i++) { if (sub[i].Type==OT_DIVE_OBJECT && sub[i+1].Type==OT_EXPONENT_OBJECT) { if (sub[i+1].Sub==SUB_LEFT) { ran.start=ran.end=i; SetParenthesis(ran); function->SetModify(); } } } } void string_object::Build() { NBug(2,"----- String Build Called -----"); int i; ResetErrorFlags(); for(i=0;iSetFocus(); return; } if (sub[0].Object) { sub[0].Object->SetFocus(); return; } } selection.start=selection.end=index; } void string_object::SeekObject(QPoint p) { int i; bool ob=false; SyntaxChk(); for(i=0;ibounds.Rect().contains(p)) { list[i].Object->SeekObject(p); ob=true; break; } } } if (ob==false) SetFocus(); } bool string_object::SelectObject(class m_base_object *obj) { int i; multible=false; for(i=0;iType; list[i].MainType=obj->MainType; list[i].Delete=false; return(i); } } AllocateListSpace(list_size+10); // ALLOCATE MORE SPACE for(i=0;i<(list_size-2);i++) { // TRY TO ADD AGAIN if (list[i].Object==NULL) { list[i].Object=obj; list[i].Type=obj->Type; list[i].MainType=obj->MainType; list[i].Delete=false; return(i); } } return(-1); } void string_object::MarkForDeletion(int in) { int i; if (list && sub) { i=sub[in].Index; if (i>=0 && i(string_size-2)) AllocateStringSpace(string_size+5); sub[pos]=data; } void string_object::AddToPre(index_obj data,int pos) { if (pos>(string_size-2)) AllocateStringSpace(string_size+5); pre[pos]=data; } void string_object::WriteToString(index_obj data,int mode) { int i,in; if (mode==MODE_ADD_LEFT || overlimits) in=index-1; else in=index; for(i=FindLast(sub);i>in;i--) AddToSub(sub[i],i+1); if (sub[0].Type==0) sub[0]=data; else AddToSub(data,in+1); overlimits=false; } void string_object::RemoveFromString(int in) { int i; for(i=in;i<(string_size-1);i++) sub[i]=sub[i+1]; Clear(sub,string_size-1); } void string_object::RemoveFromList(m_base_object *o) { if (o) ClearListIndex(FindIndex(o)); else ErrorReport("so: RemoveFromList","NULL"); } void string_object::Cut(str_range ran,bool del) { int i,s; s=ran.end-ran.start; if (ran.end>=string_size) ErrorReport("string_object::Cut()","Range is too large"); for(i=ran.start;i<=ran.end;i++) { if (del) MarkForDeletion(i); RemoveFromList(sub[i].Object); } for(i=ran.start;i<(string_size-1-s);i++) AddToSub(sub[i+s+1],i); for(i=string_size-1-s;i0) { if (sub[in].Object) selection.start--,multible=true; } } } else { if (key.code==Qt::Key_Up || key.code==Qt::Key_Home) if (parent) parent->SetFocus(); if (key.code==Qt::Key_Tab && parent) parent->FocusNextObject(); if (key.code==Qt::Key_Right) { in=index+1; if (index<=FindLast(sub)) { if (sub[in].Object) { ChangeIndex(1); sub[in].Object->SetFocus(); // Focus string and object } else if ((ob=sub[index].Object)) InsertMode=MODE_ADD_RIGHT; } } if (key.code==Qt::Key_Left) { in=index-1; if (in>=0) { if (sub[in].Object) { ChangeIndex(-1); sub[in].Object->SetFocus(); } else if ((ob=sub[index].Object)) InsertMode=MODE_ADD_LEFT; } else if ((ob=sub[index].Object)) InsertMode=MODE_ADD_LEFT; } if (key.code!=Qt::Key_Shift) { multible=false; selection.start=selection.end=index; } } //else if (multible) UnFocusAll(); } index_obj string_object::CreateObjectEntry(m_base_object *obj) { index_obj data; if (obj) { data.Object=obj; data.Index=AddObject(obj); data.Type=obj->Type; data.MainType=obj->MainType; data.Sub=obj->SubObject; data.Priority=obj->Priority; return(data); } data.Object=NULL; data.Index=-1; data.Type=99; data.MainType=0; data.Sub=0; data.Priority=0; return(data); } void string_object::ObjectInput(m_base_object *o,int left) { WriteToString(CreateObjectEntry(o),left); } void string_object::SetStringOperator(int ty,int side) { index_obj data; symbol_object *sym=NULL; int pri=0; int type=OMT_STRING_OPERATOR; int suo=SUB_NONE; if (ty==OT_ASSIGN_OBJECT) { sym=new symbol_object(QString("="),ty,AppControl,function,this); pri=PRIORITY_ASSIGN; } if (ty==OT_PLUS_OBJECT) { sym=new symbol_object(QString("+"),ty,AppControl,function,this); pri=PRIORITY_PLUS; } if (ty==OT_MINUS_OBJECT) { sym=new symbol_object(QString("-"),ty,AppControl,function,this); pri=PRIORITY_PLUS; } if (ty==OT_INLINE_DIVE_OBJECT) { sym=new symbol_object(QString("/"),ty,AppControl,function,this); pri=PRIORITY_MULTIBLY; } if (ty==OT_CROSS_OBJECT) { sym=new symbol_object(QString("×"),ty,AppControl,function,this); pri=PRIORITY_MULTIBLY; } if (ty==OT_CONJUGANT_OBJECT) { sym=new symbol_object(QString("*"),ty,AppControl,function,this); pri=PRIORITY_POWER; type=OMT_OPERATOR; suo=SUB_LEFT; } if (ty==OT_FACTORIAL_OBJECT) { sym=new symbol_object(QString("!"),ty,AppControl,function,this); pri=PRIORITY_POWER; type=OMT_OPERATOR; suo=SUB_LEFT; } if (ty==OT_MULTIBLY_OBJECT) { sym=new symbol_object(QString("_PLOT"),ty,AppControl,function,this); pri=PRIORITY_MULTIBLY; } sym->Type=ty; sym->Priority=pri; sym->MainType=type; sym->SubObject=suo; data=CreateObjectEntry(sym); WriteToString(data,side); sym->SetFocus(); SelectObject(sym); selection.start=selection.end=index; multible=false; } void string_object::SetParenthesis(str_range ran) { m_base_object *par=new par_object(0,AppControl,function,this); index_obj data=CreateObjectEntry(par); par->InsertString(ran,this); index=ran.start; WriteToString(data,MODE_ADD_LEFT); } void string_object::SetBaseObject(class m_base_object *obj,int side) { index_obj data; bool spec=false; // This is a special scase if (obj->Type==OT_EXPONENT_OBJECT && obj->SubObject==SUB_LEFT) spec=true; data=CreateObjectEntry(obj); if (multible) { if (!spec) { obj->InsertString(selection,this); index=selection.start; WriteToString(data,MODE_ADD_LEFT); if (HasFocus()) obj->Init(); } else { obj->InsertString(selection,this); WriteToString(data); } } else { // No Selection if (side==MODE_ADD_LEFT || side==MODE_ADD_RIGHT) { WriteToString(data,side); if (HasFocus()) obj->Init(); SelectObject(obj); } if (side==MODE_INSERT) { selection.start=selection.end=index; obj->InsertString(selection,this); index=selection.start; if (!spec) WriteToString(data,MODE_ADD_LEFT); else WriteToString(data); if (HasFocus()) obj->Init(); } } selection.start=selection.end=index; multible=false; } void string_object::AutoOperations() { m_base_object *ob; int i; for(i=0;iAutoDeletion()) { // Auto Deletion MarkForDeletion(i); RemoveFromString(i); if (index>=i) ChangeIndex(-1); FocusObject(); } } } } void string_object::ResetSelection() { m_base_object *ob=sub[index].Object; if (ob) { SelectObject(ob); ob->SetFocus(); } else ErrorReport("so: ResetSelection","NULL"); } void string_object::KeyReceived(key_code key) { int ch=key.code; int insert=key.insert_mode; IndexChk(); // never pass auto_mode to objects if (insert==MODE_AUTO) insert=InsertMode; if (insert==MODE_AUTO) insert=MODE_ADD_RIGHT; if (key.number==false && key.integer==false && key.oper==false) { // EDIT if (key.code==Qt::Key_Delete) { if (!multible) { MarkForDeletion(index); RemoveFromString(index); ChangeIndex(-1); FocusObject(); } else { Cut(selection,true); FocusObject(); } } else // insert mode can be set always if (key.code==Qt::Key_Insert) InsertMode=MODE_INSERT; else MoveCursor(key); } if (key.number==true) { // VALUE value_object *i=new value_object(key.unicode,AppControl,function,this); if (insert==MODE_ADD_LEFT) ObjectInput(i,MODE_ADD_LEFT); else ObjectInput(i); i->SetFocus(); selection.start=selection.end=index; multible=false; } if (key.integer==true) { // INTEGER integer_object *i=new integer_object(key.unicode,AppControl,function,this); if (insert==MODE_ADD_LEFT) ObjectInput(i,MODE_ADD_LEFT); else ObjectInput(i); i->SetFocus(); selection.start=selection.end=index; multible=false; } if (key.oper==true || key.spec==true) { // OPERATOR // Special Inline Operators if (ch=='=') SetStringOperator(OT_ASSIGN_OBJECT,insert); if (ch=='+') SetStringOperator(OT_PLUS_OBJECT,insert); if (ch=='-') SetStringOperator(OT_MINUS_OBJECT,insert); if (ch=='*') SetStringOperator(OT_MULTIBLY_OBJECT,insert); if (ch=='/' && !multible && InsertMode!=MODE_INSERT) SetStringOperator(OT_INLINE_DIVE_OBJECT,insert); if (ch=='/' && (multible || InsertMode==MODE_INSERT)) SetBaseObject(new dive_object(AppControl,function,this),MODE_INSERT); if (ch=='>') SetBaseObject(new symbol_object(QString(">"),OT_SYMBOL_OBJECT,AppControl,function,this),insert); if (ch=='<') SetBaseObject(new symbol_object(QString("<"),OT_SYMBOL_OBJECT,AppControl,function,this),insert); if (ch==':' || key.code==Qt::Key_Enter || key.code==Qt::Key_Return) function->ShowValue(); } } void string_object::MessageReceived(DataStorage *msg,int dest) { int what; int op; int insert; if (dest==TO_STRING) { what=msg->ReadInt("type"); op=msg->ReadInt("Oper"); insert=InsertMode; if (insert==MODE_AUTO) insert=MODE_ADD_RIGHT; if (ISMSG(MSG_FONTSIZE)) SetFontSize(msg->ReadInt("size")); // E D I T C O M M A N D S if (ISMSG(MSG_SELECTALL)) { UnFocusAll(); multible=true; selection.start=0; selection.end=FindLast(sub); } if (ISMSG(MSG_CUT)) { if (!multible) { CopySelection(AppControl->Clipboard); MarkForDeletion(index); RemoveFromString(index); ChangeIndex(-1); FocusObject(); Build(); } else { CopySelection(AppControl->Clipboard); Cut(selection,true); FocusObject(); Build(); } } if (ISMSG(MSG_COPY)) { GlobalCopy(); ResetSelection(); } if (ISMSG(MSG_PASTE)) { GlobalPaste(); } // M A T H C O M M A N D S if (ISMSG(MSG_MATHCOMMAND)) { if (op==T_CROSS) SetStringOperator(OT_CROSS_OBJECT,insert); if (op==T_CONJUGANT) SetStringOperator(OT_CONJUGANT_OBJECT,insert); if (op==T_FACTORIAL) SetStringOperator(OT_FACTORIAL_OBJECT,insert); if (op==T_IMAGINARY) SetBaseObject(new imaginary_object(0,AppControl,function,this),insert); if (op==T_VECTOR_I) SetBaseObject(new imaginary_object(1,AppControl,function,this),insert); if (op==T_VECTOR_J) SetBaseObject(new imaginary_object(2,AppControl,function,this),insert); if (op==T_VECTOR_K) SetBaseObject(new imaginary_object(3,AppControl,function,this),insert); if (op==T_DIVE) SetBaseObject(new dive_object(AppControl,function,this),insert); if (op==T_SQRT) SetBaseObject(new sqrt_object(AppControl,function,this),insert); // TRIGONO OBJECT if (op==T_SIN) SetBaseObject(new trigono_object(0,AppControl,function,this),insert); if (op==T_COS) SetBaseObject(new trigono_object(1,AppControl,function,this),insert); if (op==T_TAN) SetBaseObject(new trigono_object(2,AppControl,function,this),insert); if (op==T_COT) SetBaseObject(new trigono_object(3,AppControl,function,this),insert); if (op==T_ASIN) SetBaseObject(new trigono_object(4,AppControl,function,this),insert); if (op==T_ACOS) SetBaseObject(new trigono_object(5,AppControl,function,this),insert); if (op==T_ATAN) SetBaseObject(new trigono_object(6,AppControl,function,this),insert); if (op==T_ACOT) SetBaseObject(new trigono_object(12,AppControl,function,this),insert); // HYP if (op==T_SINH) SetBaseObject(new trigono_object(13,AppControl,function,this),insert); if (op==T_COSH) SetBaseObject(new trigono_object(14,AppControl,function,this),insert); if (op==T_TANH) SetBaseObject(new trigono_object(15,AppControl,function,this),insert); if (op==T_COTH) SetBaseObject(new trigono_object(16,AppControl,function,this),insert); if (op==T_ASINH) SetBaseObject(new trigono_object(17,AppControl,function,this),insert); if (op==T_ACOSH) SetBaseObject(new trigono_object(18,AppControl,function,this),insert); if (op==T_ATANH) SetBaseObject(new trigono_object(19,AppControl,function,this),insert); if (op==T_ACOTH) SetBaseObject(new trigono_object(20,AppControl,function,this),insert); // TRIGONO HANDLES ALSO if (op==T_LN) SetBaseObject(new trigono_object(7,AppControl,function,this),insert); if (op==T_INT) SetBaseObject(new trigono_object(9,AppControl,function,this),insert); if (op==T_FRAC) SetBaseObject(new trigono_object(10,AppControl,function,this),insert); if (op==T_LOG) SetBaseObject(new trigono_object(11,AppControl,function,this),insert); if (op==T_ARG_Z) SetBaseObject(new trigono_object(21,AppControl,function,this),insert); if (op==T_REZ) SetBaseObject(new trigono_object(22,AppControl,function,this),insert); if (op==T_IMZ) SetBaseObject(new trigono_object(23,AppControl,function,this),insert); // PARENTHESIS OBJECT if (op==T_PAR_A) SetBaseObject(new par_object(0,AppControl,function,this),insert); if (op==T_PAR_B) SetBaseObject(new par_object(1,AppControl,function,this),insert); if (op==T_PAR_C) SetBaseObject(new par_object(2,AppControl,function,this),insert); if (op==T_ABS || op==T_MODUL_Z || op==T_LENGTH) SetBaseObject(new par_object(3,AppControl,function,this),insert); // COMPLEX OBJECT if (op==T_COMPLEX_A) SetBaseObject(new complex_object(0,AppControl,function,this),insert); // EXPONENT OBJECT if (op==T_POWER) SetBaseObject(new exp_object(0,AppControl,function,this),insert); if (op==T_E) SetBaseObject(new exp_object(1,AppControl,function,this),insert); if (op==T_EXP) SetBaseObject(new exp_object(2,AppControl,function,this),insert); // SIGMA if (op==T_SIGMA) SetBaseObject(new sigma_object(0,AppControl,function,this),insert); if (op==T_BIG_PII) SetBaseObject(new sigma_object(1,AppControl,function,this),insert); if (op==T_INTEGRAL) SetBaseObject(new sigma_object(2,AppControl,function,this),insert); if (op==T_LOOP) SetBaseObject(new sigma_object(3,AppControl,function,this),insert); // MINMAX if (op==T_MIN) SetBaseObject(new minmax_object(0,AppControl,function,this),insert); if (op==T_MAX) SetBaseObject(new minmax_object(1,AppControl,function,this),insert); // FUNCTIONS if (op==T_FUNCTION_DEF) SetBaseObject(new function_defination_object(1,AppControl,function,this),insert); if (op==T_FUNCTION_DEF_2) SetBaseObject(new function_defination_object(2,AppControl,function,this),insert); if (op==T_FUNCTION_DEF_3) SetBaseObject(new function_defination_object(3,AppControl,function,this),insert); if (op==T_FUNCTION) SetBaseObject(new function_header_object(msg->ReadQString("func"),AppControl,function,this),insert); if (op==T_UNIT) SetBaseObject(new unit_object(AppControl,function,this),insert); if (op==T_MATRIX) SetBaseObject(new matrix_object(4,4,2,AppControl,function,this),insert); } function->SetModify(); DrawRQ(); } } void string_object::PostMessage(DataStorage *msg,int dest) { if (dest==TO_FRAME) function->MessageReceived(msg,dest); else if (dest==TO_OPERATOR) if (GetFocus()) GetFocus()->MessageReceived(msg,dest); else AppControl->PostMessage(msg,dest); } void string_object::CopySelection(DataStorage *clipboard) { CopyRange(selection,clipboard); } void string_object::GlobalCopy() { DataStorage *data=new DataStorage(); CopyRange(selection,data); SETMSG(data,MSG_COPY); QApplication::clipboard()->setData(new DataDragObject(data)); // NOTE: QClipboard owns DragObject / DataStorage } void string_object::GlobalPaste() { QClipboard *cp=QApplication::clipboard(); QMimeSource *mime=cp->data(); if (mime) { if (DataDragObject::canDecode(mime)) { DataStorage *data=DataDragObject::Decode(mime); PasteSelection(data); delete data; } } } void string_object::CopyRange(str_range ran,DataStorage *clipboard) { DataStorage *ar; int i,no; char name[20]; clipboard->Clear(); no=0; for(i=ran.start;i<=ran.end;i++) { sprintf(name,"entry:%d",(int)no); if (sub[i].Object) { ar=sub[i].Object->BuildStorage(); clipboard->AddDataStorage(name,ar); delete ar; no++; } } } void string_object::CopyAll(DataStorage *board) { DataStorage *ar; int i,no,last; char name[20]; board->Clear(); no=0; last=FindLast(sub); for(i=0;i<=last;i++) { sprintf(name,"entry:%d",(int)no); if (sub[i].Object) { ar=sub[i].Object->BuildStorage(); board->AddDataStorage(name,ar); no++; } } } void string_object::PasteSelection(DataStorage *board) { DataStorage ar; int no; char name[20]; m_base_object *obj; for(no=0;no<50;no++) { sprintf(name,"entry:%d",(int)no); if (board->Contains(name)) { ar.Clear(); board->ReadDataStorage(name,&ar); ar.AddPointer("function",(void *)function); ar.AddPointer("string",(void *)this); ar.AddPointer("appcontrol",(void *)AppControl); obj=(class m_base_object *)ConstructNewObject(&ar); ObjectInput(obj); SelectObject(obj); // use selectobject... otherwice index 0 will cause problems } else break; } function->SetModify(); }