/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Browser.h" #include "BrowserCommand.h" #include "MainWindow.h" #include "IBMApplication.h" #include "../base/WarningDialogManager.h" #include "../base/ButtonInterface.h" #include "../base/Strings.h" #include #include #ifdef DXD_WIN #define stat _stat #endif #if defined(HAVE_RE_COMP) #undef HAVE_REGCMP #undef HAVE_REGCOMP #undef HAVE_FINDFIRST extern "C" char *re_comp(char *s); extern "C" int re_exec(char *); #elif defined(HAVE_REGCMP) #undef HAVE_REGCOMP #undef HAVE_FINDFIRST extern "C" char *regcmp(...); extern "C" char *regex(char *, char *, ...); #elif HAVE_REGCOMP extern "C" { #include } #undef HAVE_RE_COMP #undef HAVE_FINDFIRST #elif defined(HAVE_RE_COMP) #undef HAVE_FINDFIRST extern "C" char *re_comp(char *s); extern "C" int re_exec(char *); #elif defined(HAVE_FINDFIRST) #include #endif boolean Browser::ClassInitialized = FALSE; String Browser::DefaultResources[] = { "*Btext.fontList: -misc-fixed-medium-r-normal--13*", ".iconName: Browser", ".title: File Browser", ".geometry: +435+105", "*XmScrollBar.initialDelay: 250", "*XmScrollBar.repeatDelay: 50", "*browFileMenu.labelString: File", "*browFileMenu.mnemonic: F", "*browCloseOption.labelString: Close", "*browCloseOption.mnemonic: C", "*browMarkMenu.labelString: Mark", "*browMarkMenu.mnemonic: M", "*browPlaceMarkOption.labelString: Place mark", "*browPlaceMarkOption.mnemonic: P", "*browClearMarkOption.labelString: Clear mark", "*browClearMarkOption.mnemonic: P", "*browGotoMarkOption.labelString: Goto mark", "*browGotoMarkOption.mnemonic: P", "*browPageMenu.labelString: Page", "*browPageMenu.mnemonic: P", "*browFirstPageOption.labelString: First page", "*browFirstPageOption.mnemonic: F", "*browLastPageOption.labelString: Last page", "*browLastPageOption.mnemonic: L", "*browSearchMenu.labelString: Search", "*browSearchMenu.mnemonic: S", "*browSearchOption.labelString: Search...", "*browSearchOption.mnemonic: S", "*browByteOffsets.labelString: Byte Offsets:", "*browLineOffsets.labelString: Line Offsets:", "*browFromMark.labelString: From mark:", "*browFromTopOfFile.labelString: From top of file:", "*browFromStartOfLine.labelString: From start of line:", NULL }; Browser::Browser(MainWindow *) : IBMMainWindow("GARBrowser", TRUE) { // // Initialize member data. // this->page_size = 1024*20; this->ignore_cb = False; this->marker_char[0] = '\0'; this->marker_char[1] = '\0'; this->closeOption = NUL(CommandInterface*); this->placeMarkOption = NUL(CommandInterface*); this->clearMarkOption = NUL(CommandInterface*); this->gotoMarkOption = NUL(CommandInterface*); this->firstPageOption = NUL(CommandInterface*); this->lastPageOption = NUL(CommandInterface*); this->searchOption = NUL(CommandInterface*); this->placeMarkCmd = new BrowserCommand("placeMark",this->commandScope, TRUE, this, this->PLACE_MARK); this->clearMarkCmd = new BrowserCommand("clearMark",this->commandScope, TRUE, this, this->CLEAR_MARK); this->gotoMarkCmd = new BrowserCommand("gotoMark",this->commandScope, TRUE, this, this->GOTO_MARK); this->firstPageCmd = new BrowserCommand("firstPage",this->commandScope, TRUE, this, this->FIRST_PAGE); this->lastPageCmd = new BrowserCommand("lastPage",this->commandScope, TRUE, this, this->LAST_PAGE); this->searchCmd = new BrowserCommand("search",this->commandScope, TRUE, this, this->SEARCH); this->closeCmd = new BrowserCommand("close",this->commandScope, TRUE, this, this->CLOSE); this->searchDialog = (SearchDialog*)NULL; // // Install the default resources for THIS class (not the derived classes) // if (NOT Browser::ClassInitialized) { ASSERT(theApplication); Browser::ClassInitialized = TRUE; this->installDefaultResources(theApplication->getRootWidget()); } } Browser::~Browser() { if (this->searchDialog) delete this->searchDialog; if (this->searchOption) delete this->searchOption; if (this->lastPageOption) delete this->lastPageOption; if (this->firstPageOption)delete this->firstPageOption; if (this->gotoMarkOption) delete this->gotoMarkOption; if (this->clearMarkOption)delete this->clearMarkOption; if (this->placeMarkOption)delete this->placeMarkOption; if (this->closeOption) delete this->closeOption; delete this->closeCmd; delete this->searchCmd; delete this->lastPageCmd; delete this->firstPageCmd; delete this->gotoMarkCmd; delete this->clearMarkCmd; delete this->placeMarkCmd; } // // called by MainWindow::CloseCallback(). // void Browser::closeWindow() { this->closeCmd->execute(); } void Browser::createMenus(Widget parent) { this->createFileMenu(parent); this->createMarkMenu(parent); this->createPageMenu(parent); this->createSearchMenu(parent); this->createHelpMenu(parent); Browser::AddHelpCallbacks(this->fileMenu); Browser::AddHelpCallbacks(this->markMenu); Browser::AddHelpCallbacks(this->pageMenu); Browser::AddHelpCallbacks(this->searchMenu); Browser::AddHelpCallbacks(this->helpMenu); } void Browser::createFileMenu(Widget parent) { ASSERT(parent); Widget pulldown; // // Create "File" menu and options. // pulldown = this->fileMenuPulldown = XmCreatePulldownMenu(parent, "fileMenuPulldown", NUL(ArgList), 0); this->fileMenu = XtVaCreateManagedWidget ("browFileMenu", xmCascadeButtonWidgetClass, parent, XmNsubMenuId, pulldown, NULL); this->closeOption = new ButtonInterface(pulldown, "browCloseOption", this->closeCmd); Browser::AddHelpCallbacks(pulldown); } void Browser::createMarkMenu(Widget parent) { ASSERT(parent); Widget pulldown; // // Create "Mark" menu and options. // pulldown = this->fileMenuPulldown = XmCreatePulldownMenu(parent, "browMarkMenuPulldown",NUL(ArgList),0); this->markMenu = XtVaCreateManagedWidget ("browMarkMenu", xmCascadeButtonWidgetClass, parent, XmNsubMenuId, pulldown, NULL); this->placeMarkOption = new ButtonInterface(pulldown, "browPlaceMarkOption", this->placeMarkCmd); this->clearMarkOption = new ButtonInterface(pulldown, "browClearMarkOption", this->clearMarkCmd); this->gotoMarkOption = new ButtonInterface(pulldown, "browGotoMarkOption", this->gotoMarkCmd); Browser::AddHelpCallbacks(pulldown); } void Browser::createPageMenu(Widget parent) { ASSERT(parent); Widget pulldown; // // Create "File" menu and options. // pulldown = this->pageMenuPulldown = XmCreatePulldownMenu(parent, "browPageMenuPulldown",NUL(ArgList),0); this->pageMenu = XtVaCreateManagedWidget ("browPageMenu", xmCascadeButtonWidgetClass, parent, XmNsubMenuId, pulldown, NULL); this->firstPageOption = new ButtonInterface(pulldown, "browFirstPageOption", this->firstPageCmd); this->lastPageOption = new ButtonInterface(pulldown, "browLastPageOption", this->lastPageCmd); Browser::AddHelpCallbacks(pulldown); } void Browser::createSearchMenu(Widget parent) { ASSERT(parent); Widget pulldown; // // Create "Search" menu and options. // pulldown = this->searchMenuPulldown = XmCreatePulldownMenu(parent, "browSearchMenuPulldown", NUL(ArgList), 0); this->searchMenu = XtVaCreateManagedWidget ("browSearchMenu", xmCascadeButtonWidgetClass, parent, XmNsubMenuId, pulldown, NULL); this->searchOption = new ButtonInterface(pulldown, "browSearchOption", this->searchCmd); Browser::AddHelpCallbacks(pulldown); } void Browser::createHelpMenu(Widget parent) { this->createBaseHelpMenu(parent); } // // Install the default resources for this class. // void Browser::installDefaultResources(Widget baseWidget) { this->setDefaultResources(baseWidget, Browser::DefaultResources); this->IBMMainWindow::installDefaultResources(baseWidget); } void Browser::initialize() { if (!this->isInitialized()) { // // Now, call the superclass initialize(). // this->IBMMainWindow::initialize(); } } Widget Browser::createWorkArea(Widget parent) { Widget form1; Widget hsb; Widget label; Pixel bg; Arg wargs[50]; int n; form1 = XtVaCreateManagedWidget("browForm", xmFormWidgetClass, parent,NULL); n = 0; XtSetArg(wargs[n], XmNwordWrap, False); n++; XtSetArg(wargs[n], XmNeditMode, XmMULTI_LINE_EDIT); n++; XtSetArg(wargs[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNleftAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNrightAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNeditable, False); n++; XtSetArg(wargs[n], XmNcolumns, 80); n++; XtSetArg(wargs[n], XmNrows, 16); n++; this->text = XmCreateScrolledText(form1, "Btext", wargs, n); XtManageChild(this->text); XtAddCallback(this->text, XmNmotionVerifyCallback, Browser::motionCB, (XtPointer)this); XtVaGetValues(XtParent(this->text), XmNverticalScrollBar, &this->vsb, XmNhorizontalScrollBar, &hsb, NULL); XtVaGetValues(this->text, XmNbackground, &bg, NULL); XtVaSetValues(this->vsb, XmNforeground, bg, NULL); XtVaSetValues(hsb, XmNforeground, bg, NULL); XtAddCallback(this->vsb, XmNincrementCallback, Browser::pageIncCB, (XtPointer)this); XtAddCallback(this->vsb, XmNdecrementCallback, Browser::pageDecCB, (XtPointer)this); XtAddCallback(this->vsb, XmNpageIncrementCallback, Browser::pageIncCB, (XtPointer)this); XtAddCallback(this->vsb, XmNpageDecrementCallback, Browser::pageDecCB, (XtPointer)this); XtAddCallback(this->vsb, XmNtoTopCallback, Browser::pageDecCB, (XtPointer)this); XtAddCallback(this->vsb, XmNtoBottomCallback, Browser::pageIncCB, (XtPointer)this); XtAddCallback(this->vsb, XmNvalueChangedCallback, Browser::pageControlCB, (XtPointer)this); label = XtVaCreateManagedWidget( "browFromMark", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 20, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 20, NULL); this->byte_mark_offset = XtVaCreateManagedWidget( "byte_mark_offset", xmTextWidgetClass, form1, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, label, XmNleftOffset, 10, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopOffset, -2, XmNtopWidget, label, XmNcolumns, 8, NULL); XtAddCallback(this->byte_mark_offset, XmNactivateCallback, Browser::gotoByteMarkOffsetCB, (XtPointer)this); XtAddCallback(this->byte_mark_offset, XmNmodifyVerifyCallback, Browser::integerMVCB, (XtPointer)this); label = XtVaCreateManagedWidget( "browFromMark", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 20, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 70, NULL); this->line_mark_offset = XtVaCreateManagedWidget( "line_mark_offset", xmTextWidgetClass, form1, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, label, XmNleftOffset, 10, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopOffset, -2, XmNtopWidget, label, XmNcolumns, 8, NULL); XtAddCallback(this->line_mark_offset, XmNactivateCallback, Browser::gotoLineMarkOffsetCB, (XtPointer)this); XtAddCallback(this->line_mark_offset, XmNmodifyVerifyCallback, Browser::integerMVCB, (XtPointer)this); label = XtVaCreateManagedWidget( "browFromStartOfLine", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, label, XmNbottomOffset, 10, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 20, NULL); this->byte_start_offset = XtVaCreateManagedWidget( "byte_start_offset", xmTextWidgetClass, form1, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, label, XmNleftOffset, 10, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, label, XmNtopOffset, -2, XmNcolumns, 8, NULL); XtAddCallback(this->byte_start_offset, XmNactivateCallback, Browser::gotoByteStartOffsetCB, (XtPointer)this); XtAddCallback(this->byte_start_offset, XmNmodifyVerifyCallback, Browser::integerMVCB, (XtPointer)this); label = XtVaCreateManagedWidget( "browFromTopOfFile", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, label, XmNbottomOffset, 10, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 20, NULL); this->byte_top_offset = XtVaCreateManagedWidget( "byte_top_offset", xmTextWidgetClass, form1, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, label, XmNleftOffset, 10, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, label, XmNtopOffset, -2, XmNcolumns, 8, NULL); XtAddCallback(this->byte_top_offset, XmNactivateCallback, Browser::gotoByteTopOffsetCB, (XtPointer)this); XtAddCallback(this->byte_top_offset, XmNmodifyVerifyCallback, Browser::integerMVCB, (XtPointer)this); label = XtVaCreateManagedWidget( "browFromTopOfFile", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, label, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 70, NULL); this->line_top_offset = XtVaCreateManagedWidget( "line_top_offset", xmTextWidgetClass, form1, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, label, XmNleftOffset, 10, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, label, XmNtopOffset, -2, XmNcolumns, 8, NULL); XtAddCallback(this->line_top_offset, XmNactivateCallback, Browser::gotoLineTopOffsetCB, (XtPointer)this); XtAddCallback(this->line_top_offset, XmNmodifyVerifyCallback, Browser::integerMVCB, (XtPointer)this); label = XtVaCreateManagedWidget( "browByteOffsets", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, label, XmNbottomOffset, 10, XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET, XmNrightWidget, this->byte_top_offset, XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, XmNleftWidget, this->byte_top_offset, XmNleftOffset, -10, XmNrightOffset, -10, NULL); label = XtVaCreateManagedWidget( "browLineOffsets", xmLabelWidgetClass, form1, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, label, XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET, XmNrightWidget, this->line_top_offset, XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, XmNleftWidget, this->line_top_offset, XmNleftOffset, -10, XmNrightOffset, -10, NULL); XtVaSetValues(XtParent(this->text), XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, label, XmNbottomOffset, 10, NULL); Browser::AddHelpCallbacks(form1); return form1; } // // Called when the slide bar is moved down. // void Browser::pageIncCB(Widget w, XtPointer client, XtPointer ) { Browser *browser = (Browser *)client; int max; int value; int slider_size; if(browser->ignore_cb) return; theIBMApplication->setBusyCursor(TRUE); XtVaGetValues(w, XmNmaximum, &max, XmNsliderSize, &slider_size, XmNvalue, &value, NULL); if(max == (value + slider_size)) { if(browser->nextPage()) browser->adjustScrollBar(True); } theIBMApplication->setBusyCursor(FALSE); } // // Called when the slide bar is moved up. // void Browser::pageDecCB(Widget w, XtPointer client, XtPointer ) { Browser *browser = (Browser *)client; int min; int value; int slider_size; if(browser->ignore_cb) return; theIBMApplication->setBusyCursor(TRUE); XtVaGetValues(w, XmNminimum, &min, XmNvalue, &value, XmNsliderSize, &slider_size, NULL); if(value == min) { if(browser->prevPage()) browser->adjustScrollBar(False); } theIBMApplication->setBusyCursor(FALSE); } void Browser::pageControlCB(Widget w, XtPointer client, XtPointer ) { Browser *browser = (Browser *)client; int max; int value; int slider_size; if(browser->ignore_cb) return; theIBMApplication->setBusyCursor(TRUE); XtVaGetValues(w, XmNmaximum, &max, XmNvalue, &value, XmNsliderSize, &slider_size, NULL); if(value == 0) { if(browser->prevPage()) browser->adjustScrollBar(False); } else if(value == (max - slider_size)) { if(browser->nextPage()) browser->adjustScrollBar(True); } theIBMApplication->setBusyCursor(FALSE); } void Browser::adjustScrollBar(Boolean top) { int min; int max; int value; int slider_size; int inc; int page_inc; // // The idea is to place the slide bar 1/2 a "slider_size" away from the end. // XtVaGetValues(this->vsb, XmNminimum, &min, XmNmaximum, &max, NULL); XmScrollBarGetValues(this->vsb, &value, &slider_size, &inc, &page_inc); if(top) { value = min + slider_size/2; if(this->page_start == 0) value = min; if(value > max - slider_size) value = max - slider_size; } else { value = max - slider_size/2 - slider_size; if(value > max - slider_size) value = max - slider_size; if(this->page_start == this->file_size - this->page_size) value = max - slider_size; if(value < min) value = min; } XmScrollBarSetValues(this->vsb, value, slider_size, inc, page_inc, True); } boolean Browser::nextPage() { float percentage_overlap; char *str = XmTextGetString(this->text); int i; int lines = 0; short visible_lines; XtVaGetValues(this->text, XmNrows, &visible_lines, NULL); for(i = STRLEN(str)-1; i >= 0; i--) { if(str[i] == '\n') lines++; if(lines == visible_lines) break; } percentage_overlap = (float)(STRLEN(str) - i)/(float)STRLEN(str); if(percentage_overlap > 50.0) percentage_overlap = 50.0; // // If we are already on the last page, forget it. // if( (this->page_start >= this->file_size - this->page_size) || (this->file_size <= this->page_size) ) { XtFree(str); return FALSE; } // // Next page // this->page_start += this->page_size; // // Back off visible_lines lines, or 50%, whichever is less // this->page_start -= (int)(percentage_overlap*this->page_size); // // Clamp to file size // if(this->page_start > this->file_size - this->page_size) this->page_start = this->file_size - this->page_size; this->loadBuffer(this->page_start); this->updateOffsets(0); XtFree(str); return TRUE; } boolean Browser::prevPage() { float percentage_overlap; char *str = XmTextGetString(this->text); int i; int lines = 0; short visible_lines; XtVaGetValues(this->text, XmNrows, &visible_lines, NULL); for(i = 0; i < STRLEN(str)-1; i++) { if(str[i] == '\n') lines++; if(lines == visible_lines) break; } percentage_overlap = (float)i/(float)STRLEN(str); if(percentage_overlap > 50.0) percentage_overlap = 50.0; if(this->page_start == 0) { XtFree(str); return FALSE; } // // Prev page // if(this->page_start > this->page_size) this->page_start -= this->page_size; else this->page_start = 0; // // Provide some overlap, unless this is the start of the file // if(this->page_start != 0) this->page_start += (int)(percentage_overlap*this->page_size); // // Clamp to start of file // if(this->page_start < 0) this->page_start = 0; this->loadBuffer(this->page_start); this->updateOffsets(0); XtFree(str); return TRUE; } void Browser::placeMark() { int i; int line_no; char mark_str[2]; mark_str[0] = '\001'; mark_str[1] = '\0'; theIBMApplication->setBusyCursor(TRUE); char *str = XmTextGetString(this->text); this->clearMark(); // // Calc where it should go // unsigned long pos = XmTextGetInsertionPosition(this->text); this->marker_pos = this->page_start + pos; line_no = 0; for(i = 0; i < pos; i++) { if(str[i] == '\n') line_no++; } this->marker_line_no = this->page_start_line_no + line_no; this->updateOffsets(pos); // // Save the marker character // this->marker_char[0] = str[pos]; this->ignore_cb = True; XmTextReplace(this->text, pos, pos+1, mark_str); this->ignore_cb = False; XmTextSetInsertionPosition(this->text, pos); XtFree(str); theIBMApplication->setBusyCursor(FALSE); } void Browser::clearMark() { unsigned long pos; if(!this->marker_char[0]) return; // // If the marker is on this page... // if( (this->marker_pos >= this->page_start) && (this->marker_pos < this->page_start + this->page_size) ) { pos = this->marker_pos - this->page_start; this->ignore_cb = True; XmTextReplace(this->text, pos, pos+1, this->marker_char); this->ignore_cb = False; } else { pos = XmTextGetInsertionPosition(this->text) - 1; } this->marker_pos = 0; this->marker_char[0] = '\0'; this->updateOffsets(pos+1); } void Browser::gotoMark() { this->gotoByte(this->marker_pos); } void Browser::gotoByte(unsigned long offset) { XmTextPosition pos; // // Is it on this page? // if( (offset > this->page_start) && (offset < (this->page_start + this->page_size)) ) { pos = offset - this->page_start; } else { if(offset > this->page_size/2) this->page_start = offset - this->page_size/2; else this->page_start = 0; if(this->page_start + this->page_size > this->file_size) this->page_start = this->file_size - this->page_size; this->loadBuffer(this->page_start); pos = offset - this->page_start; } XmTextShowPosition(this->text, pos); XmTextSetInsertionPosition(this->text, pos); } void Browser::gotoLineTopOffsetCB(Widget w, XtPointer client, XtPointer ) { Browser *browser = (Browser *)client; unsigned long line_num; theIBMApplication->setBusyCursor(TRUE); char *str = XmTextGetString(w); if(STRLEN(str) > 0) line_num = atoi(str); else return; browser->gotoLine(line_num); theIBMApplication->setBusyCursor(FALSE); } void Browser::gotoLineMarkOffsetCB(Widget w, XtPointer client, XtPointer) { Browser *browser = (Browser *)client; unsigned long line_num; theIBMApplication->setBusyCursor(TRUE); char *str = XmTextGetString(w); if(STRLEN(str) > 0) line_num = atoi(str) + browser->marker_line_no; else return; browser->gotoLine(line_num); theIBMApplication->setBusyCursor(FALSE); } void Browser::gotoLine(unsigned long line_num) { int i; unsigned long offset; unsigned long current_line_num; char *buf = (char *)CALLOC(this->page_size+1, sizeof(char)); if(line_num >= this->page_start_line_no) { offset = this->page_start; current_line_num = this->page_start_line_no; } else { offset = 0; current_line_num = 0; } // // Calc the line number offset of this position // while (offset < this->file_size) { this->from->seekg((streampos)offset); if(!this->from) { cerr << "Seekg failed in Browser::gotoLine()" << endl; break; } this->from->read(buf, this->page_size); if(!this->from) { cerr << "Read failed in Browser::gotoLine()" << endl; break; } if(this->from->fail()) this->from->clear(); // // Get the actual number of chars read in // int nread = this->from->gcount(); for(i = 0; i < nread; i++) { if(buf[i] == '\n') { current_line_num++; } if(current_line_num == line_num) break; } if(current_line_num == line_num) break; offset += nread; } // // Move to the start of the next line // i++; this->gotoByte(offset+i); delete buf; } void Browser::gotoByteTopOffsetCB(Widget w, XtPointer client, XtPointer) { Browser *browser = (Browser *)client; XmTextPosition pos; theIBMApplication->setBusyCursor(TRUE); char *str = XmTextGetString(w); if(STRLEN(str) > 0) { pos = atoi(str); } else { theIBMApplication->setBusyCursor(FALSE); return; } if( !((pos >= browser->page_start) && (pos < (browser->page_start + browser->page_size))) ) { browser->page_start = pos - browser->page_size/2; if(browser->page_start + browser->page_size > browser->file_size) browser->page_start = browser->file_size - browser->page_size; if(browser->page_start < 0) browser->page_start = 0; browser->loadBuffer(browser->page_start); } pos = pos - browser->page_start; XmTextShowPosition(browser->text, pos); XmTextSetInsertionPosition(browser->text, pos); theIBMApplication->setBusyCursor(FALSE); } void Browser::gotoByteStartOffsetCB(Widget w, XtPointer client, XtPointer ) { Browser *browser = (Browser *)client; XmTextPosition pos; theIBMApplication->setBusyCursor(TRUE); char *str = XmTextGetString(w); if(STRLEN(str) > 0) { pos = atoi(str); } else { theIBMApplication->setBusyCursor(FALSE); return; } char *text_str = XmTextGetString(browser->text); XmTextPosition current_pos = XmTextGetInsertionPosition(browser->text); long line_start = current_pos; // // Search backwards for the start of the line // while (line_start >= 0) { if(text_str[line_start] == '\n') break; line_start--; } line_start++; XmTextShowPosition(browser->text, line_start + pos); XmTextSetInsertionPosition(browser->text, line_start + pos); theIBMApplication->setBusyCursor(FALSE); } void Browser::gotoByteMarkOffsetCB(Widget w, XtPointer client, XtPointer) { Browser *browser = (Browser *)client; XmTextPosition pos; theIBMApplication->setBusyCursor(TRUE); char *str = XmTextGetString(w); if(STRLEN(str) > 0) { pos = atoi(str) + browser->marker_pos; } else { theIBMApplication->setBusyCursor(FALSE); return; } if(!(pos >= browser->page_start) && (pos < (browser->page_start + browser->page_size)) ) { browser->page_start = browser->marker_pos - browser->page_size/2; if(browser->page_start + browser->page_size > browser->file_size) browser->page_start = browser->file_size - browser->page_size; if(browser->page_start < 0) browser->page_start = 0; browser->loadBuffer(browser->page_start); } pos = pos - browser->page_start; XmTextShowPosition(browser->text, pos); XmTextSetInsertionPosition(browser->text, pos); theIBMApplication->setBusyCursor(FALSE); } void Browser::firstPage() { this->loadBuffer(0); XmTextSetInsertionPosition(this->text, 0); this->updateOffsets(0); } void Browser::lastPage() { unsigned long offset; if(this->page_size > this->file_size) offset = 0; else offset = this->file_size - this->page_size; this->loadBuffer(offset); // // Put the slider at the end. // int max; int value; int slider_size; int inc; int page_inc; XtVaGetValues(this->vsb, XmNmaximum, &max, NULL); XmScrollBarGetValues(this->vsb, &value, &slider_size, &inc, &page_inc); XmScrollBarSetValues(this->vsb, max-slider_size, slider_size, inc, page_inc, True); this->updateOffsets(0); } void Browser::motionCB(Widget , XtPointer client, XtPointer call) { XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)call; Browser *browser = (Browser *)client; browser->updateOffsets((unsigned long)cbs->newInsert); } // // Note:new_pos is the byte offset from the start of the CURRENT page! // void Browser::updateOffsets(unsigned long new_pos) { char string[256]; unsigned long i; int start_of_line_offset; unsigned long position = this->page_start + new_pos; long line_no = this->page_start_line_no; char *str = XmTextGetString(this->text); // // Replace the marker char with the original char in case the original // was a newline. // if( (this->marker_pos >= this->page_start) && (this->marker_pos < this->page_start + this->page_size) && (this->marker_char[0]) ) { str[this->marker_pos - this->page_start] = this->marker_char[0]; } start_of_line_offset = 0; for(i = 0; i < new_pos; i++) { start_of_line_offset++; if(str[i] == '\n') { start_of_line_offset = 0; line_no++; } } // // Number of lines from top of file // sprintf(string, "%d", line_no); XmTextSetString(this->line_top_offset, string); // // Number of bytes from top of file // sprintf(string, "%d", position); XmTextSetString(this->byte_top_offset, string); // // Number of bytes from start of line // sprintf(string, "%d", start_of_line_offset); XmTextSetString(this->byte_start_offset, string); // // Number of bytes from marker // long marker_byte_offset = position - this->marker_pos; sprintf(string, "%d", marker_byte_offset); XmTextSetString(this->byte_mark_offset, string); // // Number of lines from marker // // // If the marker is on a prior page... // if(this->marker_pos < this->page_start) { line_no = this->page_start_line_no; for(i = 0; i < new_pos; i++) { if(str[i] == '\n') line_no++; } line_no = line_no - this->marker_line_no; } // // If the marker is on a subsequent page... // else if(this->marker_pos >= this->page_start + this->page_size) { line_no = this->page_start_line_no; for(i = 0; i < new_pos; i++) { if(str[i] == '\n') line_no++; } line_no = line_no - this->marker_line_no; } // // If the marker is on this page... // else if( (this->marker_pos >= this->page_start) && (this->marker_pos < this->page_start + this->page_size) ) { unsigned long start; unsigned long end; line_no = 0; unsigned long marker_pos = this->marker_pos - this->page_start; if(marker_pos > new_pos) { start = new_pos; end = marker_pos; } else { start = marker_pos; end = new_pos; } for(i = start; i < end; i++) { if(str[i] == '\n') { if(marker_pos > new_pos) line_no--; else line_no++; } } } sprintf(string, "%d", line_no); XmTextSetString(this->line_mark_offset, string); XtFree(str); } void Browser::output_formatCB(Widget , XtPointer , XtPointer ) { #ifdef Comment UIVDATA *uivdata; XtVaGetValues(w, XmNuserData, &uivdata, NULL); set_watch(uivdata->text); if(w == uivdata->ascii_w) uivdata->output_format = ASCII; else if(w == uivdata->hex8_w) uivdata->output_format = HEX8; else if(w == uivdata->hex16_w) uivdata->output_format = HEX16; else if(w == uivdata->hex32_w) uivdata->output_format = HEX32; else if(w == uivdata->float_w) uivdata->output_format = FLOAT; else if(w == uivdata->double_w) uivdata->output_format = DOUBLE; setPageNum(uivdata, uivdata->page_num); reset_cursor(uivdata->text); #endif } void Browser::integerMVCB(Widget , XtPointer clientData, XtPointer call) { Browser *browser = (Browser *) clientData; XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)call; int i; if(cbs->text->ptr == NULL) //backspace return; for(i = 0; i < cbs->text->length; i++) if(!(isdigit(cbs->text->ptr[i]) || cbs->text->ptr[i] == '-')) { cbs->doit = False; return; } } boolean Browser::openFile(char *filenm) { struct stat statb; char title[512]; this->from = new ifstream(filenm); if(!this->from) { WarningMessage("File open failed for file %s", filenm); return FALSE; } if(stat(filenm, &statb) == -1) { // stat failed return FALSE; } this->file_size = statb.st_size; // // Clear any existing mark // this->marker_pos = 0; this->marker_char[0] = '\0'; this->page_start = 0; this->page_start_line_no = 0; this->loadBuffer(0); title[0] = '\0'; strcat(title, "File Browser: "); strcat(title, filenm); this->setWindowTitle(title); return TRUE; } void Browser::loadBuffer(unsigned long file_offset) { char *buf = (char *)CALLOC(this->page_size+1, sizeof(char)); char *linebuf = (char *)CALLOC(this->page_size+1, sizeof(char)); int i; // // HACK! // if(this->from->fail()) this->from->clear(); // // Read in a buffer // this->from->seekg((streampos)file_offset); if(!this->from) { cerr << "Seekg failed in Browser::loadBuffer()" << endl; } this->from->read(buf, this->page_size); if(!this->from) { cerr << "Read failed in Browser::loadBuffer()" << endl; } if(this->from->fail()) this->from->clear(); this->page_start = file_offset; // // Get the actual number of chars read in // int nread = this->from->gcount(); // // And NULL terminate the string // buf[nread] = '\0'; // // Convert non-printing chars to '.' for(i = 0; i < nread; i++) { if(((!isprint(buf[i])) && (buf[i] != '\n') && (buf[i] !='\t') && (buf[i] != ' ')) || (!isascii(buf[i]))) buf[i] = '.'; } // // If the marker is on this page, change the character // if( (this->marker_pos >= this->page_start) && (this->marker_pos < this->page_start + this->page_size) && this->marker_char[0] ) { unsigned long pos = this->marker_pos - this->page_start; buf[pos] = '\001'; } // // Give it to the text widget // this->ignore_cb = True; XmTextSetString(this->text, buf); this->ignore_cb = False; // // Calc the line number offset of this position // this->from->seekg((streampos)0); if(!this->from) { cerr << "Seekg failed in Browser::loadBuffer()" << endl; } int offset = 0; this->page_start_line_no = 0; while (offset < file_offset) { this->from->getline(linebuf, this->page_size); if(!this->from) { cerr << "Getline failed in Browser::gotoLine()" << endl; break; } // Add one, since getline does not get the '\n' offset += STRLEN(linebuf)+1; if(offset < file_offset) this->page_start_line_no++; } FREE(buf); FREE(linebuf); } void Browser::postSearchDialog() { if(!this->searchDialog) this->searchDialog = new SearchDialog(this->getRootWidget(), this); this->searchDialog->post(); } void Browser::unpostSearchDialog() { this->searchDialog->unmanage(); } void Browser::searchForward(char *text) { boolean wrap = FALSE; boolean found = FALSE; char *buf = (char *)CALLOC(this->page_size+1, sizeof(char)); int i; long start_pos = 1 + XmTextGetInsertionPosition(this->text) + this->page_start; if(start_pos >= this->file_size) start_pos = 0; long pos = start_pos; theIBMApplication->setBusyCursor(TRUE); #if defined(HAVE_REGCOMP) char *search_for = (char *)regcomp(text); ASSERT(search_for != NULL); #elif defined(HAVE_REGCMP) char *search_for = regcmp(text, NULL); ASSERT(search_for != NULL); #elif defined(HAVE_RE_COMP) char *error_string = re_comp(text); if(error_string) WarningMessage("Couldn't compile regular expression! %s", error_string); #endif while(!found && !wrap || pos < start_pos) { // // Read in a buffer // this->from->seekg((streampos)pos); if(!this->from) { cerr << "Seekg failed in Browser::searchForward()" << endl; } this->from->read(buf, this->page_size); if(!this->from) { cerr << "Read failed in Browser::searchForward()" << endl; } if(this->from->fail()) this->from->clear(); // // Get the actual number of chars read in // int nread = this->from->gcount(); // // And NULL terminate the string // buf[nread] = '\0'; // // Convert non-printing chars to '.' // for(i = 0; i < nread; i++) { if(((!isprint(buf[i])) && (buf[i] != '\n') && (buf[i] !='\t') && (buf[i] != ' ')) || (!isascii(buf[i]))) buf[i] = '.'; } int offset; #if defined(HAVE_REGCOMP) int i; for (i = 0; i < STRLEN(buf); i++) if (! regexec((regexp *)search_for, buf[i])) break; if (i) { offset = i - 1; found = 1; } #elif defined(HAVE_REGCMP) extern char *__loc1; if (regex(search_for, buf)) { offset = __loc1 - buf; found = 1; } #elif defined(HAVE_RE_COMP) int i; for (i = 0; i < STRLEN(buf); i++) if (! re_exec(buf + i)) break; if (i) { offset = i - 1; found = 1; } #else char *s; s = strstr(text, buf); if (s) { offset = s - buf; found = 1; } #endif if(found) { this->gotoByte(offset); found = TRUE; break; } else { int nread = this->from->gcount(); // // "Loop" around on the search // if(nread == this->page_size) { pos += (int)(0.95*this->page_size); } else { // If we have already wrapped, break out. if(wrap) break; else pos = 0; wrap = TRUE; } } } if(!found) WarningMessage("Pattern not found"); #if defined(HAVE_RECOMP) || defined(HAVE_REGCMP) free(search_for); #endif FREE(buf); theIBMApplication->setBusyCursor(FALSE); } void Browser::searchBackward(char *text) { boolean wrap = FALSE; boolean last_buf = FALSE; boolean found = FALSE; char *buf = (char *)CALLOC(this->page_size+1, sizeof(char)); long start_pos = XmTextGetInsertionPosition(this->text) + this->page_start; if(start_pos < 0) start_pos = this->file_size; long pos = start_pos; long prev_pos; long bufstart; theIBMApplication->setBusyCursor(TRUE); #if defined(HAVE_REGCOMP) char *search_for = (char *)regcomp(text); ASSERT(search_for != NULL); #elif defined(HAVE_REGCMP) char *search_for = regcmp(text, NULL); ASSERT(search_for != NULL); #elif defined(HAVE_RE_COMP) char *error_string = re_comp(text); if(error_string) WarningMessage("Couldn't compile regular expression! %s", error_string); #endif bufstart = start_pos - this->page_size; if(bufstart < 0) bufstart = 0; while(!wrap || pos >= start_pos) { // // Read in a buffer // this->from->seekg((streampos)bufstart); if(!this->from) { cerr << "Seekg failed in Browser::searchBackward()" << endl; } this->from->read(buf, this->page_size); if(!this->from) { cerr << "Read failed in Browser::searchBackward()" << endl; } if(this->from->fail()) this->from->clear(); // // Get the actual number of chars read in // int nread = this->from->gcount(); // // And NULL terminate the string // buf[nread] = '\0'; // // Convert non-printing chars to '.' // int i; for(i = 0; i < nread; i++) { if(((!isprint(buf[i])) && (buf[i] != '\n') && (buf[i] !='\t') && (buf[i] != ' ')) || (!isascii(buf[i]))) buf[i] = '.'; } int offset; #if defined(HAVE_REGCOMP) if (regexec((regexp *)search_for, buf)) { found = 1; for (i = STRLEN(buf)-1; i >= 0; i--) if (! regexec((regexp *)search_for, buf[i])) break; offset = i + 1; } #elif defined(HAVE_REGCMP) if (regex(search_for, buf)) { found = 1; for (i = STRLEN(buf)-1; i >= 0; i--) if (! regex(search_for, buf[i])) break; offset = i + 1; } #elif defined(HAVE_RE_COMP) if (re_exec(buf)) { found = 1; for (i = STRLEN(buf)-1; i >= 0; i--) if (! re_exec(buf + i)) break; offset = i + 1; } #else int i; if (strstr(text, buf)) { found = 1; for (i = STRLEN(buf)-1; i >= 0; i--) if (! strstr(text, buf[i])) break; offset = i + 1; } #endif pos = bufstart + offset; if(!wrap) { if(pos >= start_pos) { break; } else { prev_pos = pos; found = TRUE; } } else { prev_pos = pos; found = TRUE; } if(!found) { // // "Loop" around on the search // if(bufstart != 0) { bufstart -= (int)(0.95*this->page_size); if(bufstart < 0) bufstart = 0; if(wrap) { if(bufstart < start_pos) { if(last_buf) break; bufstart = start_pos; last_buf = TRUE; } } } else { bufstart = this->file_size - this->page_size; if(bufstart < 0) bufstart = 0; pos = this->file_size; if(wrap) break; wrap = TRUE; } } else { this->gotoByte(prev_pos); break; } } if(!found) WarningMessage("Pattern not found"); #ifdef REGCMP_EXISTS free(search_for); #endif FREE(buf); theIBMApplication->setBusyCursor(FALSE); } void Browser::AddHelpCallbacks(Widget w) { // // Add the callback for this one... // XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)Browser_HelpCB, (XtPointer)NULL); // // Add the callback for any descendants // if(XtIsComposite(w)) { WidgetList children; Cardinal nchild; int i; XtVaGetValues(w, XmNchildren, &children, XmNnumChildren, &nchild, NULL); for(i = 0; i < nchild; i++) { Browser::AddHelpCallbacks(children[i]); } } } extern "C" void Browser_HelpCB(Widget w, XtPointer, XtPointer) { theApplication->helpOn(XtName(w)); }