%D \module %D [ file=mp-core.mpiv, %D version=1999.08.01, % anchoring %D title=\CONTEXT\ \METAPOST\ graphics, %D subtitle=background macros, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. if known context_core : endinput ; fi ; boolean context_core ; context_core := true ; %D Copied to here .. not used any more. if unknown NOfTextColumns : numeric NOfTextColumns ; NOfTextColumns := 1 ; fi ; if unknown NOfTextAreas : numeric NOfTextAreas ; NOfTextAreas := 1 ; fi ; def SaveTextAreas = path SavedTextAreas [] ; path SavedTextColumns[] ; numeric NOfSavedTextAreas ; numeric NOfSavedTextColumns ; for i=1 upto NOfTextAreas : SavedTextAreas[i] := TextAreas[i] ; endfor ; for i=1 upto NOfTextColumns : SavedTextColumns[i] := TextColumns[i] ; endfor ; NOfSavedTextAreas := NOfTextAreas ; NOfSavedTextColumns := NOfTextColumns ; enddef ; def ResetTextAreas = path TextAreas[], TextColumns[], PlainTextArea, RegionTextArea ; numeric NOfTextAreas ; NOfTextAreas := 0 ; numeric NOfTextColumns ; NOfTextColumns := 0 ; numeric nofmultipars ; nofmultipars := 0 ; TextAreas[0] := TextColumns[0] := origin -- cycle ; enddef ; ResetTextAreas ; SaveTextAreas ; ; def RegisterTextArea (expr x, y, w, h, d) = begingroup ; save p ; path p ; p := unitsquare xyscaled(w,h+d) shifted (x,y-d) ; if NOfTextAreas>0 : % if needed, concatenate areas if (round(llcorner TextAreas[NOfTextAreas]) = round(ulcorner p)) and (round(lrcorner TextAreas[NOfTextAreas]) = round(urcorner p)) : p := ulcorner TextAreas[NOfTextAreas] -- urcorner TextAreas[NOfTextAreas] -- lrcorner p -- llcorner p -- cycle ; else : NOfTextAreas := NOfTextAreas + 1 ; fi ; else : NOfTextAreas := NOfTextAreas + 1 ; fi ; TextAreas[NOfTextAreas] := p ; if NOfTextColumns>0 : if (round(xpart llcorner TextColumns[NOfTextColumns]) = round(xpart ulcorner p)) and (round(xpart lrcorner TextColumns[NOfTextColumns]) = round(xpart urcorner p)) : p := ulcorner TextColumns[NOfTextColumns] -- urcorner TextColumns[NOfTextColumns] -- lrcorner p -- llcorner p -- cycle ; else : NOfTextColumns := NOfTextColumns + 1 ; fi ; else : NOfTextColumns := NOfTextColumns + 1 ; fi ; TextColumns[NOfTextColumns] := p ; endgroup ; enddef ; %D We store a local area in slot zero. def RegisterPlainTextArea(expr x,y,w,h,d) = PlainTextArea := unitsquare xyscaled(w,h+d) shifted (x,y-d) ; enddef ; def RegisterRegionTextArea(expr x,y,w,h,d) = RegionTextArea := unitsquare xyscaled(w,h+d) shifted (x,y-d) ; % RegionTextArea := RegionTextArea enlarged 2mm ; enddef ; def RegisterLocalTextArea (expr x, y, w, h, d) = TextAreas[0] := TextColumns[0] := unitsquare xyscaled(w,h+d) shifted (x,y-d) ; enddef ; def ResetLocalTextArea = TextAreas[0] := TextColumns[0] := origin -- cycle ; enddef ; ResetLocalTextArea ; vardef InsideTextArea (expr _i_, _xy_) = (round(xpart _xy_) >= round(xpart llcorner TextAreas[_i_])) and (round(xpart _xy_) <= round(xpart lrcorner TextAreas[_i_])) and (round(ypart _xy_) >= round(ypart llcorner TextAreas[_i_])) and (round(ypart _xy_) <= round(ypart urcorner TextAreas[_i_])) enddef ; vardef InsideSavedTextArea (expr _i_, _xy_) = (round(xpart _xy_) >= round(xpart llcorner SavedTextAreas[_i_])) and (round(xpart _xy_) <= round(xpart lrcorner SavedTextAreas[_i_])) and (round(ypart _xy_) >= round(ypart llcorner SavedTextAreas[_i_])) and (round(ypart _xy_) <= round(ypart urcorner SavedTextAreas[_i_])) enddef ; vardef InsideSomeTextArea (expr _xy_) = save ok ; boolean ok ; ok := false ; for i := 1 upto NOfTextAreas : if InsideTextArea(i,_xy_) : ok := true ; % we can move the exit here fi ; exitif ok ; endfor ; ok enddef ; vardef InsideSomeSavedTextArea (expr _xy_) = save ok ; boolean ok ; ok := false ; for i := 1 upto NOfSavedTextAreas : if InsideSavedTextArea(i,_xy_) : ok := true ; fi ; exitif ok ; endfor ; ok enddef ; vardef TextAreaX (expr x) = numeric _TextAreaX_ ; _TextAreaX_ := 0 ; for i := 1 upto NOfTextAreas : if (round(x) >= round(xpart llcorner TextAreas[i])) and (round(x) <= round(xpart lrcorner TextAreas[i])) : _TextAreaX_ := xpart llcorner TextAreas[i] ; fi ; endfor ; _TextAreaX_ enddef ; vardef TextAreaY (expr y) = numeric _TextAreaY_ ; _TextAreaY_ := 0 ; for i := 1 upto NOfTextAreas : if (round(y) >= round(ypart llcorner TextAreas[NOfTextAreas])) and (round(y) <= round(ypart ulcorner TextAreas[NOfTextAreas])) : _TextAreaY_ := ypart llcorner TextAreas[NOfTextAreas] ; fi ; endfor ; _TextAreaY_ enddef ; vardef TextAreaXY (expr x, y) = pair _TextAreaXY_ ; _TextAreaXY_ := origin ; for i := 1 upto NOfTextAreas : if (round(x) >= round(xpart llcorner TextAreas[i])) and (round(x) <= round(xpart lrcorner TextAreas[i])) and (round(y) >= round(ypart llcorner TextAreas[i])) and (round(y) <= round(ypart ulcorner TextAreas[i])) : _TextAreaXY_ := llconer TextAreas[i] ; fi ; endfor ; _TextAreaXY_ enddef ; vardef TextAreaW (expr x) = numeric _TextAreaW_ ; _TextAreaW_ := 0 ; for i := 1 upto NOfTextAreas : if (round(x) >= round(xpart llcorner TextAreas[i])) and (round(x) <= round(xpart lrcorner TextAreas[i])) : _TextAreaW_ := bbwidth(TextAreas[i]) ; fi ; endfor ; _TextAreaW_ enddef ; vardef TextAreaH (expr y) = numeric _TextAreaH_ ; _TextAreaH_ := 0 ; for i := 1 upto NOfTextAreas : if (round(y) >= round(ypart llcorner TextAreas[i])) and (round(y) <= round(ypart ulcorner TextAreas[i])) : _TextAreaH_ := bbheight(TextAreas[i]) ; fi ; endfor ; _TextAreaH_ enddef ; vardef TextAreaWH (expr x, y) = pair _TextAreaWH_ ; _TextAreaWH_ := origin ; for i := 1 upto NOfTextAreas : if (round(x) >= round(xpart llcorner TextAreas[i])) and (round(x) <= round(xpart lrcorner TextAreas[i])) and (round(y) >= round(ypart llcorner TextAreas[i])) and (round(y) <= round(ypart ulcorner TextAreas[i])) : _TextAreaWH_ := (bbwidth(TextAreas[i]),bbheight(TextAreas[i])) ; fi ; endfor ; _TextAreaWH_ enddef ; %D Till here. pair lxy[], rxy[], cxy[], llxy[], lrxy[], ulxy[], urxy[] ; path pxy[] ; numeric hxy[], wxy[], dxy[], nxy[] ; def box_found (expr n,x,y,w,h,d) = not ((x=0) and (y=0) and (w=0) and (h=0) and (d=0)) enddef ; def initialize_box_pos (expr pos,n,x,y,w,h,d) = pair lxy, rxy, cxy, llxy, lrxy, ulxy, urxy ; path pxy ; numeric hxy, wxy, dxy, nxy; lxy := (x,y) ; llxy := (x,y-d) ; lrxy := (x+w,y-d) ; urxy := (x+w,y+h) ; ulxy := (x,y+h) ; wxy := w ; hxy := h ; dxy := d ; rxy := lxy shifted (wxy,0) ; pxy := llxy--lrxy--urxy--ulxy--cycle ; cxy := center pxy ; nxy := n ; freeze_box(pos) ; enddef ; def freeze_box (expr pos) = lxy[pos] := lxy ; llxy[pos] := llxy ; lrxy[pos] := lrxy ; urxy[pos] := urxy ; ulxy[pos] := ulxy ; wxy[pos] := wxy ; hxy[pos] := hxy ; dxy[pos] := dxy ; rxy[pos] := rxy ; pxy[pos] := pxy ; cxy[pos] := cxy ; nxy[pos] := nxy ; enddef ; def initialize_box (expr n,x,y,w,h,d) = numeric bpos ; bpos := 0 ; initialize_box_pos(bpos,n,x,y,w,h,d) ; enddef ; def initialize_area (expr fn,fx,fy,fw,fh,fd, tn,tx,ty,tw,th,td) = numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ; numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ; do_initialize_area (fpos, tpos) ; enddef ; def do_initialize_area (expr fpos, tpos) = lxy := lxy[fpos] ; llxy := (xpart llxy[fpos], ypart llxy[tpos]) ; lrxy := lrxy[tpos] ; urxy := (xpart urxy[tpos], ypart urxy[fpos]) ; ulxy := ulxy[fpos] ; wxy := xpart lrxy - xpart llxy ; hxy := hxy[fpos] ; dxy := dxy[tpos] ; rxy := lxy shifted (wxy,0) ; pxy := llxy--lrxy--urxy--ulxy--cycle ; cxy := center pxy ; enddef ; def set_par_line_height (expr ph, pd) = par_strut_height := if ph>0 : ph elseif StrutHeight>0 : StrutHeight else : 8pt fi ; par_strut_depth := if pd>0 : pd elseif StrutDepth >0 : StrutDepth else : 3pt fi ; par_line_height := par_strut_height + par_strut_depth ; enddef ; def initialize_par (expr fn,fx,fy,fw,fh,fd, tn,tx,ty,tw,th,td, mn,mx,my,mw,mh,md, pn,px,py,pw,ph,pd, rw,rl,rr,rh,ra,ri) = numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ; numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ; numeric mpos ; mpos := 3 ; initialize_box_pos(mpos,mn,mx,my,mw,mh,md) ; numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ; numeric par_strut_height, par_strut_depth, par_line_height ; set_par_line_height (ph, pd) ; do_initialize_area (fpos, tpos) ; do_initialize_par (fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) ; enddef ; def initialize_area_par (expr fn,fx,fy,fw,fh,fd, tn,tx,ty,tw,th,td, wn,wx,wy,ww,wh,wd) = numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ; numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ; numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ; numeric par_strut_height, par_strut_depth, par_line_height ; set_par_line_height (wh, wd) ; numeric ffpos ; ffpos := 4 ; initialize_box_pos(ffpos,wn,wx,fy,0,wh,wd) ; numeric ttpos ; ttpos := 5 ; initialize_box_pos(ttpos,wn,wx+ww,ty,0,wh,wd) ; do_initialize_area (ffpos, ttpos) ; numeric mpos ; mpos := 6 ; freeze_box(mpos) ; do_initialize_par (fpos, tpos, mpos, ffpos, 0,0,0,0,0,0) ; enddef ; def do_initialize_par (expr fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) = pair lref, rref, pref, lhref, rhref ; % clip the page area to the left and right skips llxy[mpos] := llxy[mpos] shifted (+rl,0) ; lrxy[mpos] := lrxy[mpos] shifted (-rr,0) ; urxy[mpos] := urxy[mpos] shifted (-rr,0) ; ulxy[mpos] := ulxy[mpos] shifted (+rl,0) ; % fixate the leftskip, rightskip and hanging indentation lref := (xpart llxy[mpos],ypart ulxy[ppos]) ; lhref := lref shifted (rh,0) ; rref := (xpart lrxy[mpos],ypart urxy[ppos]) ; rhref := rref shifted (rh,0) ; pref := lxy[ppos] ; if nxy[tpos] > nxy[fpos] : if nxy[fpos] = nxy[mpos] : % first of multiple pages llxy[tpos] := llxy[mpos] ; lrxy[tpos] := lrxy[mpos] ; urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ; ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ; boxgriddirection := down ; elseif nxy[tpos] = nxy[mpos] : % last of multiple pages llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ; lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ; urxy[fpos] := urxy[mpos] ; ulxy[fpos] := ulxy[mpos] ; boxgriddirection := up ; else : % middle of multiple pages llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ; lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ; urxy[fpos] := urxy[mpos] ; ulxy[fpos] := ulxy[mpos] ; llxy[tpos] := llxy[mpos] ; lrxy[tpos] := lrxy[mpos] ; urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ; ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ; boxgriddirection := up ; fi ; else : % just one page boxgriddirection := up ; fi ; path txy, bxy, pxy, mxy ; txy := originpath ; % top bxy := originpath ; % bottom pxy := originpath ; % composed boolean lefthang, righthang, somehang ; % we only hang on the first of a multiple page background if nxy[mpos] > nxy[fpos] : lefthang := righthang := somehang := false ; else : lefthang := (rh>0) ; righthang := (rh<0) ; somehang := false ; fi ; if lefthang : mxy := boundingbox (lref -- lref shifted (rh,ra*par_line_height)) ; elseif righthang : mxy := boundingbox (rref -- rref shifted (rh,ra*par_line_height)) ; else : mxy := originpath ; fi ; if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) : % We have a one-liner. Watch how er use the bottom pos for % determining the height. llxy[fpos] := (xpart llxy[fpos], ypart llxy[tpos]) ; ulxy[fpos] := (xpart ulxy[fpos], ypart ulxy[tpos]) ; else : % We have a multi-liner. For convenience we now correct the % begin and end points for indentation. if lefthang and (round(ypart llxy[tpos]) >= round(ypart lrcorner mxy)) : llxy[tpos] := (xpart lhref, ypart llxy[tpos]) ; ulxy[tpos] := (xpart lhref, ypart ulxy[tpos]) ; else : llxy[tpos] := (xpart lref, ypart llxy[tpos]) ; ulxy[tpos] := (xpart lref, ypart ulxy[tpos]) ; fi ; if righthang and (round(ypart lrxy[fpos]) >= round(ypart llcorner mxy)) : lrxy[fpos] := (xpart rhref, ypart lrxy[fpos]) ; urxy[fpos] := (xpart rhref, ypart urxy[fpos]) ; else : lrxy[fpos] := (xpart rref, ypart lrxy[fpos]) ; urxy[fpos] := (xpart rref, ypart urxy[fpos]) ; fi ; fi ; somehang := (ypart ulxy[fpos]>ypart llcorner mxy) and (ypart llxy[tpos]0 : left_skip := rl + xpart llxy[wpos] - xpart llxy[ppos] ; right_skip := rw - left_skip - ww ; else : left_skip := rl ; right_skip := rr ; fi ; path multipar, multipars[] ; numeric multiref, multirefs[] ; numeric multiloc, multilocs[] ; % 1=begin 2=between 3=end numeric multi_par_pages ; multi_par_pages := nxy[tpos]-nxy[fpos]+1 ; % locals .. why can't i move these outside? vardef _pmp_set_multipar_ (expr i) = ( (TextAreas[i] leftenlarged -left_skip) rightenlarged (-right_skip if auto_multi_par_hsize : + rw - bbwidth(TextAreas[i]) fi) ) enddef ; vardef _pmp_snapped_multi_pos_ (expr p) = if snap_multi_par_tops : if abs(ypart p - ypart ulcorner multipar) < par_line_height : (xpart p,ypart ulcorner multipar) else : p fi else : p fi enddef ; vardef _pmp_estimated_par_lines_ (expr h) = round(h/par_line_height) enddef ; vardef _pmp_top_multi_par_(expr p) = (round(_pmp_estimated_par_lines_(bbheight(p)*par_line_height))=round(bbheight(p))) enddef ; vardef _pmp_multi_par_tsc_(expr p) = if _pmp_top_multi_par_(p) : TopSkipCorrection else : 0 fi enddef ; vardef _pmp_estimated_multi_par_height_ (expr n, t) = if round(par_line_height)=0 : 0 else : save ok, h ; boolean ok ; numeric h ; h := 0 ; ok := false ; if (nxy[fpos]=RealPageNumber-1) : for i := 1 upto NOfSavedTextAreas : if (InsideSavedTextArea(i,par_start_pos)) : ok := true ; h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner SavedTextAreas[i]) ; elseif ok : h := h + _pmp_estimated_par_lines_(bbheight(SavedTextAreas[i])) ; fi ; endfor ; fi ; if ok : for i := 1 upto n-1 : h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ; endfor ; else : % already: ok := false ; for i := 1 upto n-1 : if (InsideTextArea(i,par_start_pos)) : ok := true ; h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner TextAreas[i]) ; elseif ok : h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ; fi ; endfor ; fi ; h fi enddef ; vardef _pmp_left_top_hang_ (expr same_area) = par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ; if (par_hang_indent>0) and (par_hang_after<0) and obey_multi_par_hang : pair _ul_ ; _ul_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])); pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ; if same_area : _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llxy[tpos])) ; fi ; if obey_multi_par_more and (round(par_line_height)>0) : par_hang_after := min(0,round(par_hang_after + (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; fi ; (xpart _ul_ + par_hang_indent, ypart lrxy[fpos]) -- (xpart _ul_ + par_hang_indent, ypart _pa_) -- (xpart ulcorner multipar, ypart _pa_) else : (xpart ulcorner multipar, ypart lrxy[fpos]) fi enddef ; vardef _pmp_right_top_hang_ (expr same_area) = par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ; if (par_hang_indent<0) and (par_hang_after<0) and obey_multi_par_hang : pair _ur_ ; _ur_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ; pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ; if same_area : _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ; fi ; if obey_multi_par_more and (round(par_line_height)>0) : par_hang_after := min(0,round(par_hang_after + (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; fi ; (xpart urcorner multipar, ypart _pa_) -- (xpart _ur_ + par_hang_indent, ypart _pa_) -- (xpart _ur_ + par_hang_indent, ypart _pmp_snapped_multi_pos_(urxy[fpos])) else : (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) fi enddef ; vardef _pmp_x_left_top_hang_ (expr i, t) = par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ; if (par_hang_indent>0) and (par_hang_after<0) : pair _ul_ ; _ul_ := ulcorner multipar ; pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; if t : _pa_ := (xpart _pa_,max(ypart _pa_,ypart llxy[tpos])); fi ; if abs(ypart _pa_-ypart llxy[tpos])0) and (par_hang_after>0) and obey_multi_par_hang : _ll_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])) ; _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; if same_area : _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; fi ; if obey_multi_par_more and (round(par_line_height)>0) : par_hang_after := max(0,round(par_hang_after - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; fi ; _pa_ -- (xpart _pa_ + par_hang_indent,ypart _pa_) -- (xpart _pa_ + par_hang_indent,ypart _sa_) else : (xpart llcorner multipar, ypart _sa_) fi enddef ; vardef _pmp_right_bottom_hang_ (expr same_area) = pair _lr_, _sa_, _pa_ ; _sa_ := if same_area : _pmp_snapped_multi_pos_(ulxy[tpos]) else : lrcorner multipar fi ; if (par_hang_indent<0) and (par_hang_after>0) and obey_multi_par_hang : _lr_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ; _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; if same_area : _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ; fi ; if obey_multi_par_more and (round(par_line_height)>0) : par_hang_after := max(0,round(par_hang_after - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; fi ; (xpart _pa_ + par_hang_indent,ypart _sa_) -- (xpart _pa_ + par_hang_indent,ypart _pa_) -- _pa_ else : (xpart lrcorner multipar, ypart _sa_) fi enddef ; vardef _pmp_x_left_bottom_hang_ (expr i, t) = pair _ll_, _sa_, _pa_ ; _sa_ := if t : llxy[tpos] else : llcorner multipar fi ; if (par_hang_indent>0) and (ra>0) : par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i,t)) ; _ll_ := ulcorner multipar ; _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; % we need to compensate for topskip enlarged areas if abs(ypart _pa_ - ypart _sa_) > par_line_height : (xpart _pa_ + par_hang_indent,ypart _sa_) -- (xpart _pa_ + par_hang_indent,ypart _pa_) -- fi _pa_ else : (xpart llcorner multipar, ypart _sa_) fi enddef ; vardef _pmp_x_right_bottom_hang_ (expr i, t) = pair _lr_, _sa_, _pa_ ; _sa_ := if t : _pmp_snapped_multi_pos_(ulxy[tpos]) else : llcorner multipar fi ; if (par_hang_indent<0) and (ra>0) : par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i, t)) ; _lr_ := urcorner multipar ; _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; % we need to compensate for topskip enlarged areas _pa_ if abs(ypart _pa_ - ypart _sa_) > par_line_height : -- (xpart _pa_ + par_hang_indent,ypart _pa_) -- (xpart _pa_ + par_hang_indent,ypart _sa_) fi else : (xpart lrcorner multipar, ypart _sa_) fi enddef ; % def _pmp_test_multipar_ = % multipar := boundingbox multipar ; % enddef ; % first loop ii := 0 ; nn := NOfTextAreas+1 ; nofmultipars := 0 ; if enable_multi_par_fallback and (nxy[fpos]=RealPageNumber) and (nxy[tpos]=RealPageNumber) and not (InsideSomeTextArea(lxy[fpos]) and InsideSomeTextArea(rxy[tpos])) : % fallback % multipar := % llxy[fpos] -- % lrxy[tpos] -- % urxy[tpos] -- % ulxy[fpos] -- cycle ; % % save_multipar (1,1,multipar) ; % we need to take the boundingbox because there can be % more lines and we want a proper rectange multipar := ulxy[fpos] -- urxy[tpos] -- lrxy[fpos] -- llxy[tpos] -- cycle ; save_multipar (1,1,boundingbox(multipar)) ; else : % normal for i=1 upto NOfTextAreas : TopSkipCorrection := 0 ; multipar := _pmp_set_multipar_(i) ; % watch how we compensate for negative indentation if (nxy[fpos]=RealPageNumber) and (InsideTextArea(i,par_start_pos)) : % first one in chain ii := i ; if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) : % in same area nn := i ; if compensate_multi_par_topskip and (round(LineHeight-ph-pd)=0) : TopSkipCorrection := TopSkip - StrutHeight ; if round(ypart ulxy[fpos] + TopSkipCorrection) = round(ypart ulcorner TextAreas[i]) : ulxy[fpos] := ulxy[fpos] shifted (0,TopSkipCorrection) ; urxy[fpos] := urxy[fpos] shifted (0,TopSkipCorrection) ; else : TopSkipCorrection := 0 ; fi ; fi ; if ypart llxy[fpos] = ypart llxy[tpos] : multipar := llxy[fpos] -- lrxy[tpos] -- _pmp_snapped_multi_pos_(urxy[tpos]) -- _pmp_snapped_multi_pos_(ulxy[fpos]) -- cycle ; save_multipar (i,1,multipar) ; elseif (ypart llxy[fpos] = ypart ulxy[tpos]) and (xpart llxy[tpos] < xpart llxy[fpos]) : % two loners multipar := if obey_multi_par_hang : _pmp_right_bottom_hang_(true) -- _pmp_right_top_hang_(true) -- _pmp_snapped_multi_pos_(urxy[fpos]) -- lrxy[fpos] -- else : llxy[fpos] -- (xpart urcorner multipar, ypart llxy[fpos]) -- (xpart urcorner multipar, ypart ulxy[fpos]) -- _pmp_snapped_multi_pos_(ulxy[fpos]) -- fi cycle ; save_multipar (i,1,multipar) ; multipar := _pmp_set_multipar_(i) ; multipar := if obey_multi_par_hang : _pmp_left_bottom_hang_(true) -- llxy[tpos] -- _pmp_snapped_multi_pos_(ulxy[tpos]) -- _pmp_left_top_hang_(true) -- else : (xpart llcorner multipar, ypart llxy[tpos]) -- llxy[tpos] -- _pmp_snapped_multi_pos_(ulxy[tpos]) -- (xpart llcorner multipar, ypart ulxy[tpos]) -- fi cycle ; save_multipar (i,1,multipar) ; else : multipar := if obey_multi_par_hang : _pmp_left_bottom_hang_(true) -- llxy[tpos] -- _pmp_snapped_multi_pos_(ulxy[tpos]) -- _pmp_right_bottom_hang_(true) -- _pmp_right_top_hang_(true) -- _pmp_snapped_multi_pos_(urxy[fpos]) -- lrxy[fpos] -- _pmp_left_top_hang_(true) -- else : (xpart llcorner multipar, ypart llxy[tpos]) -- llxy[tpos] -- _pmp_snapped_multi_pos_(ulxy[tpos]) -- (xpart lrcorner multipar, ypart ulxy[tpos]) -- (xpart urcorner multipar, ypart urxy[fpos]) -- _pmp_snapped_multi_pos_(urxy[fpos]) -- lrxy[fpos] -- (xpart ulcorner multipar, ypart lrxy[fpos]) -- fi cycle ; save_multipar (i,1,multipar) ; fi ; else : multipar := if obey_multi_par_hang : _pmp_left_bottom_hang_(false) -- _pmp_right_bottom_hang_(false) -- _pmp_right_top_hang_(false) -- _pmp_snapped_multi_pos_(urxy[fpos]) -- lrxy[fpos] -- _pmp_left_top_hang_(false) -- else : llcorner multipar -- lrcorner multipar -- (xpart urcorner multipar, ypart urxy[fpos]) -- _pmp_snapped_multi_pos_(urxy[fpos]) -- lrxy[fpos] -- (xpart ulcorner multipar, ypart lrxy[fpos]) -- fi cycle ; save_multipar (i,1,multipar) ; fi ; elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) : % last one in chain nn := i ; if obey_multi_par_hang and obey_multi_par_more : multipar := _pmp_x_left_top_hang_(i,true) -- _pmp_x_right_top_hang_(i,true) -- _pmp_x_right_bottom_hang_(i,true) -- _pmp_snapped_multi_pos_(ulxy[tpos]) -- llxy[tpos] -- _pmp_x_left_bottom_hang_(i,true) -- cycle ; else : multipar := ulcorner multipar -- urcorner multipar -- (xpart lrcorner multipar, ypart urxy[tpos]) -- _pmp_snapped_multi_pos_(ulxy[tpos]) -- llxy[tpos] -- (xpart llcorner multipar, ypart llxy[tpos]) -- cycle ; fi ; save_multipar (i,3,multipar) ; elseif multi_column_first_page_hack and ((nxy[fpos]=RealPageNumber) and (nxy[tpos]>=RealPageNumber) and (NOfTextColumns>1)) : save_multipar (i,2,multipar) ; else : % handled later fi ; endfor ; % second loop if force_multi_par_chain or (ii > 1) : for i=ii+1 upto nn-1 : % rest of chain / todo : hang % hm, the second+ column in column sets now gets lost in a NOfTextColumns if (not check_multi_par_chain) or ((nxy[fpos]RealPageNumber)) : multipar := _pmp_set_multipar_(i) ; if obey_multi_par_hang and obey_multi_par_more : multipar := _pmp_x_left_top_hang_(i,false) -- _pmp_x_right_top_hang_(i,false) -- _pmp_x_right_bottom_hang_(i,false) -- _pmp_x_left_bottom_hang_(i,false) -- cycle ; fi ; save_multipar(i,2,multipar) ; fi ; endfor ; fi ; % end of normal/fallback fi ; if span_multi_column_pars : endgroup ; fi ; % potential safeguard: % for i=1 upto nofmultipars : % if length p <= 4 : % multipars[i] := boundingbox(multipars[i]) ; % fi ; % end ; % quick hack for gb: one_piece_multi_par := (nofmultipars=1) and (pn=tn) ; enddef ; def boxgridoptions = withcolor .8red enddef ; def boxlineoptions = withcolor .8blue enddef ; def boxfilloptions = withcolor .8white enddef ; numeric boxgridtype ; boxgridtype := 0 ; numeric boxlinetype ; boxlinetype := 1 ; numeric boxfilltype ; boxfilltype := 1 ; numeric boxdashtype ; boxdashtype := 0 ; pair boxgriddirection ; boxgriddirection := up ; numeric boxgridwidth ; boxgridwidth := 1pt ; numeric boxlinewidth ; boxlinewidth := 1pt ; numeric boxlineradius ; boxlineradius := 0pt ; numeric boxfilloffset ; boxfilloffset := 0pt ; numeric boxgriddistance ; boxgriddistance := .5cm ; numeric boxgridshift ; boxgridshift := 0pt ; % def draw_box = % draw pxy boxlineoptions withpen pencircle scaled boxlinewidth ; % draw lxy -- rxy boxlineoptions withpen pencircle scaled boxgridwidth ; % enddef ; def draw_par = % 1 2 3 11 12 do_draw_par(pxy) ; do_draw_par(txy) ; do_draw_par(bxy) ; for i = pxy, txy, bxy : if boxgridtype = 1 : boxgriddirection := origin ; draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ; elseif boxgridtype = 2 : boxgriddirection := origin ; draw baseline_grid (i,boxgriddirection,false) boxgridoptions ; elseif boxgridtype = 3 : boxgriddirection := origin ; draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ; draw baseline_grid (i,boxgriddirection,true ) shifted (0,ExHeight) boxgridoptions ; elseif boxgridtype = 4 : boxgriddirection := origin ; draw baseline_grid (i,boxgriddirection,true ) shifted (0,ExHeight/2) boxgridoptions ; elseif boxgridtype = 11 : draw graphic_grid(i,boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ; elseif boxgridtype = 12 : draw graphic_grid(i,boxgriddistance,boxgriddistance,0,0) ; fi ; endfor ; enddef ; def do_show_par (expr p, r, c) = if length(p) > 2 : for i=0 upto length(p) : draw fullcircle scaled r shifted point i of p withpen pencircle scaled .5pt withcolor c ; endfor ; fi ; draw p withpen pencircle scaled .5pt withcolor c ; enddef ; def show_par = if length(mxy) > 2 : draw mxy dashed evenly withpen pencircle scaled .5pt withcolor .5white ; fi ; do_show_par(txy, 4pt, .5green) ; do_show_par(bxy, 6pt, .5blue ) ; do_show_par(pxy, 8pt, .5red ) ; draw pref withpen pencircle scaled 2pt ; enddef ; def sort_multi_pars = if nofmultipars>1 : begingroup ; save _p_, _n_ ; path _p_ ; numeric _n_ ; for i := 1 upto nofmultipars : if multilocs[i] = 3 : _p_ := multipars[nofmultipars] ; multipars[nofmultipars] := multipars[i] ; multipars[i] := _p_ ; _n_ := multirefs[nofmultipars] ; multirefs[nofmultipars] := multirefs[i] ; multirefs[i] := _n_ ; _n_ := multilocs[nofmultipars] ; multilocs[nofmultipars] := multilocs[i] ; multilocs[i] := _n_ ; fi ; endfor ; endgroup ; fi ; enddef ; def collapse_multi_pars = if nofmultipars>1 : begingroup ; save _nofmultipars_ ; numeric _nofmultipars_ ; _nofmultipars_ := 1 ; sort_multi_pars ; % block not in order: 1, 3, 2.... for i:=1 upto nofmultipars-1 : if (round(xpart(llcorner multipars[i]-llcorner multipars[i+1]))=0) and (round(xpart(lrcorner multipars[i]-lrcorner multipars[i+1]))=0) : multilocs[_nofmultipars_] := multilocs[i+1] ; multirefs[_nofmultipars_] := multirefs[i+1] ; multipars[_nofmultipars_] := ulcorner multipars[_nofmultipars_] -- urcorner multipars[_nofmultipars_] -- lrcorner multipars[i+1] -- llcorner multipars[i+1] -- cycle ; else : _nofmultipars_ := _nofmultipars_ + 1 ; multipars[_nofmultipars_] := multipars[i+1] ; multilocs[_nofmultipars_] := multilocs[i+1] ; multirefs[_nofmultipars_] := multirefs[i+1] ; fi ; endfor ; nofmultipars := _nofmultipars_ ; endgroup ; fi ; enddef ; def draw_multi_pars = for i=1 upto nofmultipars : do_draw_par(multipars[i]) ; if boxgridtype= 1 : draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; elseif boxgridtype= 2 : draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,false) ; elseif boxgridtype= 3 : draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ; elseif boxgridtype= 4 : draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ; elseif boxgridtype=11 : draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ; elseif boxgridtype=12 : draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ; fi ; endfor ; enddef ; def show_multi_pars = for i=1 upto nofmultipars : do_show_par(multipars[i], 6pt, .5blue) ; endfor ; enddef ; vardef do_draw_par (expr p) = if (length p>2) and (bbwidth(p)>1) and (bbheight(p)>1) : save pp ; path pp ; if (boxlineradius>0) and (boxlinetype=2) : pp := p cornered boxlineradius ; else : pp := p ; fi ; if boxfilltype>0 : if boxfilloffset>0 : % temporary hack begingroup ; interim linejoin := mitered ; filldraw pp boxfilloptions withpen pencircle scaled (2*boxfilloffset) ; endgroup ; else : fill pp boxfilloptions ; fi ; fi ; if boxlinetype>0 : draw pp boxlineoptions withpen pencircle scaled boxlinewidth ; fi ; fi ; enddef ; vardef baseline_grid (expr pxy, pdir, at_baseline) = save width ; width := bbwidth(pxy) ; save height ; height := bbheight(pxy) ; if (par_line_height>0) and (height>1) and (width>1) and (boxgridwidth>0) : save i, grid, bb ; picture grid ; pair start ; path bb ; def _do_ (expr start) = % 1 = normal, 2 = with background (i.e. no shine-through) if boxdashtype = 2 : draw start -- start shifted (width,0) withpen pencircle scaled boxgridwidth boxfilloptions ; fi ; draw start -- start shifted (width,0) if boxdashtype > 0 : dashed evenly fi withpen pencircle scaled boxgridwidth boxgridoptions ; enddef ; grid := image ( % fails with inlinespace if pdir=up : for i = if at_baseline : par_strut_depth else : 0 fi step par_line_height until max(height,par_line_height) : _do_ (llcorner pxy shifted (0,+i)) ; endfor ; else : for i = if at_baseline : par_strut_height else : 0 fi step par_line_height until height : _do_ (ulcorner pxy shifted (0,-i)) ; endfor ; fi ; ) ; clip grid to pxy ; bb := boundingbox grid ; grid := grid shifted (0,boxgridshift) ; setbounds grid to bb ; grid else : nullpicture fi enddef ; vardef graphic_grid (expr pxy, dx, dy, x, y) = if (bbheight(pxy)>dy) and (bbwidth(pxy)>dx) and (boxgridwidth>0) : save grid ; picture grid ; grid := image ( for i = xpart llcorner pxy step dx until xpart lrcorner pxy : draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy) withpen pencircle scaled boxgridwidth ; endfor ; for i = ypart llcorner pxy step dy until ypart ulcorner pxy : draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i) withpen pencircle scaled boxgridwidth ; endfor ) shifted (x,y) ; clip grid to pxy ; grid else : nullpicture fi enddef ; def anchor_box (expr n,x,y,w,h,d) = currentpicture := currentpicture shifted (-x,-y) ; enddef ; let draw_area = draw_box ; let anchor_area = anchor_box ; let anchor_par = anchor_box ; numeric sync_n[], sync_p[][], sync_w[][], sync_h[][], sync_d[][], sync_t[][] ; pair sync_xy[][] ; color sync_c[][] ; def ResetSyncTasks = path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ; NOfSyncPaths := CurrentSyncClass := 0 ; if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0 ; fi ; if unknown SyncWidth : numeric SyncWidth ; SyncWidth := 0 ; fi ; if unknown SyncThreshold : numeric SyncThreshold ; SyncThreshold := LineHeight ; fi ; if unknown SyncColor : color SyncColor ; SyncColor := .5white ; fi ; if (SyncLeftOffset = 0) and (SyncWidth = 0) : SyncWidth := if known TextWidth : TextWidth else : -1cm fi ; fi ; enddef ; ResetSyncTasks ; vardef SyncBox(expr n, i, leftoffset, width, topoffset, bottomoffset) = save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ; o shifted (leftoffset,sync_h[n][i]+topoffset) -- o shifted (width+leftoffset,sync_h[n][i]+topoffset) -- o shifted (width+leftoffset,bottomoffset) -- o shifted (leftoffset,bottomoffset) -- cycle enddef ; def SetSyncColor(expr n, i, c) = sync_c[n][i] := c ; enddef ; def SetSyncThreshold(expr n, i, th) = sync_th[n][i] := th ; enddef ; vardef TheSyncColor(expr n, i) = if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi enddef ; vardef TheSyncThreshold(expr n, i) = if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi enddef ; vardef PrepareSyncTasks(expr n, collapse, extendtop, prestartnext) = ResetSyncTasks ; if known sync_n[n] : CurrentSyncClass := n ; save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ; for i=1 upto sync_n[n] : if RealPageNumber > sync_p[n][i] : l := i ; elseif RealPageNumber = sync_p[n][i] : NOfSyncPaths := NOfSyncPaths + 1 ; if not ok : if i>1 : if sync_t[n][i-1] = sync_t[n][i] : SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; SyncTasks[NOfSyncPaths] := i ; else : SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; SyncTasks[NOfSyncPaths] := i-1 ; NOfSyncPaths := NOfSyncPaths + 1 ; SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; SyncTasks[NOfSyncPaths] := i ; fi ; else : SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; SyncTasks[NOfSyncPaths] := i ; fi ; else : SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; SyncTasks[NOfSyncPaths] := i ; fi ; ok := true ; fi ; endfor ; if (NOfSyncPaths = 0) and (l > 0) : NOfSyncPaths := 1 ; SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; SyncTasks[NOfSyncPaths] := l ; fi ; if NOfSyncPaths > 0 : for i = 1 upto NOfSyncPaths-1 : SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ; endfor ; if unknown SyncThresholdMethod : numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ; fi ; if extendtop : if SyncThresholdMethod = 1 : if NOfSyncPaths>1 : d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ; if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) : SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ; fi ; fi ; else : for i = 1 upto NOfSyncPaths : d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ; if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) : SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ; fi ; endfor ; fi ; fi ; if prestartnext : if NOfSyncPaths>1 : if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ; if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) : SyncPaths[NOfSyncPaths+1] := (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) -- (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) -- lrcorner SyncPaths[NOfSyncPaths] -- llcorner SyncPaths[NOfSyncPaths] -- cycle ; SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ; NOfSyncPaths := NOfSyncPaths + 1 ; fi ; fi ; fi ; else : if NOfSyncPaths>1 : d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ; if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) : NOfSyncPaths := NOfSyncPaths - 1 ; SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ; fi ; fi ; fi ; if (NOfSyncPaths>1) and collapse : save j ; numeric j ; j := 1 ; for i = 2 upto NOfSyncPaths : if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] : SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ; SyncTasks[j] := SyncTasks[i] ; else : j := j + 1 ; SyncPaths[j] := SyncPaths[i] ; SyncTasks[j] := SyncTasks[i] ; fi ; endfor ; NOfSyncPaths := j ; fi ; fi ; fi ; enddef ; def SyncTask(expr n) = if known SyncTasks[n] : SyncTasks[n] else : 0 fi enddef ; def FlushSyncTasks = for i = 1 upto NOfSyncPaths : ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ; endfor ; enddef ; def ProcessSyncTask(expr p, c) = fill p withcolor c ; enddef ;