/* Print out a summary giving the number of catalog entries * and total number of tracks across all of them */ static void count_all_entries(void) { int cd_entries_found = 0; int track_entries_found = 0; cdc_entry cdc_found; cdt_entry cdt_found; int track_no = 1; int first_time = 1; char *search_string = ""; // loop over all cdc entries. The `first_time` is a flag which should // be 1 ("first time = true") on the initial call; it gets set to 0 (note // it's passed via ptr), and internally the database code tracks the // progress of the search from that point forward do { cdc_found = search_cdc_entry(search_string, &first_time); if (cdc_found.catalog[0]) { cd_entries_found++; track_no = 1; do { cdt_found = get_cdt_entry(cdc_found.catalog, track_no); if (cdt_found.catalog[0]) { track_entries_found++; track_no++; } } while (cdt_found.catalog[0]); } } while (cdc_found.catalog[0]); printf("Found %d CDs, with a total of %d tracks\n", cd_entries_found, track_entries_found); get_confirm("Press Enter"); }
static void count_all_entries(void) { int cd_entries_found = 0; int track_entries_found = 0; cdc_entry cdc_found; cdt_entry cdt_found; int track_no = 1; int first_time = 1; char *search_string = ""; do { cdc_found = search_cdc_entry(search_string, &first_time); if (cdc_found.catalog[0]) { cd_entries_found++; track_no = 1; do { cdt_found = get_cdt_entry(cdc_found.catalog, track_no); if (cdt_found.catalog[0]) { track_entries_found++; track_no++; } } while (cdt_found.catalog[0]); } } while (cdc_found.catalog[0]); printf("Found %d CDs, with a total of %d tracks\n", cd_entries_found, track_entries_found); (void)get_confirm("Press return"); }
static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; if (entry_to_add_to->catalog[0] == '\0') { return; } printf("\nUpdating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); while (1) { memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); if (existing_track.catalog[0]) { printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { /* no existing entry, so finish adding */ break; } else { /* leave existing entry, jump to next track */ track_no++; continue; } } if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { /* delete this and ramaining tracks */ while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } strncpy(new_track.track_txt, tmp_str, TRACK_TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } /* while */ }
/* prints out all tracks for a given catalog entry */ static void list_tracks(const cdc_entry *entry_to_use) { int track_no = 1; cdt_entry entry_found; display_cdc(entry_to_use); printf("\nTracks\n"); do { entry_found = get_cdt_entry(entry_to_use->catalog, track_no); if (entry_found.catalog[0]) { display_cdt(&entry_found); track_no++; } } while(entry_found.catalog[0]); get_confirm("Press return"); } /* list tracks */
/* list tracks for the active catalog */ static void list_tracks(const cdc_entry *entry_to_use) { int track_no = 1; cdt_entry entry_found; // first display the current catalog display_cdc(entry_to_use); // loop over entries and display them printf("\nTracks\n"); do { entry_found = get_cdt_entry(entry_to_use->catalog, track_no); if (entry_found.catalog[0]) { display_cdt(&entry_found); track_no++; } } while (entry_found.catalog[0]); // let the user look before returning to menu get_confirm("Press return"); }
/* Mildly misnamed function... it loops through existing track entries if * there are any and the user can either edit description or delete this and * all later entries. When it finishes looping over existing entries, the user * can also add new ones. */ static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; // if there's no current catalog, do nothing if (entry_to_add_to->catalog[0] == '\0') return; // print out instructions printf("Updating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); // loop over tracks, let the user choose what to do with each one. // note that dbm is helping a lot here - in our flat file curses impl // from ch6, the only easy things to do were to keep all tracks or // redo everything. Dbm makes single-track changes much easier. // We are still somewhat limited because the track ids have to be in // increaseing order. So you can edit descriptions atomically, but if // you delete one you have to delete everything later. We could get // around this, but it would be too much work for a demo program. while (1) { memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); // existing track.caltalog[0] is set to 0 by get_cdt_entry if there // is no track with track number `track_no`. Hence.. if(existing_track.catalog[0]) { // if we are here, there's a track description already printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { // if we are here, there is not printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); // If tmp_str has length 0, the user didn't want to do anything for // this track. if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { // if this is true, then we had already seen all existing // tracks, so we are done. break; } else { // if we get here, it means the user didn't want to edit this // track, so we go on to the next one. track_no++; continue; } } // Entering a single 'd' is a special case for delete this track and // all later tracks, as mentioned in the instructions printed above. // So, loop through all remaining tracks, delete, then break. if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { // del_cdt_entry will return 0 when we try to delete a nonexistant // track_no, so we use that as our terminate condition. while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } // if we get here, it means the user made a new description, so we // edit the existing track or add a new one (the api is the same, so // we don't care at this point whether the track exists) strncpy(new_track.track_txt, tmp_str, TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } // end of the big while loop over track_no's }
static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; if (entry_to_add_to->catalog[0] == '\0') return; printf("\nUpdating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); while(1) { /* First, we must check whether a track already exists with the current track number. Depending on what we find, we change the prompt. */ memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); if (existing_track.catalog[0]) { printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); /* If there was no existing entry for this track and the user hasn't added one, we assume that there are no more tracks to be added. */ if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { /* no existing entry, so finished adding */ break; } else { /* leave existing entry, jump to next track */ track_no++; continue; } } /* If the user enters a single d character, this deletes the current and any higher numbered tracks. The del_cdt_entry function will return false if it couldn't find a track to delete. */ if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { /* delete this and remaining tracks */ while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } /* Here we get to the code for adding a new track, or updating an existing one. We construct the cdt_entry structure new_track, then call the database function add_cdt_entry to add it to the database. */ strncpy(new_track.track_txt, tmp_str, TRACK_TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } /* while */ }
/* Enter new track entries for a cdc entry. * * You have the option of looping through some exiting tracks and leaving * them unchanged, but if you do change anything, it and everything after it * will get deleted. Then you can add lots of tracks if you want. * * You enter a blank line to indicate you are finished. */ static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; if (entry_to_add_to->catalog[0] == '\0') return; printf("\nUpdating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); while(1) { // set up a prompt. Either the track exists and we give the user // an option of changing the text, or if the track doesn't exist then // we ask for a description. memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); if (existing_track.catalog[0]) { printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); // if they entered a blank line *and* we already went through existing // tracks, then we are done. // If we aren't finished with existing tracks and they entered a blank // line, just go on to the next one. if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { /* no existing entry, so finished adding */ break; } else { /* leave existing entry, jump to next track */ track_no++; continue; } } // if they entered a d, delete this track and loop through all higher- // numbered tracks and delete them, then exit. if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } // otherwise, they entered new track data. Whether or not the track // previously existed, we copy that data into a ctd entry and add it // to the db on the current track_no strncpy(new_track.track_txt, tmp_str, TRACK_TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } }