/* AppSpeci 2002 Tsuguo Mogami */ #include "ciph.h" #include "value.h" #include "list.h" #include "app.h" #include #include "lib.h" static int getWidth(obj string); static void drawFormula(obj line, bool draw); void drawLines(list*line, bool draw); //static int findBeginingOfPreviousLetter(); static int findBeginingOfPreviousLine(); static list CStringToLine(obj str); static void serialize(string*rs, list l, list end); static void win_normalize(); //----- inline int_* create(ValueType t, int i){ int_* r = (int_*)alloc(); r->type = t; uint(r) = i; return r; } class frac: public list_ { public: frac(); ~frac() {} }; int viewPosition = 0; static list lines; //---------current line with insertion point object--------------------------- static list line; static int startOfThisLine; //絶対座標, multiple lineのときの始め。 static Point cursorPosition; static Point curBase; int baseLine = 50;// ほかに使っているのはplot() // baseLineはカーソル位置の拡張とおもう。 // line編集中はcursorPositionと同時に変更を行う。 static list insList=nil; // insertion point のスタック // insと合わせてinsertion pointを表す static list beginSelList; struct insp { int pos; // list l; list *curstr; // current string inline void moveInto(list *l){ curstr = l; pos = 0; } inline void moveRightmost(list *l){ ins.curstr = l; ins.pos = nList(*l); } } beginOfSel, ins; //insは現在のinsertion point static Point cursorBeforeVertMove; static Point selectionCursorPosition; static bool nowSelected = false; // didBufのデータ形式の定義 // list of insert_string("hoge"), move_to(list ins), delete(int n) // undoBufのデータ形式の定義 // delete(int n), move_to(list ins), insert_string("hoge") //いまのところundobufをつかい1-levelのundoだけ static list didBuf = nil; static list undoBuf = nil; static obj undobuf = nil; //------------draw系---------- void drawFraction(list_* f, bool draw){ Point pt; GetPen(&pt); assert(f->type==FRACTION); int numerWidth = getWidth(em0(f)); int denomWidth = getWidth(em1(f)); int width = 2 + larger(numerWidth, denomWidth) +2; MoveTo(pt.h, pt.v-FONTSIZE/3); if(draw) Line(width,0); MoveTo(pt.h+width/2-numerWidth/2, pt.v-FONTSIZE*2/3); drawFormula(em0(f), draw); MoveTo(pt.h+width/2-denomWidth/2, pt.v+FONTSIZE); drawFormula(em1(f), draw); MoveTo(pt.h+width+2, pt.v); } void drawSuperScript(obj v, bool draw){ Move(0,-FONTSIZE*2/3); TextSize(FONTSIZE*3/4); assert(type(v)==SuperScript); drawFormula(v, draw); TextSize(FONTSIZE); Move(0,FONTSIZE*2/3); } void drawSubScript(obj v, bool draw){ Move(0,+FONTSIZE/3); TextSize(FONTSIZE*3/4); assert(type(v)==SubScript); drawFormula(v, draw); TextSize(FONTSIZE); Move(0,-FONTSIZE/3); } // CRは行末に付属すると考える。 Point curbase; // curBaseはcursorのbaseline, curbaseは現在描画中のbaseline static bool crossed; int drawOne(list& l, int& pos, bool draw){ Point pt; char buf[8]; obj v = first(l); switch(type(v)){ case INT: // read *buf=0; int c = uint(v); buf[++*buf] = c; if(c&0x80){ if(! rest(l)) break;//2 byte文字が1byteずつ挿入されるから if(second(l)->type != INT) break; buf[++*buf] = uint(second(l)); } //newlineifneccesary int width = StringWidth((StringPtr)buf); if(c=='\t') width = StringWidth("\p "); if(c==CR) { pos++, l=rest(l); goto newline; } //draw: if(c=='\t') { DrawString("\p "); break; } GetPen(&pt); if(!draw || pt.v < -FONTSIZE) Move(width, 0); else DrawString((StringPtr)buf); break; case FRACTION: drawFraction((list_*)v, draw); break; case SuperScript: drawSuperScript(v, draw); break; case SubScript: drawSubScript(v, draw); break; case tShow: DrawString("\p▽"); drawLines(&ul(v), draw); DrawString("\p▽"); break; case tHide: DrawString("\p△"); break; } if(type(v)==INT && uint(v)&0x80 && rest(l) && second(l)->type==INT){ pos++; l=rest(l); } pos++, l=rest(l); return 0; newline: return 1; } inline int getInsertionCloseTo0(list& l, int &pos, int h, int&curr_mark){ Point pt; for(; ;){ GetPen(&pt); if(pt.h <= h) curr_mark = pos; if(! l) goto endline; if(&line==ins.curstr && pos==ins.pos) crossed = true; if(drawOne(l, pos, false)) goto newline; GetPen(&pt); if(pt.h > LEFTMARGIN+colWidth) goto newline; //wrap } newline: return 1; endline: return 0; } void findInsertionCloseTo(int h, int &next, int &prev){ int pos = findBeginingOfPreviousLine(); int curr_mark=0; if(pos<0) pos=0; list l=rest(line, pos); next=-1; prev=-1; crossed = false; bool metend = false; MoveTo(LEFTMARGIN,0); for(; l;){ if(getInsertionCloseTo0(l, pos, h, curr_mark)==1) goto newline; else goto endline; newline: Point pt; GetPen(&pt); MoveTo(LEFTMARGIN, pt.v+LINEHEIGHT); if(! crossed) prev = curr_mark;// if(pos<=ins.pos) prev = curr_mark; endline: if(metend) {next = curr_mark; return;} if(crossed) metend = true; // if(pos>ins.pos) metend = true; } } insp click; Point clickpnt; Point curclick; int drawFormula0(list* line, list& l, int& pos, bool draw){ Point pt; int linew=0; char buf[256]; for(; ; ){ // chars if(line==ins.curstr && pos==ins.pos){// if(line==ins.curstr && l == rest(*ins.curstr, ins.pos)){ GetPen(&cursorPosition); curBase = curbase; crossed=true; } if(! l) goto endline; if(drawOne(l, pos, draw)) goto newline; GetPen(&pt); if(pt.h > 50+colWidth) goto newline;//wrap if(pt.v < clickpnt.v + FONTSIZE/2 && pt.h < clickpnt.h){ click.curstr = line; click.pos = pos; curclick = pt; } } endline: return 0; newline: return 1; } void drawFormula(obj line, bool draw){ list l=ul(line); int pos=0; drawFormula0(&ul(line), l, pos, draw); } void drawLines(list*line, bool draw){ list l = *line; int pos = 0; Point pt; GetPen(&pt); int vv=pt.v; for(int col=0; col < nCols; col++){ // columns for(; ; ){ // lines by CR GetPen(&curbase); // get baseline of the line if(drawFormula0(line, l, pos, draw)){ vv += LINEHEIGHT; MoveTo(LEFTMARGIN+(colWidth+colSep)*col, vv); } if(line==ins.curstr && pos==ins.pos){// if(line==ins.curstr && l == rest(*ins.curstr, ins.pos)){ GetPen(&cursorPosition); curBase = curbase; crossed=true; } if(! l) return; if(vv > windowHeight) break; } vv += -windowHeight + FONTSIZE; MoveTo(LEFTMARGIN+(colWidth+colSep)*(col+1), vv); } } int getWidth(obj str){ Point pt, np; GetPen(&pt); drawFormula(str, false); // wrapされるとまずい GetPen(&np); return np.h-pt.h; } void drawObj(obj line){ //set cursorPositino at the same time char str[256]; if(type(line) ==STRING){ strcpy(str, ustr(line)); CtoPstr(str); DrawString((StringPtr)str); return; } else if(type(line)==IMAGE || type(line)==tCImg){ print_image(line); return; } else if(type(line)==tLine){ showline(line); return; } assert(line->type==LIST); drawFormula(line, true); } //------accessors of the current line ----------------- inline void set_insp(int pos){ // <-> move insertion release(insList); insList = nil; ins.curstr = &line; ins.pos = pos; } int findBeginingOfPreviousLetter(){ int p=0; int i=0; for(list l=*(ins.curstr); l && itype==INT && uint(first(l))==CR) { pp=p; p=i+1; } return pp; } static void pushInsertion(){ insList = cons(Int(ins.pos), insList); } static void popInsertion(){ ins.pos = vrInt(pop(&insList)); } list deleteALetter0(){ int p = findBeginingOfPreviousLetter(); list* inspp = rest(ins.curstr, p); list l = *inspp; *inspp = rest(l, ins.pos-p); *rest(&l, ins.pos-p) = nil; ins.pos = p; return l; } static void deleteALetter(){ list l = deleteALetter0(); if(!undobuf) undobuf = (obj)create(tIns, phi()); else if(undobuf->type!=tIns){ release(undobuf); undobuf = (obj)create(tIns, phi()); } ul(undobuf) = merge(l, ul(undobuf)); return; } inline obj snthOf(list l, int i){return first(rest(l, i));}; static int peekPreviousLetter(){ // not good for 2-bytes if(ins.pos==0) return NUL; int p = findBeginingOfPreviousLetter(); obj vp = snthOf(*ins.curstr, p); if(vp->type!=INT) return NUL; return uint(vp); } inline void insert0(obj v){ list* inspp = rest(ins.curstr, ins.pos); *inspp = cons(v, *inspp); ins.pos++; } void insert(obj v){ insert0(v); if(!undobuf) undobuf = create(tDel, 1); else if(undobuf && undobuf->type==tDel){ (uint(undobuf))++; } else { release(undobuf); undobuf = create(tDel, 1); } } void newLine(){ line = phi(); ins.moveInto(&line); insList = nil; startOfThisLine = baseLine+viewPosition; cursorPosition.h = LEFTMARGIN; cursorPosition.v = baseLine; MoveTo(LEFTMARGIN, baseLine); cursorBeforeVertMove = cursorPosition; beginOfSel.pos = 0; beginSelList = nil; selectionCursorPosition = cursorPosition; nowSelected = false; release(didBuf); release(undoBuf); didBuf = nil; undoBuf = nil; } void moveIntoDenom(list_* fr){ pushInsertion(); ins.pos = 2; pushInsertion(); ins.moveInto(&ul(em1(fr))); } void insertFraction(list num, list denom){ list_* v = render(FRACTION, list2(List2v(num), List2v(denom))); insert(v); moveIntoDenom(v); } list* curr_str(list l){ if(! l) return &line; obj v = first(rest(*curr_str(rest(l)), uint(first(l))-1)); assert(v->type==FRACTION || v->type==SubScript || v->type==SuperScript || v->type==LIST); return &ul(v); } list ins_list(list*scan, list*curstr){ // finding insList from curstr if(scan == curstr) return nil; list l = *scan; for(int i=0; l; l=rest(l), i++) { obj v=first(l); if(v->type==INT) continue; if( &ul(v)==curstr) return list1(Int(i+1)); else if (list ll = ins_list(&ul(v), curstr)) return merge(ll, list1(Int(i+1))); } return nil; } /*list* upper_str(list*scan){ if(scan == ins.curstr) assert(0); List l = *scan; for(; l; l=rest(l)) { obj v=first(l); if(v->type==INT) continue; if( &ul(v)==ins.curstr) return scan; if(list*ll = upper_str(&ul(v))) return ll; } return nil; }*/ static list isInFracRecur(){ list l = insList; if(! l) return nil; for(;; l=rest(l)){ if(! rest(l)) return nil; obj v = snthOf(*curr_str(rest(rest(l))), uint(second(l))-1); if(v->type==FRACTION) return l; } } static bool isInFrac(){ if(! insList) return false; obj v = snthOf(*curr_str(rest((insList))), uint(first(insList))-1); if(type(v)!=FRACTION) return false; return true; } void moveToUpperLevel(){ popInsertion(); if(isInFrac()) popInsertion(); ins.curstr = curr_str(insList); } int getNLine(list l){//line数-1,CRの数を数える int i=0; for(; l; l=rest(l)) if(first(l)->type==INT && uint(first(l))==CR) i++; return i; } void insertSuperScriptAndMoveInto(){ obj vp = render(SuperScript, nil); insert(vp); pushInsertion(); //insertion pointはみぎで待っていてもらうことにする。 ins.moveInto(&ul(vp)); } void insertSubScriptAndMoveInto(){ obj vp = render(SubScript, phi()); insert(vp); pushInsertion(); ins.moveInto(&ul(vp)); } // -------------- controllers ------------ void moveLeft(){ if(insList && ins.pos==0) { moveToUpperLevel(); ins.pos--; return; } if(ins.pos==0) return; obj c = snthOf(*(ins.curstr), ins.pos-1); if(c->type==SuperScript || c->type==SubScript){ pushInsertion(); ins.moveRightmost(&ul(c)); return; } if(c->type==FRACTION){ moveIntoDenom((list_*)c); ins.pos = nList(*ins.curstr); return; } ins.pos = findBeginingOfPreviousLetter(); } void moveRight(){ if(insList && ins.pos==nList(*ins.curstr) ) { moveToUpperLevel(); return; } if(ins.pos >= nList(*ins.curstr)) return; obj c = snthOf(*ins.curstr, ins.pos); if(c->type==SuperScript || c->type==SubScript){ ins.pos++; pushInsertion(); ins.moveInto(&ul(c)); return; } if(c->type==FRACTION){ ins.pos++; moveIntoDenom((list_*)c); return; } if(type(c)==INT && (uint(c)&0x80)) ins.pos++; if(type(c)==INT && uint(c)==CR) scrollBy(+LINEHEIGHT); ins.pos++; } void removeSelected(){ if(beginSelList != insList){ SysBeep(1); return; } int b = smaller(beginOfSel.pos, ins.pos); int e = larger(beginOfSel.pos, ins.pos); if(b==e) return; ins.pos = b; list*lp = rest(&line, b); for(int i=0; i= GetCaretTime() ){ if(caretState == 0) ShowCaret(); else HideCaret(); } } #define upboundby(b,x) ((x)<(b)?(x):(b)) extern WindowPtr currWindow; void win_normalize(){ if(!baseLine > windowHeight-FONTSIZE && !baseLine < FONTSIZE) return; RgnHandle updateRgn = NewRgn(); Rect rect = currWindow->portRect; while(baseLine > windowHeight-FONTSIZE) { int move= upboundby(FONTSIZE, baseLine -(windowHeight-FONTSIZE)); baseLine -= move; viewPosition += move; ScrollRect(&rect, 0, -move, updateRgn); } while(baseLine < FONTSIZE) { int move= -upboundby(FONTSIZE, -baseLine +FONTSIZE); baseLine -= move; viewPosition += move; ScrollRect(&rect, 0, -move, updateRgn); } DisposeRgn(updateRgn); MoveTo(LEFTMARGIN,baseLine); } void scrollBy(int pixels){ baseLine += pixels; win_normalize(); } void scroll(){ scrollBy(FONTSIZE); } //----------------- extern Interpreter interpreter; static list csparse(char* str, int len); void initLines(){ lines = phi(); ins.curstr = &line; } void addObjToText(obj line){ //taking line list aLine = list2(line, Int(baseLine+viewPosition)); append(&lines, List2v(aLine)); } static void addLineToText(obj line){ //taking line list aLine = list2(line, Int(startOfThisLine)); append(&lines, List2v(aLine)); } void addStringToText(char* string){ Point pt; GetPen(&pt); list aLine = list3(String2v(string), Int(viewPosition+baseLine), Int(pt.h)); append(&lines, List2v(aLine)); } #include #include void myPrintf(char *fmt,...){ va_list ap; char str[256]; Point pt; GetPen(&pt); if(pt.h > LEFTMARGIN+colWidth) return; // if(pt.h > LEFTMARGIN+colWidth) scroll(); va_start(ap,fmt); if (fmt) { vsprintf(str,fmt,ap); } va_end(ap); if(strlen(str)>255) assert_func("app.c", __LINE__); addStringToText(str); for(char* s=str; *s; s++) if(*s=='\n') *s=' '; CtoPstr(str); DrawString((StringPtr)str); } void print_str(char*s){ char str[256]; Point pt; GetPen(&pt); if(pt.h > LEFTMARGIN+colWidth) return; // addStringToText(str); // for(char* s=str; *s; s++) if(*s=='\n') *s=' '; int p=0; for(; s[p] && p<250; p++) str[p] = s[p]; s[p] = NUL; CtoPstr(str); DrawString((StringPtr)str); } int imbalanced(list line){ int paren=0,brace=0; for(list l=line; l; l=rest(l)){ switch(first(l)->type){ case INT: char c=uint(first(l)); if(c=='(') paren++; if(c==')') paren--; if(c=='{') brace++; if(c=='}') brace--; break; case FRACTION: case SuperScript: case SubScript: break; } } return abs(paren)+abs(brace); } void updateAround(bool erase){ Rect r; r.left = LEFTMARGIN; r.right= LEFTMARGIN+colWidth+50; r.top = baseLine-FONTSIZE*2; r.bottom = baseLine+FONTSIZE; // r.top = cursorPosition.v-FONTSIZE; // r.bottom = cursorPosition.v; if(erase){ r.top = baseLine-FONTSIZE*2; r.bottom = windowHeight; } if(erase) EraseRect(&r); InvalRect(&r); DoUpdate(currWindow); } void HandleTyping0(char c){ if(c==CR){ if(! insList){ insert(Int(CR)); baseLine+=LINEHEIGHT; } else moveToUpperLevel(); } else if(c==BS){ if(nowSelected) removeSelected(); else deleteALetter(); } else if(c==arrowLeft){ moveLeft(); } else if(c==arrowRight){ moveRight(); } else if(c==arrowUp){ moveUp(); win_normalize(); } else if(c==arrowDown){ moveDown(); win_normalize(); } else if(c=='~' ){ insertSuperScriptAndMoveInto(); } else if(c=='_'){ insertSubScriptAndMoveInto(); } else if(c=='/' && peekPreviousLetter() =='/') { deleteALetter(); // delete '/' list l = deleteALetter0(); insertFraction(l, nil); } else { if(nowSelected) removeSelected(); assert(c | 0xff == -1); insert(Int(c & 0xff)); } if(c==arrowLeft||c==arrowRight||c==arrowUp||c==arrowDown){ if(type(undobuf) !=tMove){ undoBuf = cons(undobuf, undoBuf); undobuf = create(tMove, cons(Int(ins.pos), retain(insList))); } } HideCaret(); updateAround(!(c==arrowLeft||c==arrowRight||c==arrowUp||c==arrowDown)); baseLine = curBase.v; ShowCaret(); if(!(c==arrowUp||c==arrowDown)) cursorBeforeVertMove = cursorPosition; // keep position for short line beginOfSel = ins; //for text selection release(beginSelList); beginSelList = retain(insList); selectionCursorPosition = cursorPosition; nowSelected = false; } void handleCR(){ addLineToText(List2v(line)); baseLine = startOfThisLine-viewPosition+FONTSIZE*(2+getNLine(line));//dame scrollBy(0); //改行します。 interpret(interpreter, line); scrollBy(FONTSIZE*2); newLine(); } void HandleTyping(char c){ if(c==CR && !insList && !imbalanced(line)){ HideCaret(); handleCR(); ShowCaret(); return; } else HandleTyping0(c); } void HandleShifted(char c){ if(!nowSelected && beginSelList != insList) return; HideCaret(); if(c==arrowLeft){ moveLeft(); } else if(c==arrowRight){ moveRight(); } else if(c==arrowUp){ moveUp(); win_normalize(); } else if(c==arrowDown){ moveDown(); win_normalize(); } updateAround(true); MoveTo(cursorPosition.h, cursorPosition.v); UInt8 curMode = LMGetHiliteMode(); LMSetHiliteMode(curMode & 0x7f); Rect r; r.left = smaller(selectionCursorPosition.h, cursorPosition.h); r.right= larger(selectionCursorPosition.h, cursorPosition.h); r.top = smaller(selectionCursorPosition.v, cursorPosition.v)-FONTSIZE; r.bottom= larger(selectionCursorPosition.v, cursorPosition.v); InvertRect(&r); LMSetHiliteMode(curMode | 0x80); // ShowCaret(); nowSelected = true; } void getClickPosition(Point pt){ clickpnt = pt; MoveTo(LEFTMARGIN, startOfThisLine-viewPosition); click.curstr = nil; drawLines(&line, false); if(!click.curstr) return; //ins.curstr = click.curstr; //ins.pos = click.pos; ins = click; release(insList); insList = ins_list(&line, click.curstr); cursorPosition = curclick; } void HandleContentClick(Point pt){ getClickPosition(pt); } void DoUpdate(WindowPtr targetWindow) { SetPortWindowPort(targetWindow); BeginUpdate(targetWindow); // EraseRect(&targetWindow->portRect); Redraw(); // DrawGrowIcon(targetWindow); //サイズボックスを描く // DrawControls(targetWindow); //コントロール、つまりスクロールバーを描く EndUpdate(targetWindow); } void DoUndo(){ obj doit=retain(undobuf); if(type(doit)==tDel){ int n = uint(doit); for(int i=0; i 0) { //TEXTの存在をチェック dataBlock = NewHandle(dataSize); dataSize = GetScrap(dataBlock, 'TEXT', &offset); list tt = csparse((char*)*dataBlock, dataSize); for(list l=tt; l; l=rest(l)) insert(first(l)); updateAround(true); MoveTo(cursorPosition.h, cursorPosition.v); DisposeHandle(dataBlock); //これでいいのかな? } // not yet ? } void DoOpen(){ static obj fn = String2v("j"); long bytes; obj rr = val(read(&bytes, (fn))); newLine(); line = CStringToLine(rr); MoveTo(LEFTMARGIN, startOfThisLine-viewPosition); drawLines(&line, true); MoveTo(cursorPosition.h, cursorPosition.v); } void DoSave(){ static obj fn = String2v("j"); obj st = listToCString(line); write(ustr(st), strlen(ustr(st))+1, fn); release(st); } void DoLatex(){ assert(0); } static int CRmode = 0; obj edit(obj fn){ // open edit save long bytes; obj rr = val(read(&bytes, (fn))); newLine(); line = CStringToLine(rr); MoveTo(LEFTMARGIN, startOfThisLine-viewPosition); drawLines(&line, true); MoveTo(cursorPosition.h, cursorPosition.v); while(! getKey(shiftCR)) ; addLineToText(List2v(line)); obj st = listToCString(line); write(ustr(st), strlen(ustr(st))+1, fn); release(st); return nil; } obj editline(obj v){ newLine(); line = CStringToLine(v); MoveTo(LEFTMARGIN, startOfThisLine-viewPosition); drawLines(&line, true); MoveTo(cursorPosition.h, cursorPosition.v); while(! getKey(onlyCR)) ; addLineToText(List2v(line)); baseLine = startOfThisLine-viewPosition; scrollBy(FONTSIZE*2+getNLine(line)*FONTSIZE); //改行します。 obj lin = listToCString(line); newLine(); return lin; } static void append(string*rs, char*s){ for(; *s; s++) appendS(rs, *s); } static void serialize(string*rs, list l, list end){ for(; l != end; l=rest(l)){ obj v = first(l); switch(type(v)){ case INT: appendS(rs, uint(v)); break; case SuperScript: appendS(rs, '^'); appendS(rs, '{'); serialize(rs, ul(v), nil); appendS(rs, '}'); break; case SubScript: appendS(rs, '_'); appendS(rs, '{'); serialize(rs, ul(v), nil); appendS(rs, '}'); break; case FRACTION: append(rs, "//{"); serialize(rs, ul(first(ul(v))), nil); append(rs, "}{"); serialize(rs, ul(second(ul(v))), nil); append(rs, "}"); break; default: assert(0); } } } obj listToCString(list l){ string rs = nullstr(); serialize(&rs, l, nil); return val(rs.s); } static char* clp; // static char* clpe; // end list csparse0(); list putchar(int c, list l){ if((c&0xff00)==0) { l = cons(Int(c), l); } else { l = cons(Int(c >> 8), l); l = cons(Int(c & 0xff), l); } return l; } list csparen(){ if(*clp != '{') { list l=putchar(readchar(clp), nil); clp = next(clp); return l; } clp++; list l = csparse0(); if(*clp != '}') ;//assert(0); else clp++; return l; } bool getchar(char**pp, int c){ if(readchar(*pp)!=c) return false; *pp = next(*pp); return true; } list csparse0(){ list l = nil; int bracelevel = 0; for(; *clp && clp!=clpe; ){ // if(readchar(clp) == '}') break; if(getchar(&clp, '^')){ assert(*clp); if(readchar(clp) != '{') continue; else l = cons(render(SuperScript, csparen()), l); } else if(getchar(&clp, '_')){ assert(*clp); if(readchar(clp) != '{') continue; else l = cons(render(SubScript, csparen()), l); } else if(get_pat((unsigned char**)&clp, "//")){ if(readchar(clp) != '{') continue; list nu = csparen(); list de = csparen(); l = cons(render(FRACTION, list2(List2v(nu), List2v(de))) ,l); } else { int c = readchar(clp); if( c =='{' ) bracelevel++; if( c =='}' ) {bracelevel--; if(bracelevel < 0) break;} l = putchar(c, l); clp = next(clp); } } return reverse(l); } list csparse(char* str, int len){ clp = str; clpe = clp+len; return csparse0(); } list CStringToLine(obj str){ assert(str->type==STRING); return csparse(ustr(str), strlen(ustr(str))); } void Redraw(){ for(list l=lines; l; l=rest(l)){ assert(type(first(l))==LIST); list aLine = ul(first(l)); int position = uint(second(aLine)); // obj hpos = snthOf(aLine,2); // if(hpos!=nil) h = uint(hpos); else h=LEFTMARGIN; int h; if(rest(rest(aLine))) h = uint(third(aLine)); else h = LEFTMARGIN;; MoveTo(h, position-viewPosition); drawObj(first(aLine)); } MoveTo(LEFTMARGIN, startOfThisLine-viewPosition); drawLines(&line, true); } /*int findBeginingOfThisLine(){ int pp=-1,p=0; assert(!insList); int i=0; for(list l=line; l && iupdate.bottom+FONTSIZE)) continue; continue; } if(drawFormula0(line, l, pos)){ if(rest(t)) release(rest(t)); // t->d = cons(dInt(pos), nil); // t=rest(t); vv += LINEHEIGHT; MoveTo(LEFTMARGIN+(colWidth+colSep)*col, vv); } if(line==*ins.curstr && pos==ins.pos) { // iru? GetPen(&cursorPosition); curBase = curbase; } if(vv > windowHeight) break; if(! l) return; } if(! l) return; vv += -windowHeight + FONTSIZE; MoveTo(LEFTMARGIN+(colWidth+colSep)*(col+1), vv); } }*/ /* void updateAround0(bool erase){ Rect r; r.left = LEFTMARGIN; r.right= LEFTMARGIN+colWidth; r.top = baseLine-FONTSIZE*3/2; r.bottom = baseLine+FONTSIZE; if(erase) EraseRect(&r); update = r; updateflag = true; MoveTo(LEFTMARGIN, startOfThisLine-viewPosition); drawLines(line, ins.pos, true); updateflag = false; }*/ /*int getWidth0(list string){ char buf[256]; buf[0]=0; int width=0; for(list l=string; l; l=rest(l)){ obj v = first(l); switch(type(v)){ case INT: int c = v2Int2(v); buf[++(*buf)] = v2Int2(v); if(c&0x80){ l=rest(l); if(! l) return width; //2 byte文字が1byteずつ挿入されるから c=v2Int2(first(l)); buf[++*buf]=c; } width += StringWidth((StringPtr)buf); *buf=0; break; case FRACTION: assert(0); // drawFraction(&(p->a)); break; case SubScript: break; case SuperScript: break; } } return width; }*/ //the lowest 2 bits // 00: others // 01: direct integer // 10: not used // 11: a character #define dVal 3 // mask #define idInt 1 #define idChar 3 //inline obj dInt(int i){return (obj)((i<<2)+1);} //inline int rInt(obj v){return (int)v>>2;}