Changes for version 0.8.0
diff --git a/gpttext.cc b/gpttext.cc
index 4db9e13..cd1c07a 100644
--- a/gpttext.cc
+++ b/gpttext.cc
@@ -33,11 +33,11 @@
 
 using namespace std;
 
-/*******************************************
-*                                          *
-* GPTDataText class and related structures *
-*                                          *
-********************************************/
+/********************************************
+ *                                          *
+ * GPTDataText class and related structures *
+ *                                          *
+ ********************************************/
 
 GPTDataTextUI::GPTDataTextUI(void) : GPTData() {
 } // default constructor
@@ -141,7 +141,8 @@
  *                                                                   *
  *********************************************************************/
 
-// Prompts user for partition number and returns the result.
+// Prompts user for partition number and returns the result. Returns "0"
+// (the first partition) if none are currently defined.
 uint32_t GPTDataTextUI::GetPartNum(void) {
    uint32_t partNum;
    uint32_t low, high;
@@ -257,7 +258,6 @@
 } // GPTDataTextUI::DeletePartition()
 
 // Prompt user for a partition number, then change its type code
-// using ChangeGPTType(struct GPTPartition*) function.
 void GPTDataTextUI::ChangePartType(void) {
    int partNum;
    uint32_t low, high;
@@ -494,6 +494,370 @@
    return protectiveMBR.DoMenu();
 } // GPTDataTextUI::XFormToMBR()
 
+
+/*********************************************************************
+ *                                                                   *
+ * The following functions provide the main menus for the gdisk      *
+ * program....                                                       *
+ *                                                                   *
+ *********************************************************************/
+
+// Accept a command and execute it. Returns only when the user
+// wants to exit (such as after a 'w' or 'q' command).
+void GPTDataTextUI::MainMenu(string filename) {
+   int goOn = 1;
+   PartType typeHelper;
+   uint32_t temp1, temp2;
+   
+   do {
+      cout << "\nCommand (? for help): ";
+      switch (ReadString()[0]) {
+         case '\0':
+            break;
+         case 'b': case 'B':
+            cout << "Enter backup filename to save: ";
+            SaveGPTBackup(ReadString());
+            break;
+         case 'c': case 'C':
+            if (GetPartRange(&temp1, &temp2) > 0)
+               SetName(GetPartNum());
+            else
+               cout << "No partitions\n";
+            break;
+         case 'd': case 'D':
+            DeletePartition();
+            break;
+         case 'i': case 'I':
+            ShowDetails();
+            break;
+         case 'l': case 'L':
+            typeHelper.ShowAllTypes();
+            break;
+         case 'n': case 'N':
+            CreatePartition();
+            break;
+         case 'o': case 'O':
+            cout << "This option deletes all partitions and creates a new protective MBR.\n"
+                 << "Proceed? ";
+            if (GetYN() == 'Y') {
+               ClearGPTData();
+               MakeProtectiveMBR();
+            } // if
+            break;
+         case 'p': case 'P':
+            DisplayGPTData();
+            break;
+         case 'q': case 'Q':
+            goOn = 0;
+            break;
+         case 'r': case 'R':
+            RecoveryMenu(filename);
+            goOn = 0;
+            break;
+         case 's': case 'S':
+            SortGPT();
+            cout << "You may need to edit /etc/fstab and/or your boot loader configuration!\n";
+            break;
+         case 't': case 'T':
+            ChangePartType();
+            break;
+         case 'v': case 'V':
+            Verify();
+            break;
+         case 'w': case 'W':
+            if (SaveGPTData() == 1)
+               goOn = 0;
+            break;
+         case 'x': case 'X':
+            ExpertsMenu(filename);
+            goOn = 0;
+            break;
+         default:
+            ShowCommands();
+            break;
+      } // switch
+   } while (goOn);
+} // GPTDataTextUI::MainMenu()
+
+void GPTDataTextUI::ShowCommands(void) {
+   cout << "b\tback up GPT data to a file\n";
+   cout << "c\tchange a partition's name\n";
+   cout << "d\tdelete a partition\n";
+   cout << "i\tshow detailed information on a partition\n";
+   cout << "l\tlist known partition types\n";
+   cout << "n\tadd a new partition\n";
+   cout << "o\tcreate a new empty GUID partition table (GPT)\n";
+   cout << "p\tprint the partition table\n";
+   cout << "q\tquit without saving changes\n";
+   cout << "r\trecovery and transformation options (experts only)\n";
+   cout << "s\tsort partitions\n";
+   cout << "t\tchange a partition's type code\n";
+   cout << "v\tverify disk\n";
+   cout << "w\twrite table to disk and exit\n";
+   cout << "x\textra functionality (experts only)\n";
+   cout << "?\tprint this menu\n";
+} // GPTDataTextUI::ShowCommands()
+
+// Accept a recovery & transformation menu command. Returns only when the user
+// issues an exit command, such as 'w' or 'q'.
+void GPTDataTextUI::RecoveryMenu(string filename) {
+   uint32_t numParts;
+   int goOn = 1, temp1;
+   
+   do {
+      cout << "\nRecovery/transformation command (? for help): ";
+      switch (ReadString()[0]) {
+         case '\0':
+            break;
+         case 'b': case 'B':
+            RebuildMainHeader();
+            break;
+         case 'c': case 'C':
+            cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
+            << "GPT form and haven't yet saved the GPT! Proceed? ";
+            if (GetYN() == 'Y')
+               LoadSecondTableAsMain();
+            break;
+         case 'd': case 'D':
+            RebuildSecondHeader();
+            break;
+         case 'e': case 'E':
+            cout << "Warning! This will probably do weird things if you've converted an MBR to\n"
+            << "GPT form and haven't yet saved the GPT! Proceed? ";
+            if (GetYN() == 'Y')
+               LoadMainTable();
+            break;
+         case 'f': case 'F':
+            cout << "Warning! This will destroy the currently defined partitions! Proceed? ";
+            if (GetYN() == 'Y') {
+               if (LoadMBR(filename) == 1) { // successful load
+                  XFormPartitions();
+               } else {
+                  cout << "Problem loading MBR! GPT is untouched; regenerating protective MBR!\n";
+                  MakeProtectiveMBR();
+               } // if/else
+            } // if
+            break;
+         case 'g': case 'G':
+            numParts = GetNumParts();
+            temp1 = XFormToMBR();
+            if (temp1 > 0)
+               cout << "\nConverted " << temp1 << " partitions. Finalize and exit? ";
+            if ((temp1 > 0) && (GetYN() == 'Y')) {
+               if ((DestroyGPT() > 0) && (SaveMBR())) {
+                  goOn = 0;
+               } // if
+            } else {
+               MakeProtectiveMBR();
+               SetGPTSize(numParts);
+               cout << "Note: New protective MBR created\n\n";
+            } // if/else
+            break;
+         case 'h': case 'H':
+            MakeHybrid();
+            break;
+         case 'i': case 'I':
+            ShowDetails();
+            break;
+         case 'l': case 'L':
+            cout << "Enter backup filename to load: ";
+            LoadGPTBackup(ReadString());
+            break;
+         case 'm': case 'M':
+            MainMenu(filename);
+            goOn = 0;
+            break;
+         case 'o': case 'O':
+            DisplayMBRData();
+            break;
+         case 'p': case 'P':
+            DisplayGPTData();
+            break;
+         case 'q': case 'Q':
+            goOn = 0;
+            break;
+         case 't': case 'T':
+            XFormDisklabel();
+            break;
+         case 'v': case 'V':
+            Verify();
+            break;
+         case 'w': case 'W':
+            if (SaveGPTData() == 1) {
+               goOn = 0;
+            } // if
+            break;
+         case 'x': case 'X':
+            ExpertsMenu(filename);
+            goOn = 0;
+            break;
+         default:
+            ShowRecoveryCommands();
+            break;
+      } // switch
+   } while (goOn);
+} // GPTDataTextUI::RecoveryMenu()
+
+void GPTDataTextUI::ShowRecoveryCommands(void) {
+   cout << "b\tuse backup GPT header (rebuilding main)\n";
+   cout << "c\tload backup partition table from disk (rebuilding main)\n";
+   cout << "d\tuse main GPT header (rebuilding backup)\n";
+   cout << "e\tload main partition table from disk (rebuilding backup)\n";
+   cout << "f\tload MBR and build fresh GPT from it\n";
+   cout << "g\tconvert GPT into MBR and exit\n";
+   cout << "h\tmake hybrid MBR\n";
+   cout << "i\tshow detailed information on a partition\n";
+   cout << "l\tload partition data from a backup file\n";
+   cout << "m\treturn to main menu\n";
+   cout << "o\tprint protective MBR data\n";
+   cout << "p\tprint the partition table\n";
+   cout << "q\tquit without saving changes\n";
+   cout << "t\ttransform BSD disklabel partition\n";
+   cout << "v\tverify disk\n";
+   cout << "w\twrite table to disk and exit\n";
+   cout << "x\textra functionality (experts only)\n";
+   cout << "?\tprint this menu\n";
+} // GPTDataTextUI::ShowRecoveryCommands()
+
+// Accept an experts' menu command. Returns only after the user
+// selects an exit command, such as 'w' or 'q'.
+void GPTDataTextUI::ExpertsMenu(string filename) {
+   GPTData secondDevice;
+   uint32_t temp1, temp2;
+   int goOn = 1;
+   string guidStr, device;
+   GUIDData aGUID;
+   ostringstream prompt;
+   
+   do {
+      cout << "\nExpert command (? for help): ";
+      switch (ReadString()[0]) {
+         case '\0':
+            break;
+         case 'a': case 'A':
+            if (GetPartRange(&temp1, &temp2) > 0)
+               SetAttributes(GetPartNum());
+            else
+               cout << "No partitions\n";
+            break;
+         case 'c': case 'C':
+            ChangeUniqueGuid();
+            break;
+         case 'd': case 'D':
+            cout << "Partitions will begin on " << GetAlignment()
+            << "-sector boundaries.\n";
+            break;
+         case 'e': case 'E':
+            cout << "Relocating backup data structures to the end of the disk\n";
+            MoveSecondHeaderToEnd();
+            break;
+         case 'f': case 'F':
+            RandomizeGUIDs();
+            break;
+         case 'g': case 'G':
+            cout << "Enter the disk's unique GUID ('R' to randomize): ";
+            guidStr = ReadString();
+            if ((guidStr.length() >= 32) || (guidStr[0] == 'R') || (guidStr[0] == 'r')) {
+               SetDiskGUID((GUIDData) guidStr);
+               cout << "The new disk GUID is " << GetDiskGUID() << "\n";
+            } else {
+               cout << "GUID is too short!\n";
+            } // if/else
+            break;
+         case 'h': case 'H':
+            RecomputeCHS();
+            break;
+         case 'i': case 'I':
+            ShowDetails();
+            break;
+         case 'l': case 'L':
+            prompt.seekp(0);
+            prompt << "Enter the sector alignment value (1-" << MAX_ALIGNMENT << ", default = "
+                   << DEFAULT_ALIGNMENT << "): ";
+            temp1 = GetNumber(1, MAX_ALIGNMENT, DEFAULT_ALIGNMENT, prompt.str());
+            SetAlignment(temp1);
+            break;
+         case 'm': case 'M':
+            MainMenu(filename);
+            goOn = 0;
+            break;
+         case 'n': case 'N':
+            MakeProtectiveMBR();
+            break;
+         case 'o': case 'O':
+            DisplayMBRData();
+            break;
+         case 'p': case 'P':
+            DisplayGPTData();
+            break;
+         case 'q': case 'Q':
+            goOn = 0;
+            break;
+         case 'r': case 'R':
+            RecoveryMenu(filename);
+            goOn = 0;
+            break;
+         case 's': case 'S':
+            ResizePartitionTable();
+            break;
+         case 't': case 'T':
+            SwapPartitions();
+            break;
+         case 'u': case 'U':
+            cout << "Type device filename, or press <Enter> to exit: ";
+            device = ReadString();
+            if (device.length() > 0) {
+               secondDevice = *this;
+               secondDevice.SetDisk(device);
+               secondDevice.SaveGPTData(0);
+            } // if
+            break;
+         case 'v': case 'V':
+            Verify();
+            break;
+         case 'w': case 'W':
+            if (SaveGPTData() == 1) {
+               goOn = 0;
+            } // if
+            break;
+         case 'z': case 'Z':
+            if (DestroyGPTwPrompt() == 1) {
+               goOn = 0;
+            }
+            break;
+         default:
+            ShowExpertCommands();
+            break;
+      } // switch
+   } while (goOn);
+} // GPTDataTextUI::ExpertsMenu()
+
+void GPTDataTextUI::ShowExpertCommands(void) {
+   cout << "a\tset attributes\n";
+   cout << "c\tchange partition GUID\n";
+   cout << "d\tdisplay the sector alignment value\n";
+   cout << "e\trelocate backup data structures to the end of the disk\n";
+   cout << "g\tchange disk GUID\n";
+   cout << "h\trecompute CHS values in protective/hybrid MBR\n";
+   cout << "i\tshow detailed information on a partition\n";
+   cout << "l\tset the sector alignment value\n";
+   cout << "m\treturn to main menu\n";
+   cout << "n\tcreate a new protective MBR\n";
+   cout << "o\tprint protective MBR data\n";
+   cout << "p\tprint the partition table\n";
+   cout << "q\tquit without saving changes\n";
+   cout << "r\trecovery and transformation options (experts only)\n";
+   cout << "s\tresize partition table\n";
+   cout << "t\ttranspose two partition table entries\n";
+   cout << "u\tReplicate partition table on new device\n";
+   cout << "v\tverify disk\n";
+   cout << "w\twrite table to disk and exit\n";
+   cout << "z\tzap (destroy) GPT data structures and exit\n";
+   cout << "?\tprint this menu\n";
+} // GPTDataTextUI::ShowExpertCommands()
+
+
+
 /********************************
  *                              *
  * Non-class support functions. *