#include /* standard I/O stuff */ #include /* file I/O stuff */ #include "CursStrType.h" /* class header file for CursStrType */ #include /* NOTE: First there is no or . These are my member function definitions. There is a lot of code here that should have looked more like Nell Dale's StrType class; however, since I wanted to user the curses library for printing to the screen the original StrType class was useless. */ /************************************************************ * CursStrType() -- is our default constructor * * * * Parameters * * NONE * * * * Returns * * NONE * ************************************************************/ CursStrType::CursStrType() { MakeEmpty(); /* here is something from Nell Dale */ Reset(); /* zero out all our indexing values */ initscr(); /* initialize screen */ } /************************************************************ * MakeEmpty() -- Nell Dale's MakeEmpty * * * * Parameters * * NONE * * * * Returns * * void * ************************************************************/ void CursStrType::MakeEmpty() { letters[0] = '\0'; /* terminate letters on first index */ index.searchstr[0] = '\0'; /* terminate searchstr on first index */ index.printscreen[0] = '\0'; /* terminate printscreen on first index */ } /************************************************************ * Reset() -- a function to reset the indexing * * * * Parameters * * NONE * * * * Returns * * void * ************************************************************/ void CursStrType::Reset() { int i; index.nextpage = 0; index.count = 0; index.find = 0; /* populate our integer array with zero */ for(i = 0; i <= MAX_INDEX; i++) { index.lastpage[i] = 0; } } /************************************************************ * Length() -- replacement for strlen. * * * * Parameters * * char srcstr[] -- character array to check size of * * * * Returns * * int -- the length of array * ************************************************************/ int CursStrType::Length(char srcstr[]) { int len = 0; /* make our length equal zero */ char *ptr; /* and put a char pointer in there */ ptr = srcstr; /* make the char pointer = srcstr */ while(*ptr) /* while *ptr does not == NULL */ { len++; /* increment our length */ ptr++; /* point to the next location */ } return(len); /* return the length */ } /************************************************************ * Cat() -- put srcstr onto the end of destscr * * * * Parameters * * char *destscr -- destination string by reference * * char srcscr[] -- source string to put into dest * * int size -- set the size of deststr * * * * Returns * * int -- just good * ************************************************************/ int CursStrType::Cat(char *destscr, char srcstr[], int size) { int i; /* deststr index */ int x = 0; /* srcstr index */ /* concatenate size characters of srcstr into destscr */ for(i = Length(destscr); i < size; i++) { destscr[i] = srcstr[x]; if(srcstr[x] == '\0') { return(0); } x++; } destscr[size] = '\0'; return(0); } /************************************************************ * Comp() -- compare str1 with str2 * * * * Parameters * * char str1[] -- string1 * * char str2[] -- string2 * * int amount -- amount of bytes to compare * * * * Returns * * int -- return zero if the same and non-zero if not * ************************************************************/ int CursStrType::Comp(char str1[], char str2[], int amount) { int i; /* compares the two strings and returns zero if they are the same */ for(i = 0; i < amount; i++) { if(str1[i] != str2[i]) { return(1); } } return(0); } /************************************************************ * Copy() -- Copy srcstr to destscr and return a pointer * * * * Parameters * * char *destscr -- destination string by reference * * char srcscr[] -- source string to put into dest * * int size -- set the size of deststr * * * * Returns * * int -- just good * ************************************************************/ int CursStrType::Copy(char *destscr, char srcstr[], int size) { int i; /* again for the counter */ /* destscr[i] will get the contents of srcstr */ for(i = 0; i < size; i++) { destscr[i] = srcstr[i]; if(srcstr[i] == '\0') { return(0); } } destscr[size] = '\0'; return(0); } /************************************************************ * MakeStrEmpty() -- make srcstr contain NULL characters * * * * Parameters * * char srcscr[] -- source string to make empty * * int size -- set the length of srcstr * * * * Returns * * void * ************************************************************/ void CursStrType::MakeStrEmpty(char *srcstr, int size) { int i; /* make the whole string have NULL characters */ for(i = 0; i <= size; i++) { srcstr[i] = '\0'; } } /************************************************************ * GetStringFile() -- Another Nell Dale function. this will * * read the file stream passed by the user and flag it as * * read. * * * * Parameters * * The infile file stream * * * * Returns * * void * ************************************************************/ void CursStrType::GetStringFile(std::ifstream& inFile) { /* this is a flat out byte read until sizeof(letters) - 1 */ inFile.read(letters, (sizeof(letters) - 1)); /* if there is no input file then die */ if(Length(letters) == 0) { Die("ERROR: File does NOT exist"); } } /************************************************************ * RefreshScreen() -- just a simple refresh of the screen * * * * Parameters * * NONE * * * * Returns * * void * ************************************************************/ void CursStrType::RefreshScreen() { echo(); /* echo input to user */ wmove(input, 1, 0); /* move cursor down for input */ touchwin(stdscr); /* touch main window and touch all */ refresh(); /* repaint (all) windows */ } /************************************************************ * GetChar() -- get's one character at a time from user * * * * Parameters * * NONE * * * * Returns * * char * ************************************************************/ char CursStrType::GetChar() { noecho(); /* don't echo user's input commands */ return(wgetch(input)); /* this will get one char from user */ } /************************************************************ * PrintError() -- print to the user any error without exit * * * * Parameters * * char errorString[] -- this is the error to print * * * * Returns * * void * ************************************************************/ void CursStrType::PrintError(char errorString[]) { int i = 0; wstandout(input); /* makes the print stand out */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 0, i, ' '); /* color our line in */ } wstandend(input); /* ends the stand out print */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 1, i, ' '); /* clear our input line */ } wstandout(input); /* makes the print stand out */ /* print the error */ mvwaddnstr(input, 0, 0, errorString, Length(errorString)); wstandend(input); /* end the funny print */ RefreshScreen(); /* refresh display */ sleep(3); wstandout(input); /* makes the print stand out */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 0, i, ' '); /* color our line in */ } wstandend(input); /* ends the stand out print */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 1, i, ' '); /* clear our input line */ } RefreshScreen(); /* refresh display */ } /************************************************************ * GetInput() -- get a user input string from the window * * * * Parameters * * char inputString[] -- this is the input question * * char* answer -- referenced string to put user input * * int size -- the size of answer * * * * Returns * * void * ************************************************************/ void CursStrType::GetInput(char inputString[], char* answer, int size) { int i = 0; do /* while we find no input prompt again */ { wstandout(input); /* makes the print stand out */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 0, i, ' '); /* color our line in */ } wstandend(input); /* ends the stand out print */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 1, i, ' '); /* clear our input line */ } wstandout(input); /* makes the print stand out */ /* ask for the inputString */ mvwaddnstr(input, 0, 0, inputString, Length(inputString)); wstandend(input); /* end the funny print */ RefreshScreen(); /* refresh display */ /* grab inputString */ wgetnstr(input, answer, size); } while(Length(answer) == 0); } /************************************************************ * PrintToScreen() -- print a page at a time to the window. * * this function gets a little complex and perhaps I could * * have done it better. but since this is my first time * * with curses I don't think it's all that bad. * * * * Parameters * * char -- character indicating what to do * * * * Returns * * void * ************************************************************/ void CursStrType::PrintToScreen(char action) { int i = 0; /* used in the for loops */ int x = 0; /* again used in the for loops */ int count = 0; /* to count how many _LINES_ we have */ int maxloop = Length(letters); /* so we don't call Length so much */ /* this is so much better then using a for loop */ MakeStrEmpty(index.printscreen, sizeof(index.printscreen)); switch(action) /* switch on the user's char */ { /* this will tell the program to page down. or if nothing is displayed yet put the first page up in the window. this gets a little hard to follow. */ case ' ': /* i will start at index.nextpage. this is a place holder for the base of the next page to be displayed. remember our constructor set this to zero above for the first run. maxloop is there because this could be the last page in our file. */ for(i = index.nextpage; i <= maxloop; i++) { /* remember we just set x to zero. there will be something to increment x later. for now we just want the base of printscreen to equal the indexed position of letters. */ index.printscreen[x] = letters[i]; /* this means we want to count every time we hit a newline. this is done so we know when to stop copying things to our _LIMITED_ window size */ if(index.printscreen[x] == '\n') { count++; /* this simply says if we have reached our window size execute the following code */ if(count == (LINES - 5)) { /* before we change index.nextpage we want to make it the same as index.lastpage. this is done because we just flipped through our page */ index.lastpage[index.count] = index.nextpage; /* and assign our new nextpage to index.nextpage */ index.nextpage = (i + 1); /* this will help index the index.lastpage array. mostly to keep track of our old window starts */ index.count++; break; /* exit outer for loop we are done */ } } /* that last if statement was all fine and dandy but what if our file ends before the maximum window size */ if(i == maxloop && (index.lastpage[index.count - 1] != index.nextpage)) { /* we want to make the last index count know the last window. */ index.lastpage[index.count] = index.nextpage; index.count++; } x++; /* there she is increment x now */ } break; /* this is what happens if the user tells us to go back a page */ case 0x08: case 'b': /* if we find ourselves back at the start page we need to display it. But that will set count lower then we want this is here to see when count is too low and reset it to the value acceptable for the first page. */ if((index.count - 1) == 0) { index.count = 2; } /* we want to start the page counter at index.lastpage */ for(i = index.lastpage[index.count - 2]; i <= maxloop; i++) { /* again the trick to assign letters to printscreen */ index.printscreen[x] = letters[i]; /* and count the newlines to make sure we fit in window */ if(index.printscreen[x] == '\n') { count++; if(count == (LINES - 5)) { /* here is something new. always decrement our position if we are not at the very beginning. this gets a little sloppy because of the stuff at the beginning. I am sure if I thought it out I would find a better way to do it. But I had to move on */ if((index.count - 1) > 0) { index.count--; } index.nextpage = (i + 1); break; } } x++; } break; case 'c': /* if we find ourselves back at the start page we need to display it. But that will set count lower then we want this is here to see when count is too low and reset it to the value acceptable for the first page. */ if((index.count - 1) == 0) { index.count = 2; } /* we want to start the page counter at index.lastpage */ for(i = index.lastpage[index.count - 1]; i <= maxloop; i++) { /* again the trick to assign letters to printscreen */ index.printscreen[x] = letters[i]; /* and count the newlines to make sure we fit in window */ if(index.printscreen[x] == '\n') { count++; if(count == (LINES - 5)) { index.nextpage = (i + 1); break; } } x++; } break; } ClearDisplay(); /* clean window off before change */ /* print output to curses screen */ waddnstr(display, index.printscreen, (MAX_CHARS + 1)); RefreshScreen(); /* Now display it to user */ } /************************************************************ * FindString() -- find a string. It would be nice to see * * this retain the current page positions but that was not * * important and I ran out of time. * * * * Parameters * * char newstr -- new string to replace old with * * * * Returns * * void * ************************************************************/ void CursStrType::FindString(char searchstr[], char opt) { int i = 0; /* this gets tossed around a lot */ int x = 0; /* the second index counter */ int count = 0; /* keep track of what will fit */ int maxloop = (Length(letters) - 1); /* the end of letters */ bool notfound = TRUE; /* if the string is not found */ char *ptr; /* to do a easy Copy() later on */ /* clean up and get things ready */ MakeStrEmpty(index.printscreen, sizeof(index.printscreen)); MakeStrEmpty(index.searchstr, sizeof(index.searchstr)); Copy(index.searchstr, searchstr, sizeof(index.searchstr)); /* if the user wants to find next or new */ if(opt != 'n') { index.find = 0; } else { index.find += (Length(index.searchstr) - 1); } /* and we're off */ for(i = index.find; i <= maxloop; i++) { if(letters[i] == index.searchstr[0]) { /* mark the first successful match */ ptr = &letters[i]; /* now see of it is the search string */ if(Comp(ptr, index.searchstr, Length(index.searchstr)) == 0) { notfound = false; /* woo hoo we got it */ index.find = i; /* update the index */ /* find the beginning of the line to highlight */ for(i = index.find; i >= 0; i--) { if(letters[i] == '\n') { index.highlight = (i + 1); break; } } /* find the end of the line to highlight */ for(i = index.find; i <= maxloop; i++) { if(letters[i] == '\n') { i++; break; } } while(i <= maxloop) { index.printscreen[x] = letters[i]; /* if we hit a newline or the EOF */ if(index.printscreen[x] == '\n' || i == maxloop) { count++; /* go in when we have filled the screen or it's EOF*/ if(count == (LINES - 6) || i == maxloop) { ClearDisplay(); /* this is fun stuff with curses. Here we are going to highlight the string we found */ for(i = index.highlight; i <= maxloop; i++) { if(i == index.find) { while(i <= (index.find + (Length(index.searchstr) - 1))) { wstandout(display); waddch(display, letters[i]); wstandend(display); i++; } i--; /* we went one over back it off */ } else { waddch(display, letters[i]); } /* we are on the end of the highlight line */ if(letters[i] == '\n') { i++; break; } } /* put the rest out to the screen */ waddnstr(display, index.printscreen, (MAX_CHARS + 1)); RefreshScreen(); break; } } x++; i++; } break; } } } /* awe no string in file */ if(notfound) { PrintError("Search string not found"); RefreshScreen(); } } /************************************************************ * ReplaceString() -- replace the last found string * * * * Parameters * * char newstr -- new string to replace old with * * * * Returns * * void * ************************************************************/ void CursStrType::ReplaceString(char newstr[]) { int startpoint; /* where do we start */ char tempstr[MAX_CHARS + 1]; /* temp for manipulation */ char *tok; /* again for easy string manip */ startpoint = index.find; /* set to last found index */ tok = &letters[startpoint]; /* and make our tok pointer go there */ /* construct the new string */ Copy(tempstr, letters, startpoint); Cat(tempstr, newstr, sizeof(tempstr)); Cat(tempstr, (tok + Length(index.searchstr)), sizeof(tempstr)); /* Copy the new string into the old one */ MakeStrEmpty(letters, sizeof(letters)); Copy(letters, tempstr, sizeof(letters)); Reset(); } /************************************************************ * InsertString() -- inset a string into letters array * * * * Parameters * * char inserstr -- string to be inserted * * int location -- user specified location * * * * Returns * * void * ************************************************************/ void CursStrType::InsertString(char insertstr[], int location) { int startpoint; /* starting position */ char tempstr[MAX_CHARS + 1]; /* temp for string manipulation */ char *tok; /* make my life easier */ /* set startpoint and tok to either last found position or user input */ if(location >= 0) { startpoint = location; tok = &letters[startpoint]; } else { startpoint = index.find; tok = &letters[startpoint]; } /* construct the new string */ Copy(tempstr, letters, startpoint); Cat(tempstr, insertstr, sizeof(tempstr)); Cat(tempstr, tok, sizeof(tempstr)); /* Copy the new string into the old one */ MakeStrEmpty(letters, sizeof(letters)); Copy(letters, tempstr, sizeof(letters)); Reset(); } /************************************************************ * DeleteString() -- delete the last string found * * * * Parameters * * int location -- location to delete from * * int number -- the number of positions to delete * * * * Returns * * void * ************************************************************/ void CursStrType::DeleteString(int location, int number) { int startpoint; /* our start point */ char tempstr[MAX_CHARS + 1]; /* manipulate a string */ char *tok; /* easy string operations */ /* if the user put this in on the command line or we user last found */ if(location >= 0) { startpoint = location; tok = &letters[startpoint + number]; } else { startpoint = index.find; tok = &letters[startpoint + Length(index.searchstr)]; } /* construct the new string */ Copy(tempstr, letters, startpoint); Cat(tempstr, tok, sizeof(tempstr)); /* Copy the new string into the old one */ MakeStrEmpty(letters, sizeof(letters)); Copy(letters, tempstr, sizeof(letters)); Reset(); } /************************************************************ * ClearDisplay() -- clear the display window * * * * Parameters * * NONE * * * * Returns * * void * ************************************************************/ void CursStrType::ClearDisplay() { int i; /* for loops */ crmode(); /* send CTRL stuff to kernel */ nonl(); /* don't return line-feed */ standout(); /* makes the print stand out */ box(stdscr, ' ', ' '); /* make a boarder around the edge */ standend(); /* ends the stand out print */ /* if our windows have not been constructed yet */ if(display == NULL && input == NULL) { /* this opens a sub-window within our main window */ display = subwin(stdscr, LINES - 4, COLS - 2, 1, 1); if(display == NULL) /* if we get NULL subwin failed */ { Die("ERROR: Problem opening sub-window(display)"); } /* this opens a sub-window within our main window */ input = subwin(stdscr, 2, COLS - 2, LINES - 3, 1); if(input == NULL) /* if we get NULL subwin failed */ { Die("ERROR: Problem opening sub-window(input)"); } } wstandout(input); /* makes the print stand out */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 0, i, ' '); /* color our line in */ } wstandend(input); /* ends the stand out print */ for(i = 0; i <= (COLS - 2); i++) { mvwaddch(input, 1, i, ' '); /* clear our input line */ } scrollok(display, TRUE); /* allow display to scroll */ werase(display); /* clear display */ RefreshScreen(); /* and refresh it to user */ } /************************************************************ * SplashScreen() -- present user with main window. I would* * have preferred to do this in the client so this class was * * less specific. But again I ran out of time. If anyone * * would like to re-write this so the client can construct * * the splash screen be my guest. * * * * Parameters * * NONE * * * * Returns * * void * ************************************************************/ void CursStrType::SplashScreen() { /* this is all stuff to print to the main screen */ char PROG_INTRO[] = "USMed is the University of Southern Maine Editor"; char PROG_AUTHOR[] = "Written By: Chris Mooney "; char PROG_VERSION[] = "Version: 0.1"; /* the USMed logo -Original logo done by the program figlet */ char LOGO_01[] = " _ _ _____ __ __ _ "; char LOGO_02[] = "| | | |/ ____| \\/ | | |"; char LOGO_03[] = "| | | | (___ | \\ / | ___ __| |"; char LOGO_04[] = "| | | |\\___ \\| |\\/| |/ _ \\/ _` |"; char LOGO_05[] = "| |__| |____) | | | | __/ (_| |"; char LOGO_06[] = " \\____/|_____/|_| |_|\\___|\\__,_|"; char LOGO_07[] = " "; /* Help Menu */ char HELP_01[] = "r: This will replace a one string for another"; char HELP_02[] = "f: Find a string (NOTE: the '/' will also work)"; char HELP_03[] = "n: Find next string"; char HELP_04[] = "i: Insert text in last found position"; char HELP_05[] = "I: Insert text in a user specified position"; char HELP_06[] = "d: Delete the last string you found"; char HELP_07[] = "D: Delete user chooses where and how many spaces to del"; char HELP_08[] = "p: Page Down (NOTE: the will also work)"; char HELP_09[] = "b: Page Up (NOTE: the will also work)"; char HELP_10[] = "q: This will quit USMed"; /* this will clean the display out so I can print all this */ ClearDisplay(); /* print the program intro, version, and author */ mvwaddnstr(display, 1, (((COLS - 2) / 2) - (Length(PROG_INTRO) / 2)), PROG_INTRO, (MAX_CHARS + 1)); mvwaddnstr(display, 2, (((COLS - 2) / 2) - (Length(PROG_VERSION) / 2)), PROG_VERSION, (MAX_CHARS + 1)); mvwaddnstr(display, 3, (((COLS - 2) / 2) - (Length(PROG_AUTHOR) / 2)), PROG_AUTHOR, (MAX_CHARS + 1)); /* print the cute looking logo */ wstandout(display); /* makes the print stand out */ mvwaddnstr(display, 5, (((COLS - 2) / 2) - (Length(LOGO_01) / 2)), LOGO_01, (MAX_CHARS + 1)); mvwaddnstr(display, 6, (((COLS - 2) / 2) - (Length(LOGO_02) / 2)), LOGO_02, (MAX_CHARS + 1)); mvwaddnstr(display, 7, (((COLS - 2) / 2) - (Length(LOGO_03) / 2)), LOGO_03, (MAX_CHARS + 1)); mvwaddnstr(display, 8, (((COLS - 2) / 2) - (Length(LOGO_04) / 2)), LOGO_04, (MAX_CHARS + 1)); mvwaddnstr(display, 9, (((COLS - 2) / 2) - (Length(LOGO_05) / 2)), LOGO_05, (MAX_CHARS + 1)); mvwaddnstr(display, 10, (((COLS - 2) / 2) - (Length(LOGO_06) / 2)), LOGO_06, (MAX_CHARS + 1)); mvwaddnstr(display, 11, (((COLS - 2) / 2) - (Length(LOGO_07) / 2)), LOGO_07, (MAX_CHARS + 1)); wstandend(display); /* ends the stand out print */ /* Print the Help Menu */ mvwaddnstr(display, 15, 2, HELP_01, (MAX_CHARS + 1)); mvwaddnstr(display, 16, 2, HELP_02, (MAX_CHARS + 1)); mvwaddnstr(display, 17, 2, HELP_03, (MAX_CHARS + 1)); mvwaddnstr(display, 18, 2, HELP_04, (MAX_CHARS + 1)); mvwaddnstr(display, 19, 2, HELP_05, (MAX_CHARS + 1)); mvwaddnstr(display, 20, 2, HELP_06, (MAX_CHARS + 1)); mvwaddnstr(display, 21, 2, HELP_07, (MAX_CHARS + 1)); mvwaddnstr(display, 22, 2, HELP_08, (MAX_CHARS + 1)); mvwaddnstr(display, 22, 2, HELP_09, (MAX_CHARS + 1)); mvwaddnstr(display, 22, 2, HELP_10, (MAX_CHARS + 1)); RefreshScreen(); /* refresh updated display */ } /************************************************************ * Die() -- clears terminal and prints any self made error * * * * Parameters * * error -- error message if any * * * * Returns * * void * ************************************************************/ void CursStrType::Die(char error[]) { mvcur(0, COLS - 1, LINES - 1, 0); /* move cursor to lower left */ clear(); /* clear screen */ refresh(); /* screen is clear now print */ endwin(); /* end window */ fprintf(stderr, "%s\n", error); /* print error to user */ exit(1); /* exit nasty */ }