. "$_EXEC/acl.sh"
 . "$_EXEC/tools.sh"
 
-from='1'; to='$'; rev=''; items='$'; hl=0; link='true'; depth=0; tags=''; page='';
+from='1'; to='$'; rev=''; items='$'; hl=0; link='true'; depth=0; tags=''; ntags=''; page='';
 
 set -- "$@" --
 while [ $# -gt 0 ]; do case $1 in
   --hl|-hl) hl=$2; shift 2;;
   --depth) depth=$2; shift 2;;
   \#*) tags="${tags}${tags:+ }${1}"; shift 1;;
+  \!*) ntags="${ntags}${ntags:+ }${1}"; shift 1;;
   --) shift 1; break;;
   *) set -- "$@" "$1"; shift 1;;
 esac; done
   mdfile="$(mdfile "$page")" || continue
   acl_read "$page" || continue
   has_tags "$page" $tags || continue
+  has_tag "$page" $ntags && continue
   printf %s\\n "$INCLUDE_LIST" |grep -qxF "$page" && continue
   export INCLUDE_LIST="${INCLUDE_LIST}${INCLUDE_LIST:+${BR}}$page"
   hglob="$(HTML "$glob")"
 
 . "$_EXEC/acl.sh"
 . "$_EXEC/tools.sh"
 
-tags='' dir='' depth='' glob_system_pages=false
+tags='' ntags='' dir='' depth='' glob_system_pages=false
 label='' labeltype='' altlabel='' cnt=0
 
 set -- "$@" --
   --system) glob_system_pages=true; shift 1;;
   --depth)  depth="$2" shift 2;;
   \#*) tags="${tags}${tags:+ }${1###}"; shift 1;;
+  \!*) ntags="${ntags}${ntags:+ }${1##!}"; shift 1;;
   --h1|--h2|--h3|--h4|--h5|--h6|--label)
     labeltype="${1#--}" label="$2"; shift 2;;
   --alt-label)
     if [ -f "$_DATA/pages/${pagedir}/#page.md" -o \
          -f "$_EXEC/pages/${pagedir}/#page.md" ] \
        && acl_read "$pagedir" \
-       && has_tags "$pagedir" $tags
+       && has_tags "$pagedir" $tags \
+       && ! has_tag "$pagedir" $ntags
     then
       [ "$cnt" -eq 0 -a "$label" ] \
       && printf '<%s class="macro pagelist label">%s</%s>' \
 
 }
 
 has_tags() {
+  # true if PAGE is tagges with all TAGS
   local page="$(page_abs "$1")"; shift 1;
   local tdir="$_DATA/tags" tag dt df
 
   for tag in "$@"; do
-    tag="$(printf %s "$tag" |awk '{ sub(/^#/, ""); gsub(/[^[:alnum:]]/, "_"); print toupper($0); }')"
+    tag="$(printf %s "$tag" |awk '{ sub(/^[#!]/, ""); gsub(/[^[:alnum:]]/, "_"); print toupper($0); }')"
     dt="$(DBM "${tdir}/${tag}" get "${page}")" || return 1
     df="$(stat -c %Y "$(mdfile "$page")")" || return 1
     if [ "$df" -gt "$dt" ]; then
   done
   return 0
 }
+
+has_tag() {
+  # true if PAGE is tagged with any of TAGS
+  local page="$(page_abs "$1")"; shift 1;
+  local tdir="$_DATA/tags" tag dt df
+
+  for tag in "$@"; do
+    tag="$(printf %s "$tag" |awk '{ sub(/^[#!]/, ""); gsub(/[^[:alnum:]]/, "_"); print toupper($0); }')"
+    dt="$(DBM "${tdir}/${tag}" get "${page}")" || continue
+    df="$(stat -c %Y "$(mdfile "$page")")" || return 1
+    if [ "$df" -gt "$dt" ]; then
+      DBM "${tdir}/${tag}" remove "${page}"
+      continue
+    else
+      return 0
+    fi
+  done
+  return 1
+}