/* * A small progam to provide a curses based slides tool. It paints * slides from a text file. * * Slides are simply segments of text ended by "--" on a line by * itself. */ #include #include #include #include /* command line arguments, held as a global variable */ char *argFileName; /* a simple list structure to store the lines on a slide */ typedef struct lineNode { char *text; /* the contents of the line itself */ struct lineNode *next; /* the next node */ } lineNode_t; /* a doubly linked list to store the slide deck */ typedef struct slideNode { lineNode_t *lines; /* the set of lines on this slide */ int lineCount; /* the number of lines */ int width; /* the width of the longest line */ struct slideNode *next; /* the next slide */ struct slideNode *prev; /* the previous slide */ } slideNode_t; /* process the command line arguments. Returns 1 on success and 0 on invalid arguments. */ int processArguments(int argc, char** argv); /* display a usage message for the wayward user */ void displayUsage(int argc, char **argv); /* loads the deck return a pointer to the deck, null on failure */ slideNode_t *loadDeck(); /* display the slide show, returns when the user quits the slideshow */ void slideShow(slideNode_t *deck); /* constructor functions */ slideNode_t *newSlide(); lineNode_t *newLine(); int main(int argc, char **argv) { slideNode_t *deck; /* startup procedures */ if(!processArguments(argc, argv)) { displayUsage(argc, argv); return -1; } deck=loadDeck(); /* run the show */ slideShow(deck); return 0; } /* process the command line arguments. Returns 1 on success and 0 on invalid arguments. */ int processArguments(int argc, char** argv) { /* there shall be 2 arguments, and the number of arguments shall be * 2. 1 argument there shall not be, unless there exists a second * argument after it. 3 is right out! */ if(argc != 2) return 0; /* get the file name */ argFileName = argv[1]; return 1; } /* display a usage message for the wayward user */ void displayUsage(int argc, char **argv) { fprintf(stderr, "\nUsage: %s fileName\n\n", argv[0]); } /* loads the deck return a pointer to the deck, null on failure */ slideNode_t * loadDeck() { slideNode_t *deck=NULL; slideNode_t *curSlide, *lastSlide; lineNode_t *curLine, *lastLine=NULL; char *text=malloc(100); int len; size_t bufSize=100; FILE *f; /* open the file, as best we can */ f = fopen(argFileName, "r"); if(!f) { perror("Error Loading Slide Deck"); return NULL; } /* start the deck off */ deck = curSlide = lastSlide = newSlide(); /* Read the file */ while(!feof(f)) { /* read the text line, strip newline */ len = getline(&text, &bufSize, f); if(len <= 0) continue; if(text[len-1]=='\n') { text[len-1]='\0'; len--; } /* handle new slides */ if(!strcmp(text, "--")) { curSlide = newSlide(); curSlide->prev = lastSlide; lastSlide->next = curSlide; lastSlide = curSlide; continue; } /* create and link the line */ curLine = newLine(); if(!(curSlide->lines)) { curSlide->lines = curLine; } else { lastLine->next = curLine; } lastLine = curLine; /* populate the line, and handle length */ curLine->text = strdup(text); if(len > curSlide->width) curSlide->width = len; curSlide->lineCount++; } fclose(f); free(text); return deck; } /* display the slide show, returns when the user quits the slideshow */ void slideShow(slideNode_t *deck) { slideNode_t *curSlide; lineNode_t *curLine; int x, y; int maxx, maxy; int c; /* handle empty slide decks */ if(!deck) { fprintf(stderr, "Error: No slides in deck!\n"); return; } /* initialize curses */ initscr(); /* initialize the screen */ noecho(); /* do not echo characters */ raw(); /* turn off character translation */ keypad(stdscr, TRUE); /* translate escape sequences to keys */ timeout(-1); /* block indefinitely for input */ curs_set(0); /* set invisible cursor */ /* get our maxes */ getmaxyx(stdscr, maxy, maxx); curSlide=deck; while(curSlide && curSlide->lines) { /* compute offsets */ getbegyx(stdscr, y, x); y += (maxy - curSlide->lineCount) / 2; x += (maxx - curSlide->width) / 2; /* display the lines */ clear(); for(curLine=curSlide->lines; curLine; curLine=curLine->next) { mvaddstr(y++, x, curLine->text); } /* get and handle the command */ c = getch(); switch(c) { case KEY_RIGHT: case KEY_DOWN: case ' ': curSlide = curSlide->next; break; case KEY_LEFT: case KEY_UP: if(curSlide->prev) curSlide = curSlide->prev; break; case 'q': case KEY_EXIT: goto finish; break; } } /* put things back to their default behavior */ finish: clear(); endwin(); } slideNode_t * newSlide() { slideNode_t *result; result = malloc(sizeof(slideNode_t)); result->lineCount = 0; result->width = 0; result->prev = result->next = NULL; return result; } lineNode_t * newLine() { lineNode_t *result; result = malloc(sizeof(lineNode_t)); result->text = NULL; result->next = NULL; return result; }