This is ColumnMatrix.m in view mode; [Download] [Up]
#import "ColumnMatrix.h" #import "Article.h" #import "MatrixSet.h" #include <assert.h> #import "instr.h" #import "regexpr.h" #import "MatrixScroller.h" @implementation ColumnMatrix #define MOD(a,b) ((a)<0)? ((a)+(b))%(b) : (a)%(b) - awakeFromNib { buttonTitle=NXCopyStringBuffer([selectionButton title]); return self; } - free { if(myVisibleCellList!=nil) [myVisibleCellList free]; free(buttonTitle); return [super free]; } - initFrame:(const NXRect *)frameRect { NXSize newIntercell = {0.0, 0.0}; NXSize newCellSize; [super initFrame:frameRect mode:NX_LISTMODE prototype:[Cell new] numRows:0 numCols:0]; [protoCell setBordered:FALSE]; [protoCell setAlignment:NX_LEFTALIGNED]; newCellSize.height=16.0; newCellSize.width = frameRect->size.width; [self setCellSize:&newCellSize]; [self setIntercell:&newIntercell]; [self setBackgroundGray:NX_LTGRAY]; [self setAutoscroll:TRUE]; return self; } - superviewSizeChanged:(const NXSize*)oldSize { NXSize newCellSize; NXRect aRect; [super superviewSizeChanged:oldSize]; [superview getFrame:&aRect]; newCellSize.width = aRect.size.width; newCellSize.height = cellSize.height; [self setCellSize:&newCellSize]; [self sizeToCells]; return self; } - scrollUp { NXSize visibleSize; NXRect theUpperRect; [[[self superview] superview] getContentSize:&visibleSize]; NXSetRect(&theUpperRect,0.0,0.0,visibleSize.width,visibleSize.height); [self scrollRectToVisible:&theUpperRect]; return self; } - loadMatrix { int i,j; for(i=numRows-1;i>=0;i--) [self removeRowAt:i andFree:NO]; [self makeVisibleCellList:self]; j=[myVisibleCellList count]; for(i=0;i<j;i++) [self addRow]; [self sizeToCells]; [self clearSelectedCell]; return self; } - reloadMatrix { List *selList; int lastCellPos=NX_NOT_IN_LIST; int i,j; selList=[self getSelectedCells:nil]; [self loadMatrix]; if(selList==nil) return self; j=[selList count]; for(i=0;i<j;i++){ id aCell=[selList objectAt:i]; if([aCell isTaged]==TRUE){ int pos=[cellList indexOf:aCell]; if(pos!=NX_NOT_IN_LIST){ [self setSelectionFrom:pos to:pos anchor:pos lit:YES]; lastCellPos=pos; } } } [selList free]; if(lastCellPos!=NX_NOT_IN_LIST) [self scrollCellToVisible:lastCellPos upperOffset:1.5 lowerOffset:1.5]; return self; } - setMatrixCellList:(List *)aList { myCellList=aList; return self; } - makeVisibleCellList:sender { int i,j; if(myVisibleCellList!=nil) [myVisibleCellList free]; myVisibleCellList=[[List alloc] init]; j=[myCellList count]; for(i=0;i<j;i++){ id aCell=[myCellList objectAt:i]; if([aCell isTaged]==TRUE) [myVisibleCellList addObject:aCell]; } return self; } - makeCellAt:(int)row :(int)col { assert(col==0); return [myVisibleCellList objectAt:row]; } - (id)selectionButton { return selectionButton; } - removeInvalidCell:aCell { return [self removeInvalidCell:aCell andUpdate:YES]; } - removeInvalidCell:aCell andUpdate:(BOOL)update { int pos=[cellList indexOf:aCell]; [myCellList removeObject:aCell]; [myVisibleCellList removeObject:aCell]; if(pos==NX_NOT_IN_LIST){ NX_ASSERT(pos==NX_NOT_IN_LIST,"Internal DS mismatch"); return self; } [self removeRowAt:pos andFree:YES]; if(update==YES) [self update]; return self; } - update { [self reloadMatrix]; [self display]; [mySet sync]; [NXApp updateWindows]; return self; } - setButtonTitle:(const char *)title { free(buttonTitle); [selectionButton setTitle:title]; buttonTitle=NXCopyStringBuffer(title); return self; } - _delayedUpdate:sender { [selectionButton setTitle:buttonTitle]; return self; } - updateButtonTitle { [self perform:@selector(_delayedUpdate:) with:self afterDelay:0.0 cancelPrevious:TRUE]; return self; } - (List *)getCurrSelections { return [self getSelectedCells:nil]; } - currSelection { return [self selectedCell]; } - (BOOL)selectNextCell:(int)delta { int i,j; id cSel; NX_ASSERT(((delta==1) || (delta==-1)),"Wrong parameter selectNextCell"); j=[myVisibleCellList count]; if(j==0) return FALSE; if((cSel=[mySet currentSelection])!=nil){ i=[myVisibleCellList indexOf:cSel]; NX_ASSERT(i!=NX_NOT_IN_LIST,"Internal DS mismatch"); if((delta>0) && (i==j-1)) return FALSE; //last article else if((delta<0) && (i==0)) return FALSE; //first article } else if(delta>0) i=-1; else i=j; [self selectCellAt:i+delta :0]; [self scrollCellToVisible:i+delta upperOffset:((delta==-1)? 1.5:0.0) lowerOffset:((delta==1)? 1.5:0.0)]; [self sendAction]; return TRUE; } - selectAll:sender { [super selectAll:sender]; [self sendAction]; return self; } - mySet { return mySet; } //------------------------- // searchable text protocol //------------------------- - (oneway void)makeSelectionVisible { id selCell=[self selectedCell]; if(selCell!=nil) [self scrollCellToVisible:[[self cellList] indexOf:selCell] upperOffset:(findNext? 0.0:1.5) lowerOffset:(findNext? 1.5:0.0)]; } - (int)replaceAll:(const char *)pattern with:(const char *)replacement mode:(SearchMode)mode regexpr:(BOOL)regexpr cases:(BOOL)cases { return SEARCH_CANNOT_WRITE; } - (oneway void)replaceSelection:(const char *)replacement { } - (const char *)stringValueForCellAt:(int)index { return [[self cellAt:index :0] stringValue]; } - (int)searchFor:(const char *)pattern mode:(SearchMode)mode reverse:(BOOL)rev regexpr:(BOOL)regexpr cases:(BOOL)cases position:(out int *)pos size:(out int *)size { int rows,cols,i; int s_pos; int fStart,fEnd; int delta; unsigned char fm[256], tr[256]; struct re_pattern_buffer rpat; findNext=!rev; s_pos=-2; fStart=fEnd=-2; [self getNumRows:&rows numCols:&cols]; if(rows==0) return 0; // find first selected cell for(i=0;i<rows;i++) if([[self cellAt:i :0] state]){ s_pos=i; break; } if(!rev){ if(s_pos<0){ fStart=0; fEnd=rows; } else{ fStart=s_pos+1; fEnd=s_pos+rows; } } else{ if(s_pos<0){ fStart=rows-1; fEnd=-1; } else{ fStart=s_pos-1+rows; fEnd=s_pos; } } delta= rev? -1:1; if(regexpr){ char *str; int i; memset(&rpat, 0, sizeof(rpat)); for(i=256; i--;) tr[i] = i; if(!cases) for(i='A'; i<='Z'; i++) tr[i] = i-'A'+'a'; rpat.translate = tr; rpat.fastmap = fm; str = re_compile_pattern((char *)pattern,strlen(pattern), &rpat); if (str!=NULL) return (strcmp(str, "Out of memory")?SEARCH_INVALID_REGEXPR:SEARCH_INTERNAL_ERROR); } for(;fStart!=fEnd;fStart+=delta){ int index=fStart%rows; const char *result=NULL; const char *cellString=[self stringValueForCellAt:index]; if(regexpr){ int l=strlen(cellString); int p=re_search_pattern(&rpat,(char *)cellString,l,0,l,0); if(p==-2) return SEARCH_INTERNAL_ERROR; result= (p==-1)? NULL : cellString; } else result=instr(cellString,pattern,cases); if(result!=NULL){ *pos=index; *size=1; return 1; } } return 0; } - (oneway void)selectTextFrom:(int)start to:(int)end { int rows,cols; if(start<=end){ if(start==end){ [self selectCellAt:-1 :-1]; [self sendAction]; } else{ [self getNumRows:&rows numCols:&cols]; if(end<=rows){ [self selectCellAt:start :0]; [self sendAction]; } } } } - (void)writeSelectionToPasteboard:(in Pasteboard *)pboard asType:(in NXAtom)type { id aList =[self getCurrSelections]; if([aList count]==1){ const char *sval=[[aList objectAt:0] stringValue]; [pboard declareTypes:&type num:1 owner:NULL]; [pboard writeType:type data:sval length:strlen(sval)]; } [aList free]; return; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.