void JSummation::Render ( const JExprRenderer& renderer, const JExprRectList& rectList ) const { // find ourselves in the list JIndex ourIndex; const JBoolean found = rectList.FindFunction(this, &ourIndex); assert( found ); const JRect ourRect = rectList.GetRect(ourIndex); const JCoordinate ourMidline = rectList.GetMidline(ourIndex); const JSize fontSize = rectList.GetFontSize(ourIndex); // draw ourselves JCoordinate h = ourRect.left; const JSize spaceWidth = renderer.GetStringWidth(fontSize, " "); const JSize argCount = GetArgCount(); for (JIndex i=1; i<=argCount; i++) { const JFunction* f = this; const JFunction* arg = GetArg(i); if (arg->GetType() == kJNegationType) { renderer.DrawString(h, ourMidline, fontSize, JPGetSubtractionString()); f = arg; const JNegation* neg = dynamic_cast<const JNegation*>(arg); assert( neg != NULL ); arg = neg->GetArg(); } else if (i > 1) { renderer.DrawString(h, ourMidline, fontSize, JPGetAdditionString()); } arg->Render(renderer, rectList); JIndex argIndex; const JBoolean found = rectList.FindFunction(arg, &argIndex); assert( found ); const JRect argRect = rectList.GetRect(argIndex); h = argRect.right; if (ParenthesizeArgForRender(*f, *arg)) { renderer.DrawParentheses(argRect); h += renderer.GetParenthesisWidth(argRect.height()); } h += spaceWidth; } }
void JSummation::Print ( ostream& output ) const { const JSize argCount = GetArgCount(); for (JIndex i=1; i<=argCount; i++) { const JFunction* f = this; const JFunction* arg = GetArg(i); if (arg->GetType() == kJNegationType) { output << JPGetSubtractionString(); f = arg; const JNegation* neg = dynamic_cast(const JNegation*, arg); assert( neg != NULL ); arg = neg->GetArg(); } else if (i > 1)
void JSummation::Print ( ostream& output ) const { const JSize argCount = GetArgCount(); for (JIndex i=1; i<=argCount; i++) { const JFunction* f = this; const JFunction* arg = GetArg(i); if (arg->GetType() == kJNegationType) { output << JPGetSubtractionString(); f = arg; const JNegation* neg = dynamic_cast<const JNegation*>(arg); assert( neg != NULL ); arg = neg->GetArg(); } else if (i > 1) { output << JPGetAdditionString(); } if (ParenthesizeArgForPrint(*f, *arg)) { output << '('; arg->Print(output); output << ')'; } else { arg->Print(output); } } }
JParseResult JParseAsSummation ( const JCharacter* origExpr, const JSize origLength, const JVariableList* theVariableList, JFunction** theFunction, const JBoolean allowUIF ) { *theFunction = NULL; // remove enclosing parentheses const JCharacter* expr = origExpr; const JSize length = JStripParentheses(&expr, origLength); // build a list of the locations of all visible + and - operators const JCharacter* plusStr = JPGetAdditionString(); const JSize plusLength = JPGetAdditionStringLength(); const JCharacter* minusStr = JPGetSubtractionString(); const JSize minusLength = JPGetSubtractionStringLength(); JArray<JCharacter> opList; JArray<JSize> opOffsetList; JArray<JSize> argOffsetList; JSize lastOffset = 0; while (1) { JSize plusOffset; const JBoolean foundPlus = JFindFirstOperator(expr + lastOffset, length - lastOffset, plusStr, &plusOffset); plusOffset += lastOffset; JSize minusOffset; const JBoolean foundMinus = JFindFirstOperator(expr + lastOffset, length - lastOffset, minusStr, &minusOffset); minusOffset += lastOffset; JCharacter opType; JSize opOffset, argOffset; if (foundPlus && foundMinus && plusOffset < minusOffset) { opType = '+'; opOffset = plusOffset; argOffset = plusOffset + plusLength; } else if (foundPlus && foundMinus && minusOffset < plusOffset) { opType = '-'; opOffset = minusOffset; argOffset = minusOffset + minusLength; } else if (foundPlus) { opType = '+'; opOffset = plusOffset; argOffset = plusOffset + plusLength; } else if (foundMinus) { opType = '-'; opOffset = minusOffset; argOffset = minusOffset + minusLength; } else { break; } if (!JIsExponentSign(expr, opOffset, argOffset)) { opList.AppendElement(opType); opOffsetList.AppendElement(opOffset); argOffsetList.AppendElement(argOffset); } lastOffset = argOffset; } if (opList.IsEmpty()) { return kJNotMyProblem; } else if (opList.GetElementCount() == 1 && opOffsetList.GetElement(1) == 0) { const JSize argOffset = argOffsetList.GetElement(1); JFunction* arg = NULL; if (!JRecurseFunction(expr + argOffset, length - argOffset, theVariableList, &arg, allowUIF)) { return kJParseError; } if (opList.GetElement(1) == '-') { *theFunction = new JNegation(arg); assert( *theFunction != NULL ); return kJParsedOK; } else // we ignore leading + { *theFunction = arg; return kJParsedOK; } } else { JSummation* sum = new JSummation; assert( sum != NULL ); // No operand in front means implied + if (opOffsetList.GetElement(1) > 0) { opList.PrependElement('+'); opOffsetList.PrependElement(0); argOffsetList.PrependElement(0); } // We append an extra element at the end of the list // so our loop catches the last summand. opList.AppendElement('+'); opOffsetList.AppendElement(length); argOffsetList.AppendElement(length); // Parse each summand const JSize opCount = opList.GetElementCount(); for (JIndex i=1; i<opCount; i++) { const JCharacter opType = opList.GetElement(i); const JSize startOffset = argOffsetList.GetElement(i); const JSize endOffset = opOffsetList.GetElement(i+1); JFunction* arg = NULL; if (!JRecurseFunction(expr + startOffset, endOffset - startOffset, theVariableList, &arg, allowUIF)) { delete sum; return kJParseError; } else if (opType == '+') { sum->SetArg(i, arg); } else // opType == '-' { JNegation* negArg = new JNegation(arg); assert( negArg != NULL ); sum->SetArg(i, negArg); } } *theFunction = sum; return kJParsedOK; } }
JIndex JSummation::PrepareToRender ( const JExprRenderer& renderer, const JPoint& upperLeft, const JSize fontSize, JExprRectList* rectList ) { // intialize our rectangle and midline JPoint argUpperLeft = upperLeft; JRect ourRect(upperLeft, argUpperLeft); ourRect.bottom += renderer.GetLineHeight(fontSize); JCoordinate ourMidline = ourRect.ycenter(); const JCoordinate origMidline = ourMidline; // get rectangle for each argument const JSize spaceWidth = renderer.GetStringWidth(fontSize, " "); const JSize plusWidth = renderer.GetStringWidth(fontSize, JPGetAdditionString()); const JSize minusWidth = renderer.GetStringWidth(fontSize, JPGetSubtractionString()); const JSize argCount = GetArgCount(); { for (JIndex i=1; i<=argCount; i++) { JFunction* f = this; JFunction* arg = GetArg(i); if (arg->GetType() == kJNegationType) { argUpperLeft.x += minusWidth + spaceWidth; if (i > 1) { argUpperLeft.x += spaceWidth; } f = arg; JNegation* neg = dynamic_cast<JNegation*>(arg); assert( neg != NULL ); arg = neg->GetArg(); } else if (i > 1) { argUpperLeft.x += plusWidth + 2*spaceWidth; } const JIndex argIndex = arg->PrepareToRender(renderer, argUpperLeft, fontSize, rectList); JRect argRect = rectList->GetRect(argIndex); argUpperLeft.x = argRect.right; if (ParenthesizeArgForRender(*f, *arg)) { const JSize parenWidth = renderer.GetParenthesisWidth(argRect.height()); rectList->ShiftRect(argIndex, parenWidth, 0); argRect = rectList->GetRect(argIndex); argUpperLeft.x += 2*parenWidth; ourRect.right = argRect.right + parenWidth; } ourRect = JCovering(ourRect, argRect); const JCoordinate argMidline = rectList->GetMidline(argIndex); if (argMidline > ourMidline) { ourMidline = argMidline; } } } // adjust the argument rectangles so all the midlines are the same // (ourMidline is guaranteed to stay constant) if (argCount > 1 && ourMidline > origMidline) { for (JIndex i=1; i<=argCount; i++) { const JFunction* arg = GetArg(i); if (arg->GetType() == kJNegationType) { const JNegation* neg = dynamic_cast<const JNegation*>(arg); assert( neg != NULL ); arg = neg->GetArg(); } JIndex argIndex; const JBoolean found = rectList->FindFunction(arg, &argIndex); assert( found ); rectList->SetMidline(argIndex, ourMidline); ourRect = JCovering(ourRect, rectList->GetRect(argIndex)); } } // save our rectangle return rectList->AddRect(ourRect, ourMidline, fontSize, this); }