static int printVariable(D4printer* out, NCD4node* var, int depth) { int ret = NC_NOERR; NCD4node* basetype = var->basetype; char* fqn = NULL; INDENT(depth); CAT("<"); switch (var->subsort) { default: CAT(basetype->name); printXMLAttributeName(out, "name", var->name); break; case NC_ENUM: CAT("Enum"); printXMLAttributeName(out, "name", var->name); printXMLAttributeName(out, "enum", (fqn=NCD4_makeFQN(basetype))); break; case NC_OPAQUE: CAT("Opaque"); printXMLAttributeName(out, "name", var->name); printXMLAttributeName(out, "type", (fqn=NCD4_makeFQN(basetype))); break; case NC_SEQ: CAT("Seq"); printXMLAttributeName(out, "name", var->name); printXMLAttributeName(out, "type", (fqn=NCD4_makeFQN(basetype))); break; case NC_STRUCT: CAT("Struct"); printXMLAttributeName(out, "name", var->name); printXMLAttributeName(out, "type", (fqn=NCD4_makeFQN(basetype))); break; } if(hasMetaData(var)) { CAT(">\n"); depth++; if((ret=printMetaData(out,var,depth))) goto done; depth--; INDENT(depth); CAT("</"); if(basetype->subsort == NC_ENUM) CAT("Enum"); else if(basetype->subsort == NC_OPAQUE) CAT("Opaque"); else if(basetype->subsort == NC_STRUCT) CAT("Struct"); else if(basetype->subsort == NC_SEQ) CAT("Sequence"); else CAT(basetype->name); CAT(">"); } else CAT("/>"); done: nullfree(fqn); return THROW(ret); }
int main(int argc, char* argv[]) { //The current working directory: Directory* dir = NULL; //Checks if too many arguments have been given: if(argc > 2) { std::cerr << "Please pass a single, valid directory\n"; return -1; } //Otherwise, sees if a directory has been given, //and if so, attempt to open it: else if(argc == 2) { //Attempt to open try { dir = new Directory(argv[1]); } //Give an error message and quit if it fails: catch(int e) { std::cerr << "Cannot open '" << argv[1] << "': "; switch(e) { case EACCES: std::cerr << "Permission denied."; break; case ENOENT: std::cerr << "No such directory."; break; case ENOTDIR: std::cerr << "Not a directory."; break; } std::cerr << std::endl; return -1; } } //Otherwise, there are no arguments given, so use //the user's current working directory: else { //Get the current working directory: char* cwd = getcwd(NULL, 0); //Attempt to open it: try { dir = new Directory(cwd); } //Give an error message and quit if it fails: catch(int e) { std::cerr << "Cannot open '" << cwd << "': "; switch(e) { case EACCES: std::cerr << "Permission denied."; break; case ENOENT: std::cerr << "No such directory."; break; case ENOTDIR: std::cerr << "Not a directory."; break; } std::cerr << std::endl; return -1; } } //Attempt to read the directory's contents: try { dir->read(); } //Give an error message and quit if it fails: catch(int e) { std::cerr << "Cannot open '" << dir->getPath() << "': "; switch(errno) { case EACCES: std::cerr << "Permission denied."; break; case ENOENT: std::cerr << "No such directory."; break; case ENOTDIR: std::cerr << "Not a directory."; break; } std::cerr << std::endl; return -1; } if(dir->getName() == "../") dir->cleanPath(); //Initialise ncurses: initscr(); //The colour pairs: init_pair(2, COLOR_WHITE, COLOR_RED); //Enable keypad mode (allows use of the up and down arrows): keypad(stdscr, true); //Start using colour: start_color(); //Update the screen: refresh(); //Hides the cursor, set 'noecho()': curs_set(0); noecho(); int input = 0; std::string path = ""; unsigned int selection = 0; DiskItem* clipboard = NULL; //While the user has not quit: while((char(input) != 'q') && (char(input) != 'Q')) { //Redraw the windows and help: updateWindows(); drawHelp(); //If necessary, resizes the directory path: path = ""; if(dir->getPath().length() >= screenX) path = fitToSize(dir->getPath(), (screenX - 2)); else path = dir->getPath(); //The X position needed to print the path in the centre: int pos = ((screenX - path.length()) / 2); //Write the user's current directory: mvprintw(0, pos, "%s", path.c_str()); //Get the files and sort the contents: std::vector <DiskItem*> items = dir->getFiles(); //Checks if the contents of the directory will fit in the window: if((fileview.height - 2) > (items.size() - dir->getDotfiles())) { //Print the contents, except the dotfiles, to the window: for(unsigned int i = dir->getDotfiles(); i < items.size(); i++) { //If we're printing the current selection, highlight it: if(selection == (i - dir->getDotfiles())) { //Print the name: mvwprintw(fileview.window,((i - dir->getDotfiles()) + 1), 1, "%s", items[i]->getName().c_str()); //Move to the beginning of the line, and highlight the line up to but excluding the window border: mvwchgat(fileview.window, ((i - dir->getDotfiles()) + 1), 1, (fileview.width - 2), A_NORMAL, 1, NULL); } else //Print the name: mvwprintw(fileview.window, ((i - dir->getDotfiles()) + 1), 1, "%s", items[i]->getName().c_str()); } } //Otherwise, we can only print part of the directory's contents: else { //If the selection is less than the height, display the first few items: if(selection < (fileview.height - 2)) { for(unsigned int i = dir->getDotfiles(); i < ((fileview.height - 2) + dir->getDotfiles()); i++) { //If we're printing the current selection, highlight it: if(selection == (i - dir->getDotfiles())) { //Print the name: mvwprintw(fileview.window,((i - dir->getDotfiles()) + 1), 1, "%s", items[i]->getName().c_str()); //Move to the beginning of the line, and highlight the line up to but excluding the window border: mvwchgat(fileview.window, ((i - dir->getDotfiles()) + 1), 1, (fileview.width - 2), A_NORMAL, 1, NULL); } else //Print the name: mvwprintw(fileview.window, ((i - dir->getDotfiles()) + 1), 1, "%s", items[i]->getName().c_str()); } } //Otherwise, display the selection as the last item: else { for(unsigned int i = (dir->getDotfiles() + ((selection + 1) - (fileview.height - 2))); i < ((selection + 1) + dir->getDotfiles()); i++) { unsigned int y = i - ((selection - (fileview.height - 2)) + dir->getDotfiles()); //If we're printing the current selection, highlight it: if(selection == (i - dir->getDotfiles())) { //Print the name: mvwprintw(fileview.window, y, 1, "%s", items[i]->getName().c_str()); //Move to the beginning of the line, and highlight the line up to but excluding the window border: mvwchgat(fileview.window, y, 1, (fileview.width - 2), A_NORMAL, 1, NULL); } else //Print the name: mvwprintw(fileview.window, y, 1, "%s", items[i]->getName().c_str()); } } } //Print the selected file's metadata to the 'fileinfo' window: printMetaData(items[selection + dir->getDotfiles()]); //Print the contents of the clipboard to the 'extrainfo' window: printClipboard(clipboard); //Refresh the screen and windows: refresh(); wrefresh(fileview.window); wrefresh(fileinfo.window); wrefresh(extrainfo.window); //Gets the input: input = getch(); //Moves the selection up or down if those keys were pressed: if((input == KEY_UP) || (char(input) == 'k') || (char(input) == 'K')) if(selection > 0) selection--; if((input == KEY_DOWN) || (char(input) == 'j') || (char(input) == 'J')) if(selection < ((items.size() - dir->getDotfiles()) - 1)) selection++; //If the user has pressed Enter: if(char(input) == '\n') { //Attempts to cast the current selection to a Directory*: Directory* selected = dynamic_cast <Directory*>(items[selection + dir->getDotfiles()]); //If the user has selected a directory: if(selected != NULL) { //Keep the old directory so we can delete it: Directory* oldDir = dir; //Makes a copy of the directory we want to move to: try { dir = new Directory(selected); dir->read(); delete oldDir; selection = 0; clear(); } //If an error occurs, inform the user with a message box: catch(int e) { std::string error = "Cannot open '" + dir->getPath() + "' "; switch(errno) { case EACCES: error += "Permission denied."; break; case ENOENT: error += "No such directory."; break; case ENOTDIR: error += "Not a directory."; break; } messageBox(error); } } } //Otherwise, if the user has pressed 'd' for delete: else if((char(input) == 'd') || (char(input) == 'D')) { DiskItem* selected = items[selection + dir->getDotfiles()]; //Attempt to delete the selected item: if(selected->deletef()) { delete selected; dir->getFiles().erase(dir->getFiles().begin() + (selection + dir->getDotfiles())); //If we deleted the last item, then 'selection + dir->getDotfiles()' will //go out of bounds on the 'item' array, so decrement selection: if((selection + dir->getDotfiles()) == dir->getFiles().size()) selection--; } //If an error occurs, inform the user with a message box: else { std::string error = "Could not delete '" + selected->getPath() + "'"; messageBox(error); } } //Otherwise, if the user has pressed 'c' for copy: else if((char(input) == 'C') || (char(input) == 'c')) { if(items[selection + dir->getDotfiles()]->getName() != "../") { //Checks if we are trying to copy a directory or a file: clipboard = dynamic_cast <Directory*>(items[selection + dir->getDotfiles()]); if(clipboard == NULL) { //We are copying a file: clipboard = new File(dynamic_cast <File*>(items[selection + dir->getDotfiles()])); } else { //We are copying a directory: clipboard = new Directory(dynamic_cast <Directory*>(items[selection + dir->getDotfiles()])); } } } //Otherwise, if the user has pressed 'x' for cut: else if((char(input) == 'X') || (char(input) == 'x')) { if(items[selection + dir->getDotfiles()]->getName() != "../") { //Checks if we are trying to cut a directory or a file: clipboard = dynamic_cast <Directory*>(items[selection + dir->getDotfiles()]); if(clipboard == NULL) { //We are cutting a file: clipboard = new File(dynamic_cast <File*>(items[selection + dir->getDotfiles()])); } else { //We are cutting a directory: clipboard = new Directory(dynamic_cast <Directory*>(items[selection + dir->getDotfiles()])); } clipboard->cut(); } } //Otherwise, if the user has pressed 'p' for paste: else if((char(input) == 'P') || (char(input) == 'p')) { if(clipboard != NULL) { //Attempt to paste the item in the clipboard: if(! clipboard->paste(dir->getPath())) { //If an error occurs, inform the user with a message box: std::string error = "Could not paste '" + clipboard->getName() + "'"; messageBox(error); } else { //If it works fine, add the new item to the directory's list of items: DiskItem* item = clipboard; dir->getFiles().push_back(item); std::sort(dir->getFiles().begin(), dir->getFiles().end(), byName); //Empty the clipboard: clipboard = NULL; } } } //Otherwise, if the user presses 'r' for rename: else if((char(input) == 'R') || (char(input) == 'r')) { //Get the new name, and attempt to rename the selected item: std::string newName = inputBox(); if(newName != "") { //Check if we are renaming a directory: if(dynamic_cast <Directory*>(items[selection + dir->getDotfiles()]) != NULL) newName += '/'; if(! items[selection + dir->getDotfiles()]->rename(newName.c_str())) { //If an error occurs, inform the user with a message box: std::string error = "Cannot rename '" + items[selection + dir->getDotfiles()]->getName() + "'"; messageBox(error); } } } } //Delete the directory object: delete dir; //Close ncurses: endwin(); return 0; }
static int printNode(D4printer* out, NCD4node* node, int depth) { int ret = NC_NOERR; int i; char* fqn = NULL; switch (node->sort) { case NCD4_GROUP: if(node->group.isdataset) printDataset(out,node,depth); else printGroup(out,node,depth); break; case NCD4_DIM: INDENT(depth); CAT("<Dimension"); if(node->name != NULL) printXMLAttributeName(out, "name", node->name); printXMLAttributeSize(out, "size", node->dim.size); if(node->dim.isunlimited) printXMLAttributeString(out, UCARTAGUNLIM, "1"); CAT("/>"); break; case NCD4_TYPE: switch (node->subsort) { default: break; case NC_OPAQUE: INDENT(depth); CAT("<Opaque"); ncbytesclear(out->tmp); printXMLAttributeName(out, "name", node->name); if(node->opaque.size > 0) printXMLAttributeSize(out, "size", node->opaque.size); CAT("/>"); break; case NC_ENUM: INDENT(depth); CAT("<Enumeration"); printXMLAttributeName(out, "name", node->name); if(node->basetype->subsort <= NC_MAX_ATOMIC_TYPE) printXMLAttributeName(out, "basetype", node->basetype->name); else { char* fqn = NULL; printXMLAttributeName(out, "basetype", (fqn = NCD4_makeFQN(node->basetype))); nullfree(fqn); } CAT(">\n"); depth++; for(i=0;i<nclistlength(node->en.econsts);i++) { NCD4node* ec = (NCD4node*)nclistget(node->en.econsts,i); INDENT(depth); CAT("<EnumConst"); printXMLAttributeName(out, "name", ec->name); printXMLAttributeAtomics(out, "value", &ec->en.ecvalue, node->basetype->subsort); CAT("/>\n"); } depth--; INDENT(depth); CAT("</Enumeration>"); break; case NC_STRUCT: INDENT(depth); CAT("<Structure"); printXMLAttributeName(out, "name", node->name); CAT(">\n"); depth++; for(i=0;i<nclistlength(node->vars);i++) { NCD4node* field = (NCD4node*)nclistget(node->vars,i); printVariable(out,field,depth); CAT("\n"); } if((ret=printMetaData(out,node,depth))) goto done; depth--; INDENT(depth); CAT("</Structure>"); break; case NC_SEQ: INDENT(depth); CAT("<Vlen"); printXMLAttributeName(out, "name", node->name); printXMLAttributeName(out, "type", (fqn=NCD4_makeFQN(node->basetype))); if(hasMetaData(node)) { CAT(">\n"); depth++; if((ret=printMetaData(out,node,depth))) goto done; depth--; INDENT(depth); CAT("</Vlen>"); } else CAT("/>"); break; } break; case NCD4_VAR: /* Only top-level vars are printed here */ if(ISTOPLEVEL(node)) { if((ret=printVariable(out,node,depth))) goto done; CAT("\n"); } break; default: abort(); break; } done: nullfree(fqn); return THROW(ret); }