home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
c_news
/
15
/
line.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-04
|
15KB
|
521 lines
/* -- File: line.c *
-- *
-- Author: Anthony Lander *
-- Date: January 10, 1989. *
-- *
-- Description: *
-- This library contains a rather complete set of functions for*
-- creating and maintaining linked lists. *
-- */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include "f_prot.h" /* Prototypes for all functions */
#include "line.h" /* STRUCTs and #DEFINEs for LINE.C */
struct _line *last_line = NULL; /* The last line in the linked list */
struct _line *first_line = NULL; /* The first line in the list */
/* Both NULL until initialized by */
/* init_list() */
/* ------------------------------------------------------------------------ */
/* Function: Return the first line in the list */
/* ------------------------------------------------------------------------ */
struct _line *get_first_line()
{
return(first_line);
}
/* ------------------------------------------------------------------------ */
/* Function: Return the last line in the list */
/* ------------------------------------------------------------------------ */
struct _line *get_last_line()
{
return(last_line);
}
/* ------------------------------------------------------------------------ */
/* Function: Return a ptr to a line that's got space malloc()'ed for it */
/* ------------------------------------------------------------------------ */
/* -- Note: string is set to NULL. Length is set to 0. Prev and next are *
-- set to NULL. *
-- *
-- takes: nothing *
-- returns: NULL if there's no more memory *
-- PTR to struct _line if a new line has been created *
-- */
struct _line *get_new_line()
{
struct _line *new_line;
new_line = (struct _line *) malloc( sizeof(struct _line) );
if(new_line == NULL) { /* malloc() failed */
return(NULL);
}
/* Otherwise, NULL all of the pointers */
new_line->string = NULL;
new_line->length = 0;
new_line->next_line = NULL;
new_line->prev_line = NULL;
return(new_line);
}
/* ------------------------------------------------------------------------ */
/* Function: Insert a line after another line. */
/* ------------------------------------------------------------------------ */
/* -- Takes: insert, a ptr with string, length, max_length set *
-- correctly. after, a ptr to the line to add 'insert; *
-- after. *
-- Returns: None *
-- *
-- Notes: This function will set up the prev_line and next_line *
-- pointers so that the inserted line will fit correctly in the *
-- chain. It will also fix the last_line pointer, if needed. *
-- */
void insert_after_line(insert, after)
struct _line *insert, /* line to insert */
*after; /* line to insert it after */
{
/* -- if after is NULL, it means that we're creating the only line in *
-- the list. Thus, we don't make an uplink for insert. *
-- */
if(after == NULL) {
insert->prev_line = NULL;
insert->next_line = NULL;
first_line = insert;
last_line = insert;
return;
}
/* -- otherwise, we're inserting after an already existing line. *
-- Check to see whether we're the new last line, and adjust *
-- accordingly. *
-- */
insert->prev_line = after;
insert->next_line = after->next_line;
after->next_line = insert;
if(insert->next_line == NULL) {
last_line = insert;
}
/* if NOT the last line in the list, then set after->next's prev_line */
else {
(insert->next_line)->prev_line = insert;
}
}
/* ------------------------------------------------------------------------ */
/* Function: Insert one line before another line */
/* ------------------------------------------------------------------------ */
/* -- Takes: insert, a ptr with string, length, max_length set *
-- correctly. before, a ptr to the line to add 'insert' *
-- before. *
-- *
-- Returns: None *
-- *
-- Notes: This function will set up the prev_line and next_line *
-- pointers so that the inserted line will fit correctly in the *
-- chain. It will also fix the first_line pointer if needed. *
-- */
void insert_before_line(insert, before)
struct _line *insert, /* line to insert */
*before; /* line to insert 'insert' before */
{
/* -- if before is NULL then we're creating the only line in the list. *
-- Set up first_line and last_line, as well as insert's prev_line *
-- and next_line links. *
-- */
if(before == NULL) {
insert->prev_line = NULL;
insert->next_line = NULL;
last_line = insert;
first_line = insert;
return;
}
/* -- otherwise we're in the middle, so set insert's next and prev *
-- pointers like this.... *
-- */
insert->next_line = before;
insert->prev_line = before->prev_line;
/* set before's prev pointer */
before->prev_line = insert;
/* if (insert->prev_line) is NULL, then it's the new start of the list */
if(insert->prev_line == NULL) {
first_line = insert;
}
/* Otherwise, reset (insert->prev_line)->next_line's pointer */
else {
(insert->prev_line)->next_line = insert;
}
/* Now set up (insert->prev_line)'s next_line link */
if(insert->prev_line != NULL)
(insert->prev_line)->next_line = insert;
}
/* ------------------------------------------------------------------------ */
/* Function: Delete a line from the list */
/* ------------------------------------------------------------------------ */
/* -- Takes: line to delete *
-- Returns: nothing -- better be sure to pass a valid pointer! *
-- *
-- Notes: If you delete the first or last line, the first_ or last_ *
-- line pointers will get updated *
-- */
void delete_line(delete)
struct _line *delete;
{
/* -- SPECIAL CASE: The first and/or last line of the list. *
-- These special cases are treated differently *
-- so that we can deal with thier NULL pointers *
-- in either prev_line, or next_line. *
-- */
if(delete == first_line || delete == last_line) {
/* -- If we're the first line, and not the only line, then make *
-- the next line the new first line. *
-- */
if((delete == first_line) && (delete->next_line != NULL))
(delete->next_line)->prev_line = NULL;
/* -- Test to see if we're (possibly also) the last line in the *
-- list, but make sure we're not the only line in the list. *
-- */
if((delete == last_line) && (delete->prev_line != NULL))
(delete->prev_line)->next_line = NULL;
}
/* OTHERWISE we're in the middle, so patch all links normally */
else {
(delete->prev_line)->next_line = delete->next_line;
(delete->next_line)->prev_line = delete->prev_line;
}
/* -- now free the structure, but first release the string space *
-- if it's been allocated. *
-- */
if(delete->string != NULL)
free(delete->string);
/* See if we have to adjust first_line and last_line */
if(delete == first_line)
first_line = delete->next_line;
if(delete == last_line)
last_line = delete->prev_line;
free(delete);
}
/* ------------------------------------------------------------------------ */
/* Function: Delete all lines in the list */
/* ------------------------------------------------------------------------ */
/* -- Takes: Nothing *
-- Returns: Nothing *
-- *
-- Notes: This goes through the list, starting at the top, and deletes *
-- all of the lines (and strings in lines) until it gets to the *
-- bottom. *
-- */
void delete_all_lines()
{
while(first_line != NULL) {
if(first_line->string != NULL)
free(first_line->string);
free(first_line);
first_line = first_line->next_line;
}
}
/* ------------------------------------------------------------------------ */
/* Function: Move a line before another line */
/* ------------------------------------------------------------------------ */
/* -- Takes: PTR to line to move. *
-- PTR to line to move it before. *
-- Returns: nothing. *
-- *
-- Notes: move_before just calls insert_before_line() and delete() *
-- */
void move_before_line(move, before)
struct _line *move, /* Line to move */
*before; /* Line to move it before (ahead of) */
{
struct _line *temp;
temp = get_new_line();
memcpy(temp, move, sizeof(struct _line));
/* Now make a copy of move->string, 'cuz temp just has the address */
temp->string = malloc(strlen(move->string)+1);
strcpy(temp->string, move->string);
/* make temp's *_line links point to NULL */
temp->prev_line = NULL;
temp->next_line = NULL;
delete_line(move);
insert_before_line(temp, before);
}
/* ------------------------------------------------------------------------ */
/* Function: Move a line after another line */
/* ------------------------------------------------------------------------ */
/* -- Takes: PTR to line to move. *
-- PTR to line to move it after. *
-- Returns: nothing. *
-- *
-- Notes: move_after just calls insert_after_line() and delete() *
-- */
void move_after_line(move, after)
struct _line *move, /* line to move */
*after; /* line to move after (follow) */
{
struct _line *temp;
temp = get_new_line();
memcpy(temp, move, sizeof(struct _line));
/* Now make a copy of move->string, because temp just has the address */
temp->string = malloc(strlen(move->string)+1);
strcpy(temp->string, move->string);
/* make temp's chains point to NULL */
temp->prev_line = NULL;
temp->next_line = NULL;
delete_line(move);
insert_after_line(temp, after);
}