module Editor { export class List { public next: List; public prev: List; private listFactory: ListFactory; constructor(public isHead: boolean, public data: T) { this.listFactory = new ListFactory(); } public add(data: T): List { var entry = this.listFactory.MakeEntry(data); this.prev.next = entry; entry.next = this; entry.prev = this.prev; this.prev = entry; return entry; } public count(): number { var entry: List; var i: number; entry = this.next; for (i = 0; !(entry.isHead); i++) { entry = entry.next; } return (i); } public isEmpty(): boolean { return (this.next == this); } public first(): T { if (this.isEmpty()) { return this.next.data; } else { return null; } } public pushEntry(entry: List): void { entry.isHead = false; entry.next = this.next; entry.prev = this; this.next = entry; entry.next.prev = entry; // entry.next.prev does not show intellisense, but entry.prev.prev does } public push(data: T): void { var entry = this.listFactory.MakeEntry(data); entry.data = data; entry.isHead = false; entry.next = this.next; entry.prev = this; this.next = entry; entry.next.prev = entry; // entry.next.prev does not show intellisense, but entry.prev.prev does } public popEntry(head: List): List { if (this.next.isHead) { return null; } else { return this.listFactory.RemoveEntry(this.next); } } public insertEntry(entry: List): List { entry.isHead = false; this.prev.next = entry; entry.next = this; entry.prev = this.prev; this.prev = entry; return entry; } public insertAfter(data: T): List { var entry: List = this.listFactory.MakeEntry(data); entry.next = this.next; entry.prev = this; this.next = entry; entry.next.prev = entry;// entry.next.prev does not show intellisense, but entry.prev.prev does return entry; } public insertEntryBefore(entry: List): List { this.prev.next = entry; entry.next = this; entry.prev = this.prev; this.prev = entry; return entry; } public insertBefore(data: T): List { var entry = this.listFactory.MakeEntry(data); return this.insertEntryBefore(entry); } } export class ListFactory { public MakeHead(): List { var entry: List = new List(true, null); entry.prev = entry; entry.next = entry; return entry; } public MakeEntry(data: T): List { var entry: List = new List(false, data); entry.prev = entry; entry.next = entry; return entry; } public RemoveEntry(entry: List): List { if (entry == null) { return null; } else if (entry.isHead) { // Can't remove the head of a list! return null; } else { entry.next.prev = entry.prev; entry.prev.next = entry.next; return entry; } } } }