-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
- client_time_heap.c for the Openbox window manager
- Copyright (c) 2006 Mikael Magnusson
- Copyright (c) 2003-2007 Dana Jansens
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#include "client_time_heap.h"
-#include "client.h"
-
-#include <X11/Xlib.h>
-
-/* Helper functions for the heap */
-
-#define isroot(n) (n == 0)
-#define parent(n) ((n-1)/2)
-#define right(n) ((n+1)*2)
-#define left(n) (right(n)-1)
-#define exists(n) (n < h->nodes->len)
-#define key(n) (((ObClient*)h->nodes->pdata[n])->user_time)
-
-static inline void swap(ObClientTimeHeap *h, guint a, guint b)
-{
- gpointer c;
-
- g_assert(a < h->nodes->len);
- g_assert(b < h->nodes->len);
-
- c = h->nodes->pdata[a];
- h->nodes->pdata[a] = h->nodes->pdata[b];
- h->nodes->pdata[b] = c;
-}
-
-static inline void heapify(ObClientTimeHeap *h, guint n)
-{
- g_assert(exists(n));
-
- /* fix up the heap, move it down below keys it's smaller than */
- while ((exists(left(n)) && key(n) < key(left(n))) ||
- (exists(right(n)) && key(n) < key(right(n))))
- {
- if (exists(left(n)) && exists(right(n)))
- if (key(left(n)) > key(right(n))) {
- swap(h, n, left(n));
- n = left(n);
- } else {
- swap(h, n, right(n));
- n = right(n);
- }
- else {
- /* its impossible in this structure to have a right child but no
- left child */
- swap(h, n, left(n));
- n = left(n);
- }
- }
-}
-
-ObClientTimeHeap* client_time_heap_new()
-{
- ObClientTimeHeap *h = g_new0(ObClientTimeHeap, 1);
- h->nodes = g_ptr_array_new();
- return h;
-}
-
-void client_time_heap_free(ObClientTimeHeap *h)
-{
- if (h != NULL) {
- /* all the clients should be removed before the heap is destroyed. */
- g_assert(h->nodes->len == 0);
- g_ptr_array_free(h->nodes, TRUE);
- g_free(h);
- }
-}
-
-guint32 client_time_heap_maximum(ObClientTimeHeap *h)
-{
- if (h->nodes->len == 0)
- return CurrentTime;
- else
- return key(0);
-}
-
-
-void client_time_heap_add(ObClientTimeHeap *h, ObClient *c)
-{
- guint n;
-
- /* insert it as the last leaf */
- g_ptr_array_add(h->nodes, c);
- n = h->nodes->len - 1;
-
- /* move it up to its proper place */
- while (!isroot(n) && key(n) > key(parent(n))) {
- swap(h, n, parent(n));
- n = parent(n);
- }
-}
-
-void client_time_heap_remove(ObClientTimeHeap *h, ObClient *c)
-{
- /* find the client */
- guint n;
- for (n = 0; h->nodes->pdata[n] != c && n < h->nodes->len; ++n);
-
- /* if the client is in the heap */
- if (n < h->nodes->len) {
- /* move it to a leaf and delete it from the heap */
- swap(h, n, h->nodes->len-1);
- g_ptr_array_remove_index(h->nodes, h->nodes->len-1);
-
- /* move the swapped leaf down to its proper place if it wasn't just
- deleted */
- if (exists(n))
- heapify(h, n);
- }
-}
-
-void client_time_heap_decrease_key(ObClientTimeHeap *h, ObClient *c)
-{
- /* find the client */
- guint n;
- for (n = 0; h->nodes->pdata[n] != c && n < h->nodes->len; ++n);
-
- /* if the client is in the heap */
- if (n < h->nodes->len) {
- /* move it down to its proper place */
- heapify(h, n);
- }
-}
-
-void client_time_heap_increase_key(ObClientTimeHeap *h, ObClient *c)
-{
- /* find the client */
- guint n;
- for (n = 0; h->nodes->pdata[n] != c && n < h->nodes->len; ++n);
-
- /* if the client is in the heap */
- if (n < h->nodes->len) {
- /* move it up to its proper place */
- while (!isroot(n) && key(n) > key(parent(n))) {
- swap(h, n, parent(n));
- n = parent(n);
- }
- }
-}