Index: inc/core/class.dc.blog.php
===================================================================
--- inc/core/class.dc.blog.php	(revision 3874)
+++ inc/core/class.dc.blog.php	(revision 3965)
@@ -457,4 +457,29 @@
     {
         return $this->getCategories(['start' => $id, 'level' => $id == 0 ? 1 : 2]);
+    }
+
+    /**
+     * Returns true if a given category if in a given category's subtree
+     *
+     * @param      string   $cat_url    The cat url
+     * @param      string   $start_url  The top cat url
+     *
+     * @return     boolean  true if cat_url is in given start_url cat subtree
+     */
+    public function IsInCatSubtree($cat_url, $start_url)
+    {
+        // Get cat_id from start_url
+        $cat = $this->getCategories(['cat_url' => $start_url]);
+        if ($cat->fetch()) {
+            // cat_id found, get cat tree list
+            $cats = $this->getCategories(['start' => $cat->cat_id]);
+            while ($cats->fetch()) {
+                // check if post category is one of the cat or sub-cats
+                if ($cats->cat_url === $cat_url) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
Index: inc/core/class.dc.rs.extensions.php
===================================================================
--- inc/core/class.dc.rs.extensions.php	(revision 3874)
+++ inc/core/class.dc.rs.extensions.php	(revision 3965)
@@ -457,4 +457,17 @@
         }
     }
+
+    /**
+     * Returns true if current category if in given cat_url subtree
+     *
+     * @param      record   $rs       Invisible parameter
+     * @param      string   $cat_url  The cat url
+     *
+     * @return     boolean  true if current cat is in given cat subtree
+     */
+    public static function underCat($rs, $cat_url)
+    {
+        return $rs->core->blog->IsInCatSubtree($rs->cat_url, $cat_url);
+    }
 }
 
Index: inc/public/class.dc.template.php
===================================================================
--- inc/public/class.dc.template.php	(revision 3874)
+++ inc/public/class.dc.template.php	(revision 3965)
@@ -243,5 +243,5 @@
 
         # --BEHAVIOR-- templateInsideBlock
-        $this->core->callBehavior('templateInsideBlock', $this->core, $this->current_tag, $attr, [&$content]);
+        $this->core->callBehavior('templateInsideBlock', $this->core, $this->current_tag, $attr, [ & $content]);
 
         $res .= parent::compileBlockNode($this->current_tag, $attr, $content);
@@ -967,10 +967,21 @@
 
         if (isset($attr['url'])) {
-            $url = addslashes(trim($attr['url']));
+            $url  = addslashes(trim($attr['url']));
+            $args = preg_split('/\s*[?]\s*/', $url, -1, PREG_SPLIT_NO_EMPTY);
+            $url  = array_shift($args);
+            $args = array_flip($args);
             if (substr($url, 0, 1) == '!') {
-                $url  = substr($url, 1);
-                $if[] = '($_ctx->categories->cat_url != "' . $url . '")';
+                $url = substr($url, 1);
+                if (isset($args['sub'])) {
+                    $if[] = '(!$core->blog->IsInCatSubtree($_ctx->categories->cat_url, "' . $url . '"))';
+                } else {
+                    $if[] = '($_ctx->categories->cat_url != "' . $url . '")';
+                }
             } else {
-                $if[] = '($_ctx->categories->cat_url == "' . $url . '")';
+                if (isset($args['sub'])) {
+                    $if[] = '($core->blog->IsInCatSubtree($_ctx->categories->cat_url, "' . $url . '"))';
+                } else {
+                    $if[] = '($_ctx->categories->cat_url == "' . $url . '")';
+                }
             }
         }
@@ -980,9 +991,20 @@
             if (is_array($urls) && count($urls)) {
                 foreach ($urls as $url) {
+                    $args = preg_split('/\s*[?]\s*/', trim($url), -1, PREG_SPLIT_NO_EMPTY);
+                    $url  = array_shift($args);
+                    $args = array_flip($args);
                     if (substr($url, 0, 1) == '!') {
-                        $url  = substr($url, 1);
-                        $if[] = '($_ctx->categories->cat_url != "' . $url . '")';
+                        $url = substr($url, 1);
+                        if (isset($args['sub'])) {
+                            $if[] = '(!$core->blog->IsInCatSubtree($_ctx->categories->cat_url, "' . $url . '"))';
+                        } else {
+                            $if[] = '($_ctx->categories->cat_url != "' . $url . '")';
+                        }
                     } else {
-                        $if[] = '($_ctx->categories->cat_url == "' . $url . '")';
+                        if (isset($args['sub'])) {
+                            $if[] = '($core->blog->IsInCatSubtree($_ctx->categories->cat_url, "' . $url . '"))';
+                        } else {
+                            $if[] = '($_ctx->categories->cat_url == "' . $url . '")';
+                        }
                     }
                 }
@@ -1325,9 +1347,20 @@
         if (isset($attr['category'])) {
             $category = addslashes(trim($attr['category']));
+            $args     = preg_split('/\s*[?]\s*/', $category, -1, PREG_SPLIT_NO_EMPTY);
+            $category = array_shift($args);
+            $args     = array_flip($args);
             if (substr($category, 0, 1) == '!') {
                 $category = substr($category, 1);
-                $if[]     = '($_ctx->posts->cat_url != "' . $category . '")';
+                if (isset($args['sub'])) {
+                    $if[] = '(!$_ctx->posts->underCat("' . $category . '"))';
+                } else {
+                    $if[] = '($_ctx->posts->cat_url != "' . $category . '")';
+                }
             } else {
-                $if[] = '($_ctx->posts->cat_url == "' . $category . '")';
+                if (isset($args['sub'])) {
+                    $if[] = '($_ctx->posts->underCat("' . $category . '"))';
+                } else {
+                    $if[] = '($_ctx->posts->cat_url == "' . $category . '")';
+                }
             }
         }
@@ -1337,9 +1370,20 @@
             if (is_array($categories) && count($categories)) {
                 foreach ($categories as $category) {
+                    $args     = preg_split('/\s*[?]\s*/', trim($category), -1, PREG_SPLIT_NO_EMPTY);
+                    $category = array_shift($args);
+                    $args     = array_flip($args);
                     if (substr($category, 0, 1) == '!') {
                         $category = substr($category, 1);
-                        $if[]     = '($_ctx->posts->cat_url != "' . $category . '")';
+                        if (isset($args['sub'])) {
+                            $if[] = '(!$_ctx->posts->underCat("' . $category . '"))';
+                        } else {
+                            $if[] = '($_ctx->posts->cat_url != "' . $category . '")';
+                        }
                     } else {
-                        $if[] = '($_ctx->posts->cat_url == "' . $category . '")';
+                        if (isset($args['sub'])) {
+                            $if[] = '($_ctx->posts->underCat("' . $category . '"))';
+                        } else {
+                            $if[] = '($_ctx->posts->cat_url == "' . $category . '")';
+                        }
                     }
                 }
