#define NOTE_LIST_C

#include "main.h"

void sticky_note_add(sticky_base *base, sticky_note *note)
{
 sticky_note *scan = base->start_name;
 
 note->base = base;
 base->count++;
 
 if (!scan)
 {
  assert(!base->start_name);
  assert(!base->start_id);
  
  base->start_name = base->start_id = note;
  note->next_name = NULL;
  note->prev_name = NULL;
  note->next_id = NULL;
  note->prev_id = NULL;
  return;
 }
 assert(base->start_name);
 assert(base->start_id);
 
 while (scan->next_name && (strcmp(note->name, scan->name) > 0))
   scan = scan->next_name;

 if (strcmp(note->name, scan->name) > 0)
 {
  assert(!scan->next_name);
  
  scan->next_name = note;
  note->next_name = NULL;
  note->prev_name = scan;
 }
 else
 {
  if ((note->prev_name = scan->prev_name))
    note->prev_name->next_name = note;
  else
    base->start_name = note;

  scan->prev_name = note;
  note->next_name = scan;
 }

 scan = base->start_id;
 while (scan->next_id && (note->unique_id > scan->unique_id))
   scan = scan->next_id;

 assert(scan->unique_id != note->unique_id);
 
 if (note->unique_id > scan->unique_id)
 {
  assert(!scan->next_id);
  
  scan->next_id = note;
  note->next_id = NULL;
  note->prev_id = scan;
 }
 else
 {
  if ((note->prev_id = scan->prev_id))
    note->prev_id->next_id = note;
  else
    base->start_id = note;

  scan->prev_id = note;
  note->next_id = scan;
 }
}

void sticky_note_del(sticky_note *note)
{
 sticky_base *base = note->base;

 base->count--;
 
 if (note->prev_name)
   note->prev_name->next_name = note->next_name;
 else
   base->start_name = note->next_name;

 if (note->next_name)
   note->next_name->prev_name = note->prev_name;

 if (note->prev_id)
   note->prev_id->next_id = note->next_id;
 else
   base->start_id = note->next_id;

 if (note->next_id)
   note->next_id->prev_id = note->prev_id;
}

void sticky_note_do_inorder(int (*func) (sticky_note *, va_list),
                            sticky_base *base, ...)
{
 sticky_note *scan = base->start_name;
 
 va_list va;
 
 va_start(va, base);

 while (scan)
 {
  sticky_note *scan_next = scan->next_name;

  if (!(*func)(scan, va))
    break;
  
  scan = scan_next;
 }
 
 va_end(va);
}

void sticky_note_do_inorder_hidden(int (*func) (sticky_note *, va_list),
                                   sticky_base *base, ...)
{
 sticky_note *scan = base->start_name;
 
 va_list va;
 
 va_start(va, base);

 while (scan)
 {
  sticky_note *scan_next = scan->next_name;

  if (!GTK_WIDGET_VISIBLE(scan->window) && !(*func)(scan, va))
    break;
  
  scan = scan_next;
 }
 
 va_end(va);
}

void sticky_note_do_cronorder(int (*func) (sticky_note *, va_list),
                              sticky_base *base, ...)
{
 sticky_note *scan = base->start_id;
 
 va_list va;
 
 va_start(va, base);

 while (scan)
 {
  sticky_note *scan_next = scan->next_id;

  if (!(*func)(scan, va))
    break;
  
  scan = scan_next;
 }
 
 va_end(va);
}
