00001 #include "menuresp.h"
00002
00003 #include <iostream>
00004 #include <iomanip>
00005 #include <cstring>
00006 #include <cctype>
00007 #include "arrutil.h"
00008 #include "genutil.h"
00009
00010 #define TEMPLATE_CLASSES_WONT_COMPILE
00011 #include "array.h"
00012
00013 using namespace std;
00014
00015 MenuChoice::MenuChoice() : number(NULL), letters(NULL) { }
00016
00017 MenuChoice::MenuChoice(const char n[], const char L[])
00018 : number(new char [strlen(n)+1]), letters(new char [strlen(L)+1])
00019 {
00020 if (number != NULL) {
00021 strcpy(number, n);
00022 }
00023 if (letters != NULL) {
00024 strcpy(letters, L);
00025 }
00026 }
00027
00028 MenuChoice::MenuChoice(const MenuChoice & choice)
00029 : number(new char [strlen(choice.number)+1]),
00030 letters(new char [strlen(choice.letters)+1])
00031 {
00032 if (number != NULL) {
00033 strcpy(number, choice.number);
00034 }
00035 if (letters != NULL) {
00036 strcpy(letters, choice.letters);
00037 }
00038 }
00039
00040 MenuChoice::~MenuChoice() {
00041 delete [] number;
00042 number = NULL;
00043 delete [] letters;
00044 letters = NULL;
00045 }
00046
00047 MenuChoice & MenuChoice::operator = (const MenuChoice & choice) {
00048 if (this != &choice)
00049 {
00050 delete [] number;
00051 number = new char [strlen(choice.number)+1];
00052 if (number != NULL) {
00053 strcpy(number, choice.number);
00054 }
00055 delete [] letters;
00056 letters = new char [strlen(choice.letters)+1];
00057 if (letters != NULL) {
00058 strcpy(letters, choice.letters);
00059 }
00060 }
00061 return *this;
00062 }
00063
00064 bool MenuChoice::operator == (const MenuChoice & choice) const {
00065 return ((strcmp(number, choice.number) == 0) &&
00066 (strcmp(letters, choice.letters) == 0));
00067 }
00068
00069 bool MenuChoice::operator == (const char choice[]) const {
00070 return ((strcmp(number, choice) == 0) ||
00071 (strstr(letters, choice) != NULL));
00072 }
00073
00074 bool MenuChoice::operator == (const char choice) const {
00075 return ((strchr(number, choice) != NULL) ||
00076 (strchr(letters, choice) != NULL));
00077 }
00078
00079 MenuResponse::MenuResponse(const char menu_text[])
00080 : menu(new char [strlen(menu_text)+1]), valid_choices()
00081 {
00082 if (menu != NULL) {
00083 strcpy(menu, menu_text);
00084 update_choices();
00085 }
00086 }
00087
00088 MenuResponse::MenuResponse(const char * menu_text[], long items )
00089 : menu(NULL), valid_choices()
00090 {
00091 long chars, strs, s;
00092 if (items == 0) {
00093 strs = 0;
00094 while (menu_text[strs][0] != '\0') {
00095 strs++;
00096 }
00097 }
00098 else {
00099 strs = items;
00100 }
00101 if (strs > 0) {
00102 for (chars = 0, s = 0; s < strs; s++) {
00103 chars += strlen(menu_text[s]);
00104 }
00105 menu = new char [chars+1];
00106 if (menu != NULL) {
00107 strcpy(menu, menu_text[0]);
00108 for (s = 1; s < strs; s++) {
00109 strcat(menu, menu_text[s]);
00110 }
00111 update_choices();
00112 }
00113 }
00114 }
00115
00116 MenuResponse::MenuResponse(const MenuResponse & resp)
00117 : menu(new char [strlen(resp.menu)+1]), valid_choices()
00118 {
00119 if (menu != NULL) {
00120 strcpy(menu, resp.menu);
00121 update_choices();
00122 }
00123 }
00124
00125 MenuResponse::~MenuResponse() {
00126 delete [] menu;
00127 menu = NULL;
00128 }
00129
00130 MenuResponse & MenuResponse::operator = (const MenuResponse & resp) {
00131 if (this != &resp)
00132 {
00133 delete [] menu;
00134 menu = new char [strlen(resp.menu)+1];
00135 if (menu != NULL) {
00136 strcpy(menu, resp.menu);
00137 update_choices();
00138 }
00139 }
00140 return *this;
00141 }
00142
00143 void do_toupper(char & ch) {
00144 ch = toupper(ch);
00145 return;
00146 }
00147
00148 long MenuResponse::get_response(void) const {
00149 char choice[12];
00150 long i;
00151
00152 cout << menu;
00153 cin >> setw(12) >> choice;
00154 for_each(choice, 0, strlen(choice)-1, do_toupper);
00155 i = find_if(valid_choices, 0, valid_choices.get_end(), (const char*)choice,
00156 isEqualTo<MenuChoice,const char*>);
00157
00158 while (i < 0) {
00159 cout << "Invalid menu choice!" << endl << endl
00160 << menu;
00161 cin >> setw(12) >> choice;
00162 for_each(choice, 0, strlen(choice)-1, do_toupper);
00163 i = find_if(valid_choices, 0, valid_choices.get_end(),
00164 (const char*)choice,
00165 isEqualTo<MenuChoice,const char*>);
00166
00167 }
00168 return i;
00169 }
00170
00171
00172
00173 bool is_num_start(char x) {
00174 return (isdigit(x) || (x == '-'));
00175 }
00176
00177 void MenuResponse::update_choices(void) {
00178 char *num_start, *num_end, *cur, was, *caps;
00179 MenuChoice *item;
00180 long num_caps, cur_ch;
00181
00182
00183
00184 valid_choices.resize(count_nonconseq_if(menu, 0, strlen(menu)-1, '\n',
00185 isEqualTo<char,char>));
00186 cur = menu;
00187 cur_ch = 0;
00188 while ((*cur != '\0') && (cur_ch < valid_choices.get_size())) {
00189 while ((*cur != '\0') && !is_num_start(*cur)) {
00190 cur++;
00191 }
00192 while ((is_num_start(*cur)) && (cur_ch < valid_choices.get_size())) {
00193 num_start = cur;
00194 do {
00195 cur++;
00196 } while (isdigit(*cur));
00197 num_end = cur;
00198 num_caps = 0;
00199 while ((*cur != '\0') && !is_num_start(*cur)) {
00200 if (isupper(*cur)) {
00201 num_caps++;
00202 }
00203
00204 cur++;
00205 }
00206 caps = new char [num_caps+1];
00207 cur = num_end;
00208 num_caps = 0;
00209 while ((*cur != '\0') && !is_num_start(*cur)) {
00210 if (isupper(*cur)) {
00211 caps[num_caps++] = *cur;
00212 }
00213 cur++;
00214 }
00215 caps[num_caps] = '\0';
00216 was = '\0';
00217 ::swap(*num_end, was);
00218 item = new MenuChoice(num_start, caps);
00219 ::swap(*num_end, was);
00220 valid_choices[cur_ch++] = *item;
00221 delete [] caps;
00222 delete item;
00223
00224
00225 }
00226 }
00227 valid_choices.resize(cur_ch);
00228 return;
00229 }