xref: /aosp_15_r20/external/gptfdisk/gptcurses.cc (revision 57696d54d05c64fd1b1787f8371dbcf104911cfb)
1*57696d54SAkhilesh Sanikop /*
2*57696d54SAkhilesh Sanikop  *    Implementation of GPTData class derivative with curses-based text-mode
3*57696d54SAkhilesh Sanikop  *    interaction
4*57696d54SAkhilesh Sanikop  *    Copyright (C) 2011-2022 Roderick W. Smith
5*57696d54SAkhilesh Sanikop  *
6*57696d54SAkhilesh Sanikop  *    This program is free software; you can redistribute it and/or modify
7*57696d54SAkhilesh Sanikop  *    it under the terms of the GNU General Public License as published by
8*57696d54SAkhilesh Sanikop  *    the Free Software Foundation; either version 2 of the License, or
9*57696d54SAkhilesh Sanikop  *    (at your option) any later version.
10*57696d54SAkhilesh Sanikop  *
11*57696d54SAkhilesh Sanikop  *    This program is distributed in the hope that it will be useful,
12*57696d54SAkhilesh Sanikop  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*57696d54SAkhilesh Sanikop  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*57696d54SAkhilesh Sanikop  *    GNU General Public License for more details.
15*57696d54SAkhilesh Sanikop  *
16*57696d54SAkhilesh Sanikop  *    You should have received a copy of the GNU General Public License along
17*57696d54SAkhilesh Sanikop  *    with this program; if not, write to the Free Software Foundation, Inc.,
18*57696d54SAkhilesh Sanikop  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*57696d54SAkhilesh Sanikop  *
20*57696d54SAkhilesh Sanikop  */
21*57696d54SAkhilesh Sanikop 
22*57696d54SAkhilesh Sanikop #include <clocale>
23*57696d54SAkhilesh Sanikop #include <iostream>
24*57696d54SAkhilesh Sanikop #include <string>
25*57696d54SAkhilesh Sanikop #include <sstream>
26*57696d54SAkhilesh Sanikop #if defined (__APPLE__) || (__FreeBSD__)
27*57696d54SAkhilesh Sanikop #include <ncurses.h>
28*57696d54SAkhilesh Sanikop #else
29*57696d54SAkhilesh Sanikop #include <ncursesw/ncurses.h>
30*57696d54SAkhilesh Sanikop #endif
31*57696d54SAkhilesh Sanikop #include "gptcurses.h"
32*57696d54SAkhilesh Sanikop #include "support.h"
33*57696d54SAkhilesh Sanikop 
34*57696d54SAkhilesh Sanikop using namespace std;
35*57696d54SAkhilesh Sanikop 
36*57696d54SAkhilesh Sanikop // # of lines to reserve for general information and headers (RESERVED_TOP)
37*57696d54SAkhilesh Sanikop // and for options and messages (RESERVED_BOTTOM)
38*57696d54SAkhilesh Sanikop #define RESERVED_TOP 7
39*57696d54SAkhilesh Sanikop #define RESERVED_BOTTOM 5
40*57696d54SAkhilesh Sanikop 
41*57696d54SAkhilesh Sanikop int GPTDataCurses::numInstances = 0;
42*57696d54SAkhilesh Sanikop 
GPTDataCurses(void)43*57696d54SAkhilesh Sanikop GPTDataCurses::GPTDataCurses(void) {
44*57696d54SAkhilesh Sanikop    if (numInstances > 0) {
45*57696d54SAkhilesh Sanikop       refresh();
46*57696d54SAkhilesh Sanikop    } else {
47*57696d54SAkhilesh Sanikop       setlocale( LC_ALL , "" );
48*57696d54SAkhilesh Sanikop       initscr();
49*57696d54SAkhilesh Sanikop       cbreak();
50*57696d54SAkhilesh Sanikop       noecho();
51*57696d54SAkhilesh Sanikop       intrflush(stdscr, false);
52*57696d54SAkhilesh Sanikop       keypad(stdscr, true);
53*57696d54SAkhilesh Sanikop       nonl();
54*57696d54SAkhilesh Sanikop       numInstances++;
55*57696d54SAkhilesh Sanikop    } // if/else
56*57696d54SAkhilesh Sanikop    firstSpace = NULL;
57*57696d54SAkhilesh Sanikop    lastSpace = NULL;
58*57696d54SAkhilesh Sanikop    currentSpace = NULL;
59*57696d54SAkhilesh Sanikop    currentSpaceNum = -1;
60*57696d54SAkhilesh Sanikop    whichOptions = ""; // current set of options
61*57696d54SAkhilesh Sanikop    currentKey = 'b'; // currently selected option
62*57696d54SAkhilesh Sanikop    displayType = USE_CURSES;
63*57696d54SAkhilesh Sanikop } // GPTDataCurses constructor
64*57696d54SAkhilesh Sanikop 
~GPTDataCurses(void)65*57696d54SAkhilesh Sanikop GPTDataCurses::~GPTDataCurses(void) {
66*57696d54SAkhilesh Sanikop    numInstances--;
67*57696d54SAkhilesh Sanikop    if ((numInstances == 0) && !isendwin())
68*57696d54SAkhilesh Sanikop       endwin();
69*57696d54SAkhilesh Sanikop } // GPTDataCurses destructor
70*57696d54SAkhilesh Sanikop 
71*57696d54SAkhilesh Sanikop /************************************************
72*57696d54SAkhilesh Sanikop  *                                              *
73*57696d54SAkhilesh Sanikop  * Functions relating to Spaces data structures *
74*57696d54SAkhilesh Sanikop  *                                              *
75*57696d54SAkhilesh Sanikop  ************************************************/
76*57696d54SAkhilesh Sanikop 
EmptySpaces(void)77*57696d54SAkhilesh Sanikop void GPTDataCurses::EmptySpaces(void) {
78*57696d54SAkhilesh Sanikop    Space *trash;
79*57696d54SAkhilesh Sanikop 
80*57696d54SAkhilesh Sanikop    while (firstSpace != NULL) {
81*57696d54SAkhilesh Sanikop       trash = firstSpace;
82*57696d54SAkhilesh Sanikop       firstSpace = firstSpace->nextSpace;
83*57696d54SAkhilesh Sanikop       delete trash;
84*57696d54SAkhilesh Sanikop    } // if
85*57696d54SAkhilesh Sanikop    numSpaces = 0;
86*57696d54SAkhilesh Sanikop    lastSpace = NULL;
87*57696d54SAkhilesh Sanikop } // GPTDataCurses::EmptySpaces()
88*57696d54SAkhilesh Sanikop 
89*57696d54SAkhilesh Sanikop // Create Spaces from partitions. Does NOT creates Spaces to represent
90*57696d54SAkhilesh Sanikop // unpartitioned space on the disk.
91*57696d54SAkhilesh Sanikop // Returns the number of Spaces created.
MakeSpacesFromParts(void)92*57696d54SAkhilesh Sanikop int GPTDataCurses::MakeSpacesFromParts(void) {
93*57696d54SAkhilesh Sanikop    uint32_t i;
94*57696d54SAkhilesh Sanikop    Space *tempSpace;
95*57696d54SAkhilesh Sanikop 
96*57696d54SAkhilesh Sanikop    EmptySpaces();
97*57696d54SAkhilesh Sanikop    for (i = 0; i < numParts; i++) {
98*57696d54SAkhilesh Sanikop       if (partitions[i].IsUsed()) {
99*57696d54SAkhilesh Sanikop          tempSpace = new Space;
100*57696d54SAkhilesh Sanikop          tempSpace->firstLBA = partitions[i].GetFirstLBA();
101*57696d54SAkhilesh Sanikop          tempSpace->lastLBA = partitions[i].GetLastLBA();
102*57696d54SAkhilesh Sanikop          tempSpace->origPart = &partitions[i];
103*57696d54SAkhilesh Sanikop          tempSpace->partNum = (int) i;
104*57696d54SAkhilesh Sanikop          LinkToEnd(tempSpace);
105*57696d54SAkhilesh Sanikop       } // if
106*57696d54SAkhilesh Sanikop    } // for
107*57696d54SAkhilesh Sanikop    return numSpaces;
108*57696d54SAkhilesh Sanikop } // GPTDataCurses::MakeSpacesFromParts()
109*57696d54SAkhilesh Sanikop 
110*57696d54SAkhilesh Sanikop // Add a single empty Space to the current Spaces linked list and sort the result....
AddEmptySpace(uint64_t firstLBA,uint64_t lastLBA)111*57696d54SAkhilesh Sanikop void GPTDataCurses::AddEmptySpace(uint64_t firstLBA, uint64_t lastLBA) {
112*57696d54SAkhilesh Sanikop    Space *tempSpace;
113*57696d54SAkhilesh Sanikop 
114*57696d54SAkhilesh Sanikop    tempSpace = new Space;
115*57696d54SAkhilesh Sanikop    tempSpace->firstLBA = firstLBA;
116*57696d54SAkhilesh Sanikop    tempSpace->lastLBA = lastLBA;
117*57696d54SAkhilesh Sanikop    tempSpace->origPart = &emptySpace;
118*57696d54SAkhilesh Sanikop    tempSpace->partNum = -1;
119*57696d54SAkhilesh Sanikop    LinkToEnd(tempSpace);
120*57696d54SAkhilesh Sanikop    SortSpaces();
121*57696d54SAkhilesh Sanikop } // GPTDataCurses::AddEmptySpace();
122*57696d54SAkhilesh Sanikop 
123*57696d54SAkhilesh Sanikop // Add Spaces to represent the unallocated parts of the partition table.
124*57696d54SAkhilesh Sanikop // Returns the number of Spaces added.
AddEmptySpaces(void)125*57696d54SAkhilesh Sanikop int GPTDataCurses::AddEmptySpaces(void) {
126*57696d54SAkhilesh Sanikop    int numAdded = 0;
127*57696d54SAkhilesh Sanikop    Space *current;
128*57696d54SAkhilesh Sanikop 
129*57696d54SAkhilesh Sanikop    SortSpaces();
130*57696d54SAkhilesh Sanikop    if (firstSpace == NULL) {
131*57696d54SAkhilesh Sanikop       AddEmptySpace(GetFirstUsableLBA(), GetLastUsableLBA());
132*57696d54SAkhilesh Sanikop       numAdded++;
133*57696d54SAkhilesh Sanikop    } else {
134*57696d54SAkhilesh Sanikop       current = firstSpace;
135*57696d54SAkhilesh Sanikop       while ((current != NULL) /* && (current->partNum != -1) */ ) {
136*57696d54SAkhilesh Sanikop          if ((current == firstSpace) && (current->firstLBA > GetFirstUsableLBA())) {
137*57696d54SAkhilesh Sanikop             AddEmptySpace(GetFirstUsableLBA(), current->firstLBA - 1);
138*57696d54SAkhilesh Sanikop             numAdded++;
139*57696d54SAkhilesh Sanikop          } // if
140*57696d54SAkhilesh Sanikop          if ((current == lastSpace) && (current->lastLBA < GetLastUsableLBA())) {
141*57696d54SAkhilesh Sanikop             AddEmptySpace(current->lastLBA + 1, GetLastUsableLBA());
142*57696d54SAkhilesh Sanikop             numAdded++;
143*57696d54SAkhilesh Sanikop          } // if
144*57696d54SAkhilesh Sanikop          if ((current->prevSpace != NULL) && (current->prevSpace->lastLBA < (current->firstLBA - 1))) {
145*57696d54SAkhilesh Sanikop             AddEmptySpace(current->prevSpace->lastLBA + 1, current->firstLBA - 1);
146*57696d54SAkhilesh Sanikop             numAdded++;
147*57696d54SAkhilesh Sanikop          } // if
148*57696d54SAkhilesh Sanikop          current = current->nextSpace;
149*57696d54SAkhilesh Sanikop       } // while
150*57696d54SAkhilesh Sanikop    } // if/else
151*57696d54SAkhilesh Sanikop    return numAdded;
152*57696d54SAkhilesh Sanikop } // GPTDataCurses::AddEmptySpaces()
153*57696d54SAkhilesh Sanikop 
154*57696d54SAkhilesh Sanikop // Remove the specified Space from the linked list and set its previous and
155*57696d54SAkhilesh Sanikop // next pointers to NULL.
UnlinkSpace(Space * theSpace)156*57696d54SAkhilesh Sanikop void GPTDataCurses::UnlinkSpace(Space *theSpace) {
157*57696d54SAkhilesh Sanikop    if (theSpace != NULL) {
158*57696d54SAkhilesh Sanikop       if (theSpace->prevSpace != NULL)
159*57696d54SAkhilesh Sanikop          theSpace->prevSpace->nextSpace = theSpace->nextSpace;
160*57696d54SAkhilesh Sanikop       if (theSpace->nextSpace != NULL)
161*57696d54SAkhilesh Sanikop          theSpace->nextSpace->prevSpace = theSpace->prevSpace;
162*57696d54SAkhilesh Sanikop       if (theSpace == firstSpace)
163*57696d54SAkhilesh Sanikop          firstSpace = theSpace->nextSpace;
164*57696d54SAkhilesh Sanikop       if (theSpace == lastSpace)
165*57696d54SAkhilesh Sanikop          lastSpace = theSpace->prevSpace;
166*57696d54SAkhilesh Sanikop       theSpace->nextSpace = NULL;
167*57696d54SAkhilesh Sanikop       theSpace->prevSpace = NULL;
168*57696d54SAkhilesh Sanikop       numSpaces--;
169*57696d54SAkhilesh Sanikop    } // if
170*57696d54SAkhilesh Sanikop } // GPTDataCurses::UnlinkSpace
171*57696d54SAkhilesh Sanikop 
172*57696d54SAkhilesh Sanikop // Link theSpace to the end of the current linked list.
LinkToEnd(Space * theSpace)173*57696d54SAkhilesh Sanikop void GPTDataCurses::LinkToEnd(Space *theSpace) {
174*57696d54SAkhilesh Sanikop    if (lastSpace == NULL) {
175*57696d54SAkhilesh Sanikop       firstSpace = lastSpace = theSpace;
176*57696d54SAkhilesh Sanikop       theSpace->nextSpace = NULL;
177*57696d54SAkhilesh Sanikop       theSpace->prevSpace = NULL;
178*57696d54SAkhilesh Sanikop    } else {
179*57696d54SAkhilesh Sanikop       theSpace->prevSpace = lastSpace;
180*57696d54SAkhilesh Sanikop       theSpace->nextSpace = NULL;
181*57696d54SAkhilesh Sanikop       lastSpace->nextSpace = theSpace;
182*57696d54SAkhilesh Sanikop       lastSpace = theSpace;
183*57696d54SAkhilesh Sanikop    } // if/else
184*57696d54SAkhilesh Sanikop    numSpaces++;
185*57696d54SAkhilesh Sanikop } // GPTDataCurses::LinkToEnd()
186*57696d54SAkhilesh Sanikop 
187*57696d54SAkhilesh Sanikop // Sort spaces into ascending order by on-disk position.
SortSpaces(void)188*57696d54SAkhilesh Sanikop void GPTDataCurses::SortSpaces(void) {
189*57696d54SAkhilesh Sanikop    Space *oldFirst, *oldLast, *earliest = NULL, *current = NULL;
190*57696d54SAkhilesh Sanikop 
191*57696d54SAkhilesh Sanikop    oldFirst = firstSpace;
192*57696d54SAkhilesh Sanikop    oldLast = lastSpace;
193*57696d54SAkhilesh Sanikop    firstSpace = lastSpace = NULL;
194*57696d54SAkhilesh Sanikop    while (oldFirst != NULL) {
195*57696d54SAkhilesh Sanikop       current = earliest = oldFirst;
196*57696d54SAkhilesh Sanikop       while (current != NULL) {
197*57696d54SAkhilesh Sanikop          if (current->firstLBA < earliest->firstLBA)
198*57696d54SAkhilesh Sanikop             earliest = current;
199*57696d54SAkhilesh Sanikop          current = current->nextSpace;
200*57696d54SAkhilesh Sanikop       } // while
201*57696d54SAkhilesh Sanikop       if (oldFirst == earliest)
202*57696d54SAkhilesh Sanikop          oldFirst = earliest->nextSpace;
203*57696d54SAkhilesh Sanikop       if (oldLast == earliest)
204*57696d54SAkhilesh Sanikop          oldLast = earliest->prevSpace;
205*57696d54SAkhilesh Sanikop       UnlinkSpace(earliest);
206*57696d54SAkhilesh Sanikop       LinkToEnd(earliest);
207*57696d54SAkhilesh Sanikop    } // while
208*57696d54SAkhilesh Sanikop } // GPTDataCurses::SortSpaces()
209*57696d54SAkhilesh Sanikop 
210*57696d54SAkhilesh Sanikop // Identify the spaces on the disk, a "space" being defined as a partition
211*57696d54SAkhilesh Sanikop // or an empty gap between, before, or after partitions. The spaces are
212*57696d54SAkhilesh Sanikop // presented to users in the main menu display.
IdentifySpaces(void)213*57696d54SAkhilesh Sanikop void GPTDataCurses::IdentifySpaces(void) {
214*57696d54SAkhilesh Sanikop    MakeSpacesFromParts();
215*57696d54SAkhilesh Sanikop    AddEmptySpaces();
216*57696d54SAkhilesh Sanikop } // GPTDataCurses::IdentifySpaces()
217*57696d54SAkhilesh Sanikop 
218*57696d54SAkhilesh Sanikop /**************************
219*57696d54SAkhilesh Sanikop  *                        *
220*57696d54SAkhilesh Sanikop  * Data display functions *
221*57696d54SAkhilesh Sanikop  *                        *
222*57696d54SAkhilesh Sanikop  **************************/
223*57696d54SAkhilesh Sanikop 
224*57696d54SAkhilesh Sanikop // Display a single Space on line # lineNum.
225*57696d54SAkhilesh Sanikop // Returns a pointer to the space being displayed
ShowSpace(int spaceNum,int lineNum)226*57696d54SAkhilesh Sanikop Space* GPTDataCurses::ShowSpace(int spaceNum, int lineNum) {
227*57696d54SAkhilesh Sanikop    Space *space;
228*57696d54SAkhilesh Sanikop    int i = 0;
229*57696d54SAkhilesh Sanikop #ifdef USE_UTF16
230*57696d54SAkhilesh Sanikop    char temp[40];
231*57696d54SAkhilesh Sanikop #endif
232*57696d54SAkhilesh Sanikop 
233*57696d54SAkhilesh Sanikop    space = firstSpace;
234*57696d54SAkhilesh Sanikop    while ((space != NULL) && (i < spaceNum)) {
235*57696d54SAkhilesh Sanikop       space = space->nextSpace;
236*57696d54SAkhilesh Sanikop       i++;
237*57696d54SAkhilesh Sanikop    } // while
238*57696d54SAkhilesh Sanikop    if ((space != NULL) && (lineNum < (LINES - 5))) {
239*57696d54SAkhilesh Sanikop       ClearLine(lineNum);
240*57696d54SAkhilesh Sanikop       if (space->partNum == -1) { // space is empty
241*57696d54SAkhilesh Sanikop          move(lineNum, 12);
242*57696d54SAkhilesh Sanikop          printw("%s", BytesToIeee((space->lastLBA - space->firstLBA + 1), blockSize).c_str());
243*57696d54SAkhilesh Sanikop          move(lineNum, 24);
244*57696d54SAkhilesh Sanikop          printw("free space");
245*57696d54SAkhilesh Sanikop       } else { // space holds a partition
246*57696d54SAkhilesh Sanikop          move(lineNum, 3);
247*57696d54SAkhilesh Sanikop          printw("%d", space->partNum + 1);
248*57696d54SAkhilesh Sanikop          move(lineNum, 12);
249*57696d54SAkhilesh Sanikop          printw("%s", BytesToIeee((space->lastLBA - space->firstLBA + 1), blockSize).c_str());
250*57696d54SAkhilesh Sanikop          move(lineNum, 24);
251*57696d54SAkhilesh Sanikop          printw("%s", space->origPart->GetTypeName().c_str());
252*57696d54SAkhilesh Sanikop          move(lineNum, 50);
253*57696d54SAkhilesh Sanikop          #ifdef USE_UTF16
254*57696d54SAkhilesh Sanikop          space->origPart->GetDescription().extract(0, 39, temp, 39);
255*57696d54SAkhilesh Sanikop          printw(temp);
256*57696d54SAkhilesh Sanikop          #else
257*57696d54SAkhilesh Sanikop          printw("%s", space->origPart->GetDescription().c_str());
258*57696d54SAkhilesh Sanikop          #endif
259*57696d54SAkhilesh Sanikop       } // if/else
260*57696d54SAkhilesh Sanikop    } // if
261*57696d54SAkhilesh Sanikop    return space;
262*57696d54SAkhilesh Sanikop } // GPTDataCurses::ShowSpace
263*57696d54SAkhilesh Sanikop 
264*57696d54SAkhilesh Sanikop // Display the partitions, being sure that the space #selected is displayed
265*57696d54SAkhilesh Sanikop // and highlighting that space.
266*57696d54SAkhilesh Sanikop // Returns the number of the space being shown (should be selected, but will
267*57696d54SAkhilesh Sanikop // be -1 if something weird happens)
DisplayParts(int selected)268*57696d54SAkhilesh Sanikop int GPTDataCurses::DisplayParts(int selected) {
269*57696d54SAkhilesh Sanikop    int lineNum = 5, i = 0, retval = -1, numToShow, pageNum;
270*57696d54SAkhilesh Sanikop    string theLine;
271*57696d54SAkhilesh Sanikop 
272*57696d54SAkhilesh Sanikop    move(lineNum++, 0);
273*57696d54SAkhilesh Sanikop    theLine = "Part. #     Size        Partition Type            Partition Name";
274*57696d54SAkhilesh Sanikop    printw("%s", theLine.c_str());
275*57696d54SAkhilesh Sanikop    move(lineNum++, 0);
276*57696d54SAkhilesh Sanikop    theLine = "----------------------------------------------------------------";
277*57696d54SAkhilesh Sanikop    printw("%s", theLine.c_str());
278*57696d54SAkhilesh Sanikop    numToShow = LINES - RESERVED_TOP - RESERVED_BOTTOM;
279*57696d54SAkhilesh Sanikop    pageNum = selected / numToShow;
280*57696d54SAkhilesh Sanikop    for (i = pageNum * numToShow; i <= (pageNum + 1) * numToShow - 1; i++) {
281*57696d54SAkhilesh Sanikop       if (i < numSpaces) { // real space; show it
282*57696d54SAkhilesh Sanikop          if (i == selected) {
283*57696d54SAkhilesh Sanikop             currentSpaceNum = i;
284*57696d54SAkhilesh Sanikop             if (displayType == USE_CURSES) {
285*57696d54SAkhilesh Sanikop                attron(A_REVERSE);
286*57696d54SAkhilesh Sanikop                currentSpace = ShowSpace(i, lineNum++);
287*57696d54SAkhilesh Sanikop                attroff(A_REVERSE);
288*57696d54SAkhilesh Sanikop             } else {
289*57696d54SAkhilesh Sanikop                currentSpace = ShowSpace(i, lineNum);
290*57696d54SAkhilesh Sanikop                move(lineNum++, 0);
291*57696d54SAkhilesh Sanikop                printw(">");
292*57696d54SAkhilesh Sanikop             }
293*57696d54SAkhilesh Sanikop             DisplayOptions(i);
294*57696d54SAkhilesh Sanikop             retval = selected;
295*57696d54SAkhilesh Sanikop          } else {
296*57696d54SAkhilesh Sanikop             ShowSpace(i, lineNum++);
297*57696d54SAkhilesh Sanikop          }
298*57696d54SAkhilesh Sanikop       } else { // blank in display
299*57696d54SAkhilesh Sanikop          ClearLine(lineNum++);
300*57696d54SAkhilesh Sanikop       } // if/else
301*57696d54SAkhilesh Sanikop    } // for
302*57696d54SAkhilesh Sanikop    refresh();
303*57696d54SAkhilesh Sanikop    return retval;
304*57696d54SAkhilesh Sanikop } // GPTDataCurses::DisplayParts()
305*57696d54SAkhilesh Sanikop 
306*57696d54SAkhilesh Sanikop /**********************************************
307*57696d54SAkhilesh Sanikop  *                                            *
308*57696d54SAkhilesh Sanikop  * Functions corresponding to main menu items *
309*57696d54SAkhilesh Sanikop  *                                            *
310*57696d54SAkhilesh Sanikop  **********************************************/
311*57696d54SAkhilesh Sanikop 
312*57696d54SAkhilesh Sanikop // Delete the specified partition and re-detect partitions and spaces....
DeletePartition(int partNum)313*57696d54SAkhilesh Sanikop void GPTDataCurses::DeletePartition(int partNum) {
314*57696d54SAkhilesh Sanikop    if (!GPTData::DeletePartition(partNum))
315*57696d54SAkhilesh Sanikop       Report("Could not delete partition!");
316*57696d54SAkhilesh Sanikop    IdentifySpaces();
317*57696d54SAkhilesh Sanikop    if (currentSpaceNum >= numSpaces) {
318*57696d54SAkhilesh Sanikop       currentSpaceNum = numSpaces - 1;
319*57696d54SAkhilesh Sanikop       currentSpace = lastSpace;
320*57696d54SAkhilesh Sanikop    } // if
321*57696d54SAkhilesh Sanikop } // GPTDataCurses::DeletePartition()
322*57696d54SAkhilesh Sanikop 
323*57696d54SAkhilesh Sanikop // Displays information on the specified partition
ShowInfo(int partNum)324*57696d54SAkhilesh Sanikop void GPTDataCurses::ShowInfo(int partNum) {
325*57696d54SAkhilesh Sanikop    uint64_t size;
326*57696d54SAkhilesh Sanikop #ifdef USE_UTF16
327*57696d54SAkhilesh Sanikop    char temp[NAME_SIZE + 1];
328*57696d54SAkhilesh Sanikop #endif
329*57696d54SAkhilesh Sanikop 
330*57696d54SAkhilesh Sanikop    clear();
331*57696d54SAkhilesh Sanikop    move(2, (COLS - 29) / 2);
332*57696d54SAkhilesh Sanikop    printw("Information for partition #%d\n\n", partNum + 1);
333*57696d54SAkhilesh Sanikop    printw("Partition GUID code: %s (%s)\n", partitions[partNum].GetType().AsString().c_str(),
334*57696d54SAkhilesh Sanikop           partitions[partNum].GetTypeName().c_str());
335*57696d54SAkhilesh Sanikop    printw("Partition unique GUID: %s\n", partitions[partNum].GetUniqueGUID().AsString().c_str());
336*57696d54SAkhilesh Sanikop    printw("First sector: %llu (at %s)\n", (long long unsigned int) partitions[partNum].GetFirstLBA(),
337*57696d54SAkhilesh Sanikop           BytesToIeee(partitions[partNum].GetFirstLBA(), blockSize).c_str());
338*57696d54SAkhilesh Sanikop    printw("Last sector: %llu (at %s)\n", (long long unsigned int) partitions[partNum].GetLastLBA(),
339*57696d54SAkhilesh Sanikop           BytesToIeee(partitions[partNum].GetLastLBA(), blockSize).c_str());
340*57696d54SAkhilesh Sanikop    size = partitions[partNum].GetLastLBA() - partitions[partNum].GetFirstLBA() + 1;
341*57696d54SAkhilesh Sanikop    printw("Partition size: %llu sectors (%s)\n", (long long unsigned int) size, BytesToIeee(size, blockSize).c_str());
342*57696d54SAkhilesh Sanikop    printw("Attribute flags: %016llx\n", (long long unsigned int) partitions[partNum].GetAttributes().GetAttributes());
343*57696d54SAkhilesh Sanikop    #ifdef USE_UTF16
344*57696d54SAkhilesh Sanikop    partitions[partNum].GetDescription().extract(0, NAME_SIZE , temp, NAME_SIZE );
345*57696d54SAkhilesh Sanikop    printw("Partition name: '%s'\n", temp);
346*57696d54SAkhilesh Sanikop    #else
347*57696d54SAkhilesh Sanikop    printw("Partition name: '%s'\n", partitions[partNum].GetDescription().c_str());
348*57696d54SAkhilesh Sanikop    #endif
349*57696d54SAkhilesh Sanikop    PromptToContinue();
350*57696d54SAkhilesh Sanikop } // GPTDataCurses::ShowInfo()
351*57696d54SAkhilesh Sanikop 
352*57696d54SAkhilesh Sanikop // Prompt for and change a partition's name....
ChangeName(int partNum)353*57696d54SAkhilesh Sanikop void GPTDataCurses::ChangeName(int partNum) {
354*57696d54SAkhilesh Sanikop    char temp[NAME_SIZE + 1];
355*57696d54SAkhilesh Sanikop 
356*57696d54SAkhilesh Sanikop    if (ValidPartNum(partNum)) {
357*57696d54SAkhilesh Sanikop       move(LINES - 4, 0);
358*57696d54SAkhilesh Sanikop       clrtobot();
359*57696d54SAkhilesh Sanikop       move(LINES - 4, 0);
360*57696d54SAkhilesh Sanikop       #ifdef USE_UTF16
361*57696d54SAkhilesh Sanikop       partitions[partNum].GetDescription().extract(0, NAME_SIZE , temp, NAME_SIZE );
362*57696d54SAkhilesh Sanikop       printw("Current partition name is '%s'\n", temp);
363*57696d54SAkhilesh Sanikop       #else
364*57696d54SAkhilesh Sanikop       printw("Current partition name is '%s'\n", partitions[partNum].GetDescription().c_str());
365*57696d54SAkhilesh Sanikop       #endif
366*57696d54SAkhilesh Sanikop       printw("Enter new partition name, or <Enter> to use the current name:\n");
367*57696d54SAkhilesh Sanikop       echo();
368*57696d54SAkhilesh Sanikop       getnstr(temp, NAME_SIZE );
369*57696d54SAkhilesh Sanikop       partitions[partNum].SetName((string) temp);
370*57696d54SAkhilesh Sanikop       noecho();
371*57696d54SAkhilesh Sanikop    } // if
372*57696d54SAkhilesh Sanikop } // GPTDataCurses::ChangeName()
373*57696d54SAkhilesh Sanikop 
374*57696d54SAkhilesh Sanikop // Change the partition's type code....
ChangeType(int partNum)375*57696d54SAkhilesh Sanikop void GPTDataCurses::ChangeType(int partNum) {
376*57696d54SAkhilesh Sanikop    char temp[80] = "L\0";
377*57696d54SAkhilesh Sanikop    PartType tempType;
378*57696d54SAkhilesh Sanikop 
379*57696d54SAkhilesh Sanikop    echo();
380*57696d54SAkhilesh Sanikop    do {
381*57696d54SAkhilesh Sanikop       move(LINES - 4, 0);
382*57696d54SAkhilesh Sanikop       clrtobot();
383*57696d54SAkhilesh Sanikop       move(LINES - 4, 0);
384*57696d54SAkhilesh Sanikop       printw("Current type is %04x (%s)\n", partitions[partNum].GetType().GetHexType(), partitions[partNum].GetTypeName().c_str());
385*57696d54SAkhilesh Sanikop       printw("Hex code or GUID (L to show codes, Enter = %04x): ", partitions[partNum].GetType().GetHexType());
386*57696d54SAkhilesh Sanikop       getnstr(temp, 79);
387*57696d54SAkhilesh Sanikop       if ((temp[0] == 'L') || (temp[0] == 'l')) {
388*57696d54SAkhilesh Sanikop          ShowTypes();
389*57696d54SAkhilesh Sanikop       } else {
390*57696d54SAkhilesh Sanikop          if (temp[0] == '\0')
391*57696d54SAkhilesh Sanikop             tempType = partitions[partNum].GetType().GetHexType();
392*57696d54SAkhilesh Sanikop          tempType = temp;
393*57696d54SAkhilesh Sanikop          partitions[partNum].SetType(tempType);
394*57696d54SAkhilesh Sanikop       } // if
395*57696d54SAkhilesh Sanikop    } while ((temp[0] == 'L') || (temp[0] == 'l') || (partitions[partNum].GetType() == (GUIDData) "0x0000"));
396*57696d54SAkhilesh Sanikop    noecho();
397*57696d54SAkhilesh Sanikop } // GPTDataCurses::ChangeType
398*57696d54SAkhilesh Sanikop 
399*57696d54SAkhilesh Sanikop // Sets the partition alignment value
SetAlignment(void)400*57696d54SAkhilesh Sanikop void GPTDataCurses::SetAlignment(void) {
401*57696d54SAkhilesh Sanikop    int alignment;
402*57696d54SAkhilesh Sanikop    char conversion_specifier[] = "%d";
403*57696d54SAkhilesh Sanikop 
404*57696d54SAkhilesh Sanikop    move(LINES - 4, 0);
405*57696d54SAkhilesh Sanikop    clrtobot();
406*57696d54SAkhilesh Sanikop    printw("Current partition alignment, in sectors, is %d.", GetAlignment());
407*57696d54SAkhilesh Sanikop    do {
408*57696d54SAkhilesh Sanikop       move(LINES - 3, 0);
409*57696d54SAkhilesh Sanikop       printw("Type new alignment value, in sectors: ");
410*57696d54SAkhilesh Sanikop       echo();
411*57696d54SAkhilesh Sanikop       scanw(conversion_specifier, &alignment);
412*57696d54SAkhilesh Sanikop       noecho();
413*57696d54SAkhilesh Sanikop    } while ((alignment == 0) || (alignment > MAX_ALIGNMENT));
414*57696d54SAkhilesh Sanikop    GPTData::SetAlignment(alignment);
415*57696d54SAkhilesh Sanikop } // GPTDataCurses::SetAlignment()
416*57696d54SAkhilesh Sanikop 
417*57696d54SAkhilesh Sanikop // Verify the data structures. Note that this function leaves curses mode and
418*57696d54SAkhilesh Sanikop // relies on the underlying GPTData::Verify() function to report on problems
Verify(void)419*57696d54SAkhilesh Sanikop void GPTDataCurses::Verify(void) {
420*57696d54SAkhilesh Sanikop    char junk;
421*57696d54SAkhilesh Sanikop 
422*57696d54SAkhilesh Sanikop    def_prog_mode();
423*57696d54SAkhilesh Sanikop    endwin();
424*57696d54SAkhilesh Sanikop    GPTData::Verify();
425*57696d54SAkhilesh Sanikop    cout << "\nPress the <Enter> key to continue: ";
426*57696d54SAkhilesh Sanikop    cin.get(junk);
427*57696d54SAkhilesh Sanikop    reset_prog_mode();
428*57696d54SAkhilesh Sanikop    refresh();
429*57696d54SAkhilesh Sanikop } // GPTDataCurses::Verify()
430*57696d54SAkhilesh Sanikop 
431*57696d54SAkhilesh Sanikop // Create a new partition in the space pointed to by currentSpace.
MakeNewPart(void)432*57696d54SAkhilesh Sanikop void GPTDataCurses::MakeNewPart(void) {
433*57696d54SAkhilesh Sanikop    uint64_t size, newFirstLBA = 0, newLastLBA = 0, lastAligned;
434*57696d54SAkhilesh Sanikop    int partNum;
435*57696d54SAkhilesh Sanikop    char inLine[80];
436*57696d54SAkhilesh Sanikop 
437*57696d54SAkhilesh Sanikop    move(LINES - 4, 0);
438*57696d54SAkhilesh Sanikop    clrtobot();
439*57696d54SAkhilesh Sanikop    lastAligned = currentSpace->lastLBA + 1;
440*57696d54SAkhilesh Sanikop    Align(&lastAligned);
441*57696d54SAkhilesh Sanikop    lastAligned--;
442*57696d54SAkhilesh Sanikop    // Discard end-alignment attempt if it's giving us an invalid end point....
443*57696d54SAkhilesh Sanikop    if (!IsFree(lastAligned))
444*57696d54SAkhilesh Sanikop        lastAligned = currentSpace->lastLBA;
445*57696d54SAkhilesh Sanikop    while ((newFirstLBA < currentSpace->firstLBA) || (newFirstLBA > currentSpace->lastLBA)) {
446*57696d54SAkhilesh Sanikop       move(LINES - 4, 0);
447*57696d54SAkhilesh Sanikop       clrtoeol();
448*57696d54SAkhilesh Sanikop       newFirstLBA = currentSpace->firstLBA;
449*57696d54SAkhilesh Sanikop       Align(&newFirstLBA);
450*57696d54SAkhilesh Sanikop       printw("First sector (%llu-%llu, default = %llu): ", (long long unsigned int) newFirstLBA,
451*57696d54SAkhilesh Sanikop              (long long unsigned int) currentSpace->lastLBA, (long long unsigned int) newFirstLBA);
452*57696d54SAkhilesh Sanikop       echo();
453*57696d54SAkhilesh Sanikop       getnstr(inLine, 79);
454*57696d54SAkhilesh Sanikop       noecho();
455*57696d54SAkhilesh Sanikop       newFirstLBA = IeeeToInt(inLine, blockSize, currentSpace->firstLBA, currentSpace->lastLBA, sectorAlignment, newFirstLBA);
456*57696d54SAkhilesh Sanikop       Align(&newFirstLBA);
457*57696d54SAkhilesh Sanikop    } // while
458*57696d54SAkhilesh Sanikop    if (newFirstLBA > lastAligned)
459*57696d54SAkhilesh Sanikop       size = currentSpace->lastLBA - newFirstLBA + 1;
460*57696d54SAkhilesh Sanikop    else
461*57696d54SAkhilesh Sanikop       size = lastAligned - newFirstLBA + 1;
462*57696d54SAkhilesh Sanikop    while ((newLastLBA > currentSpace->lastLBA) || (newLastLBA < newFirstLBA)) {
463*57696d54SAkhilesh Sanikop       move(LINES - 3, 0);
464*57696d54SAkhilesh Sanikop       clrtoeol();
465*57696d54SAkhilesh Sanikop       printw("Size in sectors or {KMGTP} (default = %llu): ", (long long unsigned int) size);
466*57696d54SAkhilesh Sanikop       echo();
467*57696d54SAkhilesh Sanikop       getnstr(inLine, 79);
468*57696d54SAkhilesh Sanikop       noecho();
469*57696d54SAkhilesh Sanikop       newLastLBA = newFirstLBA + IeeeToInt(inLine, blockSize, 1, size, sectorAlignment, size) - 1;
470*57696d54SAkhilesh Sanikop    } // while
471*57696d54SAkhilesh Sanikop    partNum = FindFirstFreePart();
472*57696d54SAkhilesh Sanikop    if (CreatePartition(partNum, newFirstLBA, newLastLBA)) { // created OK; set type code & name....
473*57696d54SAkhilesh Sanikop       ChangeType(partNum);
474*57696d54SAkhilesh Sanikop       ChangeName(partNum);
475*57696d54SAkhilesh Sanikop    } else {
476*57696d54SAkhilesh Sanikop       Report("Error creating partition!");
477*57696d54SAkhilesh Sanikop    } // if/else
478*57696d54SAkhilesh Sanikop } // GPTDataCurses::MakeNewPart()
479*57696d54SAkhilesh Sanikop 
480*57696d54SAkhilesh Sanikop // Prompt user for permission to save data and, if it's given, do so!
SaveData(void)481*57696d54SAkhilesh Sanikop void GPTDataCurses::SaveData(void) {
482*57696d54SAkhilesh Sanikop    string answer = "";
483*57696d54SAkhilesh Sanikop    char inLine[80];
484*57696d54SAkhilesh Sanikop 
485*57696d54SAkhilesh Sanikop    move(LINES - 4, 0);
486*57696d54SAkhilesh Sanikop    clrtobot();
487*57696d54SAkhilesh Sanikop    move (LINES - 2, 14);
488*57696d54SAkhilesh Sanikop    printw("Warning!! This may destroy data on your disk!");
489*57696d54SAkhilesh Sanikop    echo();
490*57696d54SAkhilesh Sanikop    while ((answer != "yes") && (answer != "no")) {
491*57696d54SAkhilesh Sanikop       move (LINES - 4, 2);
492*57696d54SAkhilesh Sanikop       printw("Are you sure you want to write the partition table to disk? (yes or no): ");
493*57696d54SAkhilesh Sanikop       getnstr(inLine, 79);
494*57696d54SAkhilesh Sanikop       answer = inLine;
495*57696d54SAkhilesh Sanikop       if ((answer != "yes") && (answer != "no")) {
496*57696d54SAkhilesh Sanikop          move(LINES - 2, 0);
497*57696d54SAkhilesh Sanikop          clrtoeol();
498*57696d54SAkhilesh Sanikop          move(LINES - 2, 14);
499*57696d54SAkhilesh Sanikop          printw("Please enter 'yes' or 'no'");
500*57696d54SAkhilesh Sanikop       } // if
501*57696d54SAkhilesh Sanikop    } // while()
502*57696d54SAkhilesh Sanikop    noecho();
503*57696d54SAkhilesh Sanikop    if (answer == "yes") {
504*57696d54SAkhilesh Sanikop       if (SaveGPTData(1)) {
505*57696d54SAkhilesh Sanikop          if (!myDisk.DiskSync())
506*57696d54SAkhilesh Sanikop             Report("The kernel may be using the old partition table. Reboot to use the new\npartition table!");
507*57696d54SAkhilesh Sanikop       } else {
508*57696d54SAkhilesh Sanikop          Report("Problem saving data! Your partition table may be damaged!");
509*57696d54SAkhilesh Sanikop       }
510*57696d54SAkhilesh Sanikop    }
511*57696d54SAkhilesh Sanikop } // GPTDataCurses::SaveData()
512*57696d54SAkhilesh Sanikop 
513*57696d54SAkhilesh Sanikop // Back up the partition table, prompting user for a filename....
Backup(void)514*57696d54SAkhilesh Sanikop void GPTDataCurses::Backup(void) {
515*57696d54SAkhilesh Sanikop    char inLine[80];
516*57696d54SAkhilesh Sanikop 
517*57696d54SAkhilesh Sanikop    ClearBottom();
518*57696d54SAkhilesh Sanikop    move(LINES - 3, 0);
519*57696d54SAkhilesh Sanikop    printw("Enter backup filename to save: ");
520*57696d54SAkhilesh Sanikop    echo();
521*57696d54SAkhilesh Sanikop    getnstr(inLine, 79);
522*57696d54SAkhilesh Sanikop    noecho();
523*57696d54SAkhilesh Sanikop    SaveGPTBackup(inLine);
524*57696d54SAkhilesh Sanikop } // GPTDataCurses::Backup()
525*57696d54SAkhilesh Sanikop 
526*57696d54SAkhilesh Sanikop // Load a GPT backup from a file
LoadBackup(void)527*57696d54SAkhilesh Sanikop void GPTDataCurses::LoadBackup(void) {
528*57696d54SAkhilesh Sanikop    char inLine[80];
529*57696d54SAkhilesh Sanikop 
530*57696d54SAkhilesh Sanikop    ClearBottom();
531*57696d54SAkhilesh Sanikop    move(LINES - 3, 0);
532*57696d54SAkhilesh Sanikop    printw("Enter backup filename to load: ");
533*57696d54SAkhilesh Sanikop    echo();
534*57696d54SAkhilesh Sanikop    getnstr(inLine, 79);
535*57696d54SAkhilesh Sanikop    noecho();
536*57696d54SAkhilesh Sanikop    if (!LoadGPTBackup(inLine))
537*57696d54SAkhilesh Sanikop       Report("Restoration failed!");
538*57696d54SAkhilesh Sanikop    IdentifySpaces();
539*57696d54SAkhilesh Sanikop } // GPTDataCurses::LoadBackup()
540*57696d54SAkhilesh Sanikop 
541*57696d54SAkhilesh Sanikop // Display some basic help information
ShowHelp(void)542*57696d54SAkhilesh Sanikop void GPTDataCurses::ShowHelp(void) {
543*57696d54SAkhilesh Sanikop    int i = 0;
544*57696d54SAkhilesh Sanikop 
545*57696d54SAkhilesh Sanikop    clear();
546*57696d54SAkhilesh Sanikop    move(0, (COLS - 22) / 2);
547*57696d54SAkhilesh Sanikop    printw("Help screen for cgdisk");
548*57696d54SAkhilesh Sanikop    move(2, 0);
549*57696d54SAkhilesh Sanikop    printw("This is cgdisk, a curses-based disk partitioning program. You can use it\n");
550*57696d54SAkhilesh Sanikop    printw("to create, delete, and modify partitions on your hard disk.\n\n");
551*57696d54SAkhilesh Sanikop    attron(A_BOLD);
552*57696d54SAkhilesh Sanikop    printw("Use cgdisk only on GUID Partition Table (GPT) disks!\n");
553*57696d54SAkhilesh Sanikop    attroff(A_BOLD);
554*57696d54SAkhilesh Sanikop    printw("Use cfdisk on Master Boot Record (MBR) disks.\n\n");
555*57696d54SAkhilesh Sanikop    printw("Command      Meaning\n");
556*57696d54SAkhilesh Sanikop    printw("-------      -------\n");
557*57696d54SAkhilesh Sanikop    while (menuMain[i].key != 0) {
558*57696d54SAkhilesh Sanikop       printw("   %c         %s\n", menuMain[i].key, menuMain[i].desc.c_str());
559*57696d54SAkhilesh Sanikop       i++;
560*57696d54SAkhilesh Sanikop    } // while()
561*57696d54SAkhilesh Sanikop    PromptToContinue();
562*57696d54SAkhilesh Sanikop } // GPTDataCurses::ShowHelp()
563*57696d54SAkhilesh Sanikop 
564*57696d54SAkhilesh Sanikop /************************************
565*57696d54SAkhilesh Sanikop  *                                  *
566*57696d54SAkhilesh Sanikop  * User input and menuing functions *
567*57696d54SAkhilesh Sanikop  *                                  *
568*57696d54SAkhilesh Sanikop  ************************************/
569*57696d54SAkhilesh Sanikop 
570*57696d54SAkhilesh Sanikop // Change the currently-selected space....
ChangeSpaceSelection(int delta)571*57696d54SAkhilesh Sanikop void GPTDataCurses::ChangeSpaceSelection(int delta) {
572*57696d54SAkhilesh Sanikop    if (currentSpace != NULL) {
573*57696d54SAkhilesh Sanikop       while ((delta > 0) && (currentSpace->nextSpace != NULL)) {
574*57696d54SAkhilesh Sanikop          currentSpace = currentSpace->nextSpace;
575*57696d54SAkhilesh Sanikop          delta--;
576*57696d54SAkhilesh Sanikop          currentSpaceNum++;
577*57696d54SAkhilesh Sanikop       } // while
578*57696d54SAkhilesh Sanikop       while ((delta < 0) && (currentSpace->prevSpace != NULL)) {
579*57696d54SAkhilesh Sanikop          currentSpace = currentSpace->prevSpace;
580*57696d54SAkhilesh Sanikop          delta++;
581*57696d54SAkhilesh Sanikop          currentSpaceNum--;
582*57696d54SAkhilesh Sanikop       } // while
583*57696d54SAkhilesh Sanikop    } // if
584*57696d54SAkhilesh Sanikop    // Below will hopefully never be true; bad counting error (bug), so reset to
585*57696d54SAkhilesh Sanikop    // the first Space as a failsafe....
586*57696d54SAkhilesh Sanikop    if (DisplayParts(currentSpaceNum) != currentSpaceNum) {
587*57696d54SAkhilesh Sanikop       currentSpaceNum = 0;
588*57696d54SAkhilesh Sanikop       currentSpace = firstSpace;
589*57696d54SAkhilesh Sanikop       DisplayParts(currentSpaceNum);
590*57696d54SAkhilesh Sanikop    } // if
591*57696d54SAkhilesh Sanikop } // GPTDataCurses
592*57696d54SAkhilesh Sanikop 
593*57696d54SAkhilesh Sanikop // Move option selection left or right....
MoveSelection(int delta)594*57696d54SAkhilesh Sanikop void GPTDataCurses::MoveSelection(int delta) {
595*57696d54SAkhilesh Sanikop    int newKeyNum;
596*57696d54SAkhilesh Sanikop 
597*57696d54SAkhilesh Sanikop    // Begin with a sanity check to ensure a valid key is selected....
598*57696d54SAkhilesh Sanikop    if (whichOptions.find(currentKey) == string::npos)
599*57696d54SAkhilesh Sanikop       currentKey = 'n';
600*57696d54SAkhilesh Sanikop    newKeyNum = whichOptions.find(currentKey);
601*57696d54SAkhilesh Sanikop    newKeyNum += delta;
602*57696d54SAkhilesh Sanikop    if (newKeyNum < 0)
603*57696d54SAkhilesh Sanikop       newKeyNum = whichOptions.length() - 1;
604*57696d54SAkhilesh Sanikop    newKeyNum %= whichOptions.length();
605*57696d54SAkhilesh Sanikop    currentKey = whichOptions[newKeyNum];
606*57696d54SAkhilesh Sanikop    DisplayOptions(currentKey);
607*57696d54SAkhilesh Sanikop } // GPTDataCurses::MoveSelection()
608*57696d54SAkhilesh Sanikop 
609*57696d54SAkhilesh Sanikop // Show user's options. Refers to currentSpace to determine which options to show.
610*57696d54SAkhilesh Sanikop // Highlights the option with the key selectedKey; or a default if that's invalid.
DisplayOptions(char selectedKey)611*57696d54SAkhilesh Sanikop void GPTDataCurses::DisplayOptions(char selectedKey) {
612*57696d54SAkhilesh Sanikop    uint64_t i, j = 0, firstLine, numPerLine;
613*57696d54SAkhilesh Sanikop    string optionName, optionDesc = "";
614*57696d54SAkhilesh Sanikop 
615*57696d54SAkhilesh Sanikop    if (currentSpace != NULL) {
616*57696d54SAkhilesh Sanikop       if (currentSpace->partNum == -1) { // empty space is selected
617*57696d54SAkhilesh Sanikop          whichOptions = EMPTY_SPACE_OPTIONS;
618*57696d54SAkhilesh Sanikop          if (whichOptions.find(selectedKey) == string::npos)
619*57696d54SAkhilesh Sanikop             selectedKey = 'n';
620*57696d54SAkhilesh Sanikop       } else { // a partition is selected
621*57696d54SAkhilesh Sanikop          whichOptions = PARTITION_OPTIONS;
622*57696d54SAkhilesh Sanikop          if (whichOptions.find(selectedKey) == string::npos)
623*57696d54SAkhilesh Sanikop             selectedKey = 't';
624*57696d54SAkhilesh Sanikop       } // if/else
625*57696d54SAkhilesh Sanikop 
626*57696d54SAkhilesh Sanikop       firstLine = LINES - 4;
627*57696d54SAkhilesh Sanikop       numPerLine = (COLS - 8) / 12;
628*57696d54SAkhilesh Sanikop       ClearBottom();
629*57696d54SAkhilesh Sanikop       move(firstLine, 0);
630*57696d54SAkhilesh Sanikop       for (i = 0; i < whichOptions.length(); i++) {
631*57696d54SAkhilesh Sanikop          optionName = "";
632*57696d54SAkhilesh Sanikop          for (j = 0; menuMain[j].key; j++) {
633*57696d54SAkhilesh Sanikop             if (menuMain[j].key == whichOptions[i]) {
634*57696d54SAkhilesh Sanikop                optionName = menuMain[j].name;
635*57696d54SAkhilesh Sanikop                if (whichOptions[i] == selectedKey)
636*57696d54SAkhilesh Sanikop                   optionDesc = menuMain[j].desc;
637*57696d54SAkhilesh Sanikop             } // if
638*57696d54SAkhilesh Sanikop          } // for
639*57696d54SAkhilesh Sanikop          move(firstLine + i / numPerLine, (i % numPerLine) * 12 + 4);
640*57696d54SAkhilesh Sanikop          if (whichOptions[i] == selectedKey) {
641*57696d54SAkhilesh Sanikop             attron(A_REVERSE);
642*57696d54SAkhilesh Sanikop             printw("[ %s ]", optionName.c_str());
643*57696d54SAkhilesh Sanikop             attroff(A_REVERSE);
644*57696d54SAkhilesh Sanikop          } else {
645*57696d54SAkhilesh Sanikop             printw("[ %s ]", optionName.c_str());
646*57696d54SAkhilesh Sanikop          } // if/else
647*57696d54SAkhilesh Sanikop       } // for
648*57696d54SAkhilesh Sanikop       move(LINES - 1, (COLS - optionDesc.length()) / 2);
649*57696d54SAkhilesh Sanikop       printw("%s", optionDesc.c_str());
650*57696d54SAkhilesh Sanikop       currentKey = selectedKey;
651*57696d54SAkhilesh Sanikop    } // if
652*57696d54SAkhilesh Sanikop } // GPTDataCurses::DisplayOptions()
653*57696d54SAkhilesh Sanikop 
654*57696d54SAkhilesh Sanikop // Accept user input and process it. Returns when the program should terminate.
AcceptInput()655*57696d54SAkhilesh Sanikop void GPTDataCurses::AcceptInput() {
656*57696d54SAkhilesh Sanikop    int inputKey, exitNow = 0;
657*57696d54SAkhilesh Sanikop 
658*57696d54SAkhilesh Sanikop    do {
659*57696d54SAkhilesh Sanikop       refresh();
660*57696d54SAkhilesh Sanikop       inputKey = getch();
661*57696d54SAkhilesh Sanikop       switch (inputKey) {
662*57696d54SAkhilesh Sanikop          case KEY_UP:
663*57696d54SAkhilesh Sanikop             ChangeSpaceSelection(-1);
664*57696d54SAkhilesh Sanikop             break;
665*57696d54SAkhilesh Sanikop          case KEY_DOWN:
666*57696d54SAkhilesh Sanikop             ChangeSpaceSelection(+1);
667*57696d54SAkhilesh Sanikop             break;
668*57696d54SAkhilesh Sanikop          case 339: // page up key
669*57696d54SAkhilesh Sanikop             ChangeSpaceSelection(RESERVED_TOP + RESERVED_BOTTOM - LINES);
670*57696d54SAkhilesh Sanikop             break;
671*57696d54SAkhilesh Sanikop          case 338: // page down key
672*57696d54SAkhilesh Sanikop             ChangeSpaceSelection(LINES - RESERVED_TOP - RESERVED_BOTTOM);
673*57696d54SAkhilesh Sanikop             break;
674*57696d54SAkhilesh Sanikop          case KEY_LEFT:
675*57696d54SAkhilesh Sanikop             MoveSelection(-1);
676*57696d54SAkhilesh Sanikop             break;
677*57696d54SAkhilesh Sanikop          case KEY_RIGHT:
678*57696d54SAkhilesh Sanikop             MoveSelection(+1);
679*57696d54SAkhilesh Sanikop             break;
680*57696d54SAkhilesh Sanikop          case KEY_ENTER: case 13:
681*57696d54SAkhilesh Sanikop             exitNow = Dispatch(currentKey);
682*57696d54SAkhilesh Sanikop             break;
683*57696d54SAkhilesh Sanikop          case 27: // escape key
684*57696d54SAkhilesh Sanikop             exitNow = 1;
685*57696d54SAkhilesh Sanikop             break;
686*57696d54SAkhilesh Sanikop          default:
687*57696d54SAkhilesh Sanikop             exitNow = Dispatch(inputKey);
688*57696d54SAkhilesh Sanikop             break;
689*57696d54SAkhilesh Sanikop       } // switch()
690*57696d54SAkhilesh Sanikop    } while (!exitNow);
691*57696d54SAkhilesh Sanikop } // GPTDataCurses::AcceptInput()
692*57696d54SAkhilesh Sanikop 
693*57696d54SAkhilesh Sanikop // Operation has been selected, so do it. Returns 1 if the program should
694*57696d54SAkhilesh Sanikop // terminate on return from this program, 0 otherwise.
Dispatch(char operation)695*57696d54SAkhilesh Sanikop int GPTDataCurses::Dispatch(char operation) {
696*57696d54SAkhilesh Sanikop    int exitNow = 0;
697*57696d54SAkhilesh Sanikop 
698*57696d54SAkhilesh Sanikop    switch (operation) {
699*57696d54SAkhilesh Sanikop       case 'a': case 'A':
700*57696d54SAkhilesh Sanikop          SetAlignment();
701*57696d54SAkhilesh Sanikop          break;
702*57696d54SAkhilesh Sanikop       case 'b': case 'B':
703*57696d54SAkhilesh Sanikop          Backup();
704*57696d54SAkhilesh Sanikop          break;
705*57696d54SAkhilesh Sanikop       case 'd': case 'D':
706*57696d54SAkhilesh Sanikop          if (ValidPartNum(currentSpace->partNum))
707*57696d54SAkhilesh Sanikop             DeletePartition(currentSpace->partNum);
708*57696d54SAkhilesh Sanikop          break;
709*57696d54SAkhilesh Sanikop       case 'h': case 'H':
710*57696d54SAkhilesh Sanikop          ShowHelp();
711*57696d54SAkhilesh Sanikop          break;
712*57696d54SAkhilesh Sanikop       case 'i': case 'I':
713*57696d54SAkhilesh Sanikop          if (ValidPartNum(currentSpace->partNum))
714*57696d54SAkhilesh Sanikop             ShowInfo(currentSpace->partNum);
715*57696d54SAkhilesh Sanikop          break;
716*57696d54SAkhilesh Sanikop       case 'l': case 'L':
717*57696d54SAkhilesh Sanikop          LoadBackup();
718*57696d54SAkhilesh Sanikop          break;
719*57696d54SAkhilesh Sanikop       case 'm': case 'M':
720*57696d54SAkhilesh Sanikop          if (ValidPartNum(currentSpace->partNum))
721*57696d54SAkhilesh Sanikop             ChangeName(currentSpace->partNum);
722*57696d54SAkhilesh Sanikop          break;
723*57696d54SAkhilesh Sanikop       case 'n': case 'N':
724*57696d54SAkhilesh Sanikop          if (currentSpace->partNum < 0) {
725*57696d54SAkhilesh Sanikop             MakeNewPart();
726*57696d54SAkhilesh Sanikop             IdentifySpaces();
727*57696d54SAkhilesh Sanikop          } // if
728*57696d54SAkhilesh Sanikop          break;
729*57696d54SAkhilesh Sanikop       case 'q': case 'Q':
730*57696d54SAkhilesh Sanikop          exitNow = 1;
731*57696d54SAkhilesh Sanikop          break;
732*57696d54SAkhilesh Sanikop       case 't': case 'T':
733*57696d54SAkhilesh Sanikop          if (ValidPartNum(currentSpace->partNum))
734*57696d54SAkhilesh Sanikop             ChangeType(currentSpace->partNum);
735*57696d54SAkhilesh Sanikop          break;
736*57696d54SAkhilesh Sanikop       case 'v': case 'V':
737*57696d54SAkhilesh Sanikop          Verify();
738*57696d54SAkhilesh Sanikop          break;
739*57696d54SAkhilesh Sanikop       case 'w': case 'W':
740*57696d54SAkhilesh Sanikop          SaveData();
741*57696d54SAkhilesh Sanikop          break;
742*57696d54SAkhilesh Sanikop       default:
743*57696d54SAkhilesh Sanikop          break;
744*57696d54SAkhilesh Sanikop    } // switch()
745*57696d54SAkhilesh Sanikop    DrawMenu();
746*57696d54SAkhilesh Sanikop    return exitNow;
747*57696d54SAkhilesh Sanikop } // GPTDataCurses::Dispatch()
748*57696d54SAkhilesh Sanikop 
749*57696d54SAkhilesh Sanikop // Draws the main menu
DrawMenu(void)750*57696d54SAkhilesh Sanikop void GPTDataCurses::DrawMenu(void) {
751*57696d54SAkhilesh Sanikop    string title="cgdisk ";
752*57696d54SAkhilesh Sanikop    title += GPTFDISK_VERSION;
753*57696d54SAkhilesh Sanikop    string drive="Disk Drive: ";
754*57696d54SAkhilesh Sanikop    drive += device;
755*57696d54SAkhilesh Sanikop    ostringstream size;
756*57696d54SAkhilesh Sanikop 
757*57696d54SAkhilesh Sanikop    size << "Size: " << diskSize << ", " << BytesToIeee(diskSize, blockSize);
758*57696d54SAkhilesh Sanikop 
759*57696d54SAkhilesh Sanikop    clear();
760*57696d54SAkhilesh Sanikop    move(0, (COLS - title.length()) / 2);
761*57696d54SAkhilesh Sanikop    printw("%s", title.c_str());
762*57696d54SAkhilesh Sanikop    move(2, (COLS - drive.length()) / 2);
763*57696d54SAkhilesh Sanikop    printw("%s", drive.c_str());
764*57696d54SAkhilesh Sanikop    move(3, (COLS - size.str().length()) / 2);
765*57696d54SAkhilesh Sanikop    printw("%s", size.str().c_str());
766*57696d54SAkhilesh Sanikop    DisplayParts(currentSpaceNum);
767*57696d54SAkhilesh Sanikop } // DrawMenu
768*57696d54SAkhilesh Sanikop 
MainMenu(void)769*57696d54SAkhilesh Sanikop int GPTDataCurses::MainMenu(void) {
770*57696d54SAkhilesh Sanikop    if (((LINES - RESERVED_TOP - RESERVED_BOTTOM) < 2) || (COLS < 80)) {
771*57696d54SAkhilesh Sanikop       Report("Display is too small; it must be at least 80 x 14 characters!");
772*57696d54SAkhilesh Sanikop    } else {
773*57696d54SAkhilesh Sanikop       if (GPTData::Verify() > 0)
774*57696d54SAkhilesh Sanikop          Report("Warning! Problems found on disk! Use the Verify function to learn more.\n"
775*57696d54SAkhilesh Sanikop                 "Using gdisk or some other program may be necessary to repair the problems.");
776*57696d54SAkhilesh Sanikop       IdentifySpaces();
777*57696d54SAkhilesh Sanikop       currentSpaceNum = 0;
778*57696d54SAkhilesh Sanikop       DrawMenu();
779*57696d54SAkhilesh Sanikop       AcceptInput();
780*57696d54SAkhilesh Sanikop    } // if/else
781*57696d54SAkhilesh Sanikop    endwin();
782*57696d54SAkhilesh Sanikop    return 0;
783*57696d54SAkhilesh Sanikop } // GPTDataCurses::MainMenu
784*57696d54SAkhilesh Sanikop 
785*57696d54SAkhilesh Sanikop /***********************************************************
786*57696d54SAkhilesh Sanikop  *                                                         *
787*57696d54SAkhilesh Sanikop  * Non-class support functions (mostly related to ncurses) *
788*57696d54SAkhilesh Sanikop  *                                                         *
789*57696d54SAkhilesh Sanikop  ***********************************************************/
790*57696d54SAkhilesh Sanikop 
791*57696d54SAkhilesh Sanikop // Clears the specified line of all data....
ClearLine(int lineNum)792*57696d54SAkhilesh Sanikop void ClearLine(int lineNum) {
793*57696d54SAkhilesh Sanikop    move(lineNum, 0);
794*57696d54SAkhilesh Sanikop    clrtoeol();
795*57696d54SAkhilesh Sanikop } // ClearLine()
796*57696d54SAkhilesh Sanikop 
797*57696d54SAkhilesh Sanikop // Clear the last few lines of the display
ClearBottom(void)798*57696d54SAkhilesh Sanikop void ClearBottom(void) {
799*57696d54SAkhilesh Sanikop    move(LINES - RESERVED_BOTTOM, 0);
800*57696d54SAkhilesh Sanikop    clrtobot();
801*57696d54SAkhilesh Sanikop } // ClearBottom()
802*57696d54SAkhilesh Sanikop 
PromptToContinue(void)803*57696d54SAkhilesh Sanikop void PromptToContinue(void) {
804*57696d54SAkhilesh Sanikop    ClearBottom();
805*57696d54SAkhilesh Sanikop    move(LINES - 2, (COLS - 29) / 2);
806*57696d54SAkhilesh Sanikop    printw("Press any key to continue....");
807*57696d54SAkhilesh Sanikop    cbreak();
808*57696d54SAkhilesh Sanikop    getch();
809*57696d54SAkhilesh Sanikop } // PromptToContinue()
810*57696d54SAkhilesh Sanikop 
811*57696d54SAkhilesh Sanikop // Display one line of text on the screen and prompt to press any key to continue.
Report(string theText)812*57696d54SAkhilesh Sanikop void Report(string theText) {
813*57696d54SAkhilesh Sanikop    clear();
814*57696d54SAkhilesh Sanikop    move(0, 0);
815*57696d54SAkhilesh Sanikop    printw("%s", theText.c_str());
816*57696d54SAkhilesh Sanikop    move(LINES - 2, (COLS - 29) / 2);
817*57696d54SAkhilesh Sanikop    printw("Press any key to continue....");
818*57696d54SAkhilesh Sanikop    cbreak();
819*57696d54SAkhilesh Sanikop    getch();
820*57696d54SAkhilesh Sanikop } // Report()
821*57696d54SAkhilesh Sanikop 
822*57696d54SAkhilesh Sanikop // Displays all the partition type codes and then prompts to continue....
823*57696d54SAkhilesh Sanikop // NOTE: This function temporarily exits curses mode as a matter of
824*57696d54SAkhilesh Sanikop // convenience.
ShowTypes(void)825*57696d54SAkhilesh Sanikop void ShowTypes(void) {
826*57696d54SAkhilesh Sanikop    PartType tempType;
827*57696d54SAkhilesh Sanikop    char junk;
828*57696d54SAkhilesh Sanikop 
829*57696d54SAkhilesh Sanikop    def_prog_mode();
830*57696d54SAkhilesh Sanikop    endwin();
831*57696d54SAkhilesh Sanikop    tempType.ShowAllTypes(LINES - 3);
832*57696d54SAkhilesh Sanikop    cout << "\nPress the <Enter> key to continue: ";
833*57696d54SAkhilesh Sanikop    cin.get(junk);
834*57696d54SAkhilesh Sanikop    reset_prog_mode();
835*57696d54SAkhilesh Sanikop    refresh();
836*57696d54SAkhilesh Sanikop } // ShowTypes()
837