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.