%D \module
%D   [       file=mp-asnc.mpiv,
%D        version=2012.02.19, % was mp-core: 1999.08.01, anchoring
%D          title=\CONTEXT\ \METAPOST\ graphics,
%D       subtitle=anchored 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_asnc : endinput ; fi ;

boolean context_av ; context_asnc := true ;

% will be replaced

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 ;
