int LineListWrap::find_ypos(unsigned int ypos) { wxASSERT(ypos >= 0 && ypos <= height()); wxASSERT(approxTop >= 0); verify(); if (!size()) return 0; wxASSERT(lastLoadedPos != 0 && firstLoadedPos < lastLoadedPos); bool do_approx = true; while (1) { // Often we want one just above or below current window if (ypos < (unsigned int)approxTop) { // Expand window up a bit int recalc = extendwindow(uMinus(firstLoadedPos, WINSIZE/2)); unsigned int new_ypos = uPluss(ypos, recalc); new_ypos = wxMin(new_ypos, height()); if (new_ypos >= (unsigned int)approxTop) ypos = new_ypos; } else if (lastValidPos && ypos > yPositions[lastValidPos-1]) { // Expand window down a bit int recalc = extendwindow(wxMin(last(), lastLoadedPos+(WINSIZE/2))); wxASSERT(recalc == 0); // there should be no change of approxTop } if (ypos >= (unsigned int)approxTop) { validate_positions(lastLoadedPos-1); // Make sure lastValidPos is at end of window wxASSERT(lastValidPos > 0); if (ypos <= yPositions[lastValidPos-1]) { // ypos is inside window vector<unsigned int>::iterator posline = lower_bound(yPositions.begin() + firstLoadedPos, yPositions.begin() + lastValidPos, (unsigned int)ypos); int index = distance(yPositions.begin(), posline); wxASSERT(top(index) <= ypos); return index; } else if (lastValidPos == size()) return last(); // recalc of positions may end up with pos outside text } // Else we have to find the approximate line if (do_approx) { wxASSERT(avr_lineheight > 0); unsigned int index = ypos / avr_lineheight; index = wxMin(index, last()); extendwindow(index); do_approx = false; // only try to approximate once } } wxASSERT(false); // We should never reach here return 0; }
int LineListWrap::prepare(int ypos) { verify(); approxDiff = 0; if (!size()) return 0; if (ypos == -1) { validate_positions(last()); } else { // adjust ypos a bit so we are sure to get the line above as well find_ypos(uMinus(ypos, 100)); } return approxDiff; }
int LineListWrap::OnIdle() { if (!size()) return 0; wxASSERT(lastLoadedPos != 0 && firstLoadedPos < lastLoadedPos); //wxLogDebug(wxT("ll.OnIdle %d %d (%d)"), firstLoadedPos, lastLoadedPos, size()); if (firstLoadedPos > 0) { //wxLogDebug("OnIdle 1"); unsigned int index = uMinus(firstLoadedPos, 100); // Load positions in extension unsigned int line_bottom = 0; for (unsigned int i = index; i < firstLoadedPos; ++i) { line.SetLine(offset(i), end(i)); line_bottom = yPositions[i] = line_bottom + line.GetHeight(); } // Calculate new approxTop unsigned int new_approxTop = 0; if (index) { unsigned int loadedheight = yPositions[lastLoadedPos-1] - (firstLoadedPos ? yPositions[firstLoadedPos] : 0); avr_lineheight = (yPositions[firstLoadedPos-1] + loadedheight) / (lastLoadedPos - index); new_approxTop = index * avr_lineheight; } // Adjust all positions to new approxTop int ext_diff = line_bottom - approxTop; for (unsigned int i2 = index; i2 < lastLoadedPos; ++i2) { yPositions[i2] += new_approxTop; if (i2 >= firstLoadedPos) yPositions[i2] += ext_diff; } approxTop = new_approxTop; firstLoadedPos = index; recalc_approx(); /* int bottom = yPositions[firstLoadedPos]; for (unsigned int i = firstLoadedPos; i >= index && i <= firstLoadedPos; --i) { line.SetLine(offset(i), end(i)); yPositions[i] = bottom; bottom -= line.GetHeight(); } int diff = yPositions[firstLoadedPos-1] - bottom; wxASSERT(bottom < (int)yPositions[firstLoadedPos-1]); wxASSERT(diff >= 0); approxTop -= diff; firstLoadedPos = index; int aprx = recalc_approx(true);*/ verify(); return ext_diff; } else if (lastLoadedPos != size()) { //wxLogDebug("OnIdle 2"); wxASSERT(lastLoadedPos < size()); int index = wxMin(lastLoadedPos+100, last()); int top = yPositions[lastLoadedPos-1]; for (int i = lastLoadedPos; i <= index; ++i) { line.SetLine(offset(i), end(i)); yPositions[i] = top += line.GetHeight(); } if (lastValidPos == lastLoadedPos && posDiff == 0) lastValidPos = index+1; lastLoadedPos = index+1; int aprx = recalc_approx(); // recalc approximations (below only) verify(); return aprx; } return 0; }
int LineListWrap::extendwindow(unsigned int index) { wxASSERT(index >= 0 && index < yPositions.size()); if (size() == 0) return 0; if (index >= firstLoadedPos && index < lastLoadedPos) return 0; // in window // Check if we can extend current window if (index < firstLoadedPos) { // Index above window if (WINSIZE > firstLoadedPos || index > firstLoadedPos-WINSIZE) { // extend window to index index = uMinus(firstLoadedPos, WINSIZE); // do a full block // Load positions in extension unsigned int line_bottom = 0; for (unsigned int i = index; i < firstLoadedPos; ++i) { line_bottom = yPositions[i] = line_bottom + line.GetQuickLineHeight(offset(i), end(i)); } // Calculate new approxTop unsigned int new_approxTop = 0; if (index) { unsigned int loadedheight = yPositions[lastLoadedPos-1] - (firstLoadedPos ? yPositions[firstLoadedPos] : 0); avr_lineheight = (yPositions[firstLoadedPos-1] + loadedheight) / (lastLoadedPos - index); new_approxTop = index * avr_lineheight; } // Adjust all positions to new approxTop int ext_diff = line_bottom - approxTop; for (unsigned int i2 = index; i2 < lastLoadedPos; ++i2) { yPositions[i2] += new_approxTop; if (i2 >= firstLoadedPos) yPositions[i2] += ext_diff; } approxTop = new_approxTop; firstLoadedPos = index; recalc_approx(); return ext_diff; } } else { // Index below window if (lastLoadedPos != 0 && index+1 < lastLoadedPos+WINSIZE) { // extend window to index //index = wxMin(last(), lastLoadedPos+WINSIZE); // do a full block int top = yPositions[lastLoadedPos-1]; for (unsigned int i = lastLoadedPos; i <= index; ++i) { yPositions[i] = top += line.GetQuickLineHeight(offset(i), end(i)); } if (lastValidPos == lastLoadedPos) lastValidPos = index+1; lastLoadedPos = index+1; return recalc_approx(); // recalc approximations (below only) } } // We have to create a new window // The window can't go beyond index approxDiff = 0; int endline = index; index = uMinus(index, WINSIZE); int top = 0; if (avr_lineheight > 0) top = approxTop = index * avr_lineheight; else wxASSERT(approxTop == 0); for (int i = index; i <= endline; ++i) { top = yPositions[i] = top + line.GetQuickLineHeight(offset(i), end(i)); } firstLoadedPos = index; lastValidPos =lastLoadedPos = endline+1; wxASSERT(lastValidPos > firstLoadedPos && lastValidPos <= lastLoadedPos); wxASSERT(lastValidPos < yPositions.size() || posDiff == 0); return recalc_approx(true); // recalc approximations; }
obj eval(obj exp){ ev: assert(!! exp); obj rr,lt, rt; switch (exp->type) { case tInd: return doInd(eval(ult(exp)), ul(eval(urt(exp)))); case LIST: return List2v(evalList(ul(exp))); case tArray: return map_obj(eval, exp); case tAnd: return prod_eval(ul(exp), mult); case MULT: return prod_eval(ul(exp), mult); case ARITH: return prod_eval(ul(exp), add); case POW: return prod_eval(ul(exp), power); case DIVIDE: return prod_eval(ul(exp), divide); case tRef: return retain(uref(exp)); case tSymbol: if( macromode) { if(obj rr = search_assoc(car(macro_env), exp)){ macromode = false; // macro lexical scope should be pushed to the stack here rr = exec(rr); macromode = true; return rr; } } return eval_symbol(exp); case tMinus: lt = eval(uref(exp)); rr = uMinus(lt); // releasing if(rr) {release(lt); return rr;} static obj symumn = Symbol("-"); rr = udef_op0(symumn, lt); if(rr) {release(lt); return rr;} error("uMinus: not defined to that type"); case tReturn: if(! uref(exp)) return encap(tSigRet, nil); return encap(tSigRet, eval(uref(exp))); case tBreak: return retain(exp); case CONDITION: return evalCond(exp); case tOp: if(type(ult(exp)) ==tSymbol) { lt = search_assoc(curr_interp->types, ult(exp)); if(lt) return encap((ValueType)vrInt(lt), eval(urt(exp)));} lt = eval(ult(exp)); push(lt); switch(lt->type){ case tCont: assert(0); case tSpecial: rr = ufn(lt)(urt(exp)); break; case tSyntaxLam: rr = macro_exec(lt, urt(exp)); break; case tInternalFn: case tClosure: rt = eval(urt(exp)); rr = eval_function(lt, rt); break; default: rt = eval(urt(exp)); rr = call_fn(mult, lt, rt); release(rt); } release(pop(&is)); return rr; case tClosure: assert(0); case tCurry: return eval_curry(exp, em0(exp)); /* obj vars = Assoc(); bind_vars(&vars, em0(exp), em2(exp)); rr = eval_curry(exp, vars); release(vars); return rr; */ case tArrow: // return enclose(exp); /* if(macromode){ if(obj rr = search_assoc(car(macro_env), exp)){ } } */ return render(tClosure, list3(retain(em0(exp)), retain(em1(exp)), retain(env))); case tDefine: return func_def(em0(exp), em1(exp), em2(exp)); case tSyntaxDef: let(lfind_var(em0(exp)), render(tSyntaxLam, list3(retain(em1(exp)), retain(em2(exp)), nil))); return nil; case tExec: return exec(exp); case tAssign: lt = car(exp); if(type(lt)==tOp){ return func_def(ult(lt), urt(lt), cdr(exp)); } else if(type(lt)==tMinus){ static obj symumn = Symbol("-"); return func_def(symumn, uref(lt), cdr(exp)); } else return do_assign(lt, eval(cdr(exp))); case tIf: rr = eval(em0(exp)); if (type(rr) != INT) error("if: Boolean Expected"); if (vrInt(rr)) { rr = em1(exp); } else { rr = em2(exp); } return eval(rr); case tWhile: for(;;) { rr = eval(car(exp)); if (type(rr) != INT) error("while: Boolean expected"); if(!vrInt(rr)) break; rr = exec(cdr(exp)); if(rr && type(rr)==tSigRet) return rr; if(rr && type(rr)==tBreak) {release(rr); break;} if(rr) release(rr); } return nil; default: return retain(exp); } }