#import "Aprica.h"
#ifdef GNU_RUNTIME
#import <objc/objc-api.h>
#else
#import <objc/objc-class.h>
#endif
// Aprica2
// copyright Pirmin Braun 1997-2007 - pirmin@pirmin.de
// all Rights reserved;
#ifndef GNUSTEP
#import <Python26/Python.h>
@implementation Application (Python)
- (void)py_initialize;
{ Py_Initialize();
}
- (void)py_finalize;
{ Py_Finalize();
}
- (int)pyRun_simpleString:(NSString *)s;
{ return PyRun_SimpleString([s lossyCString]);
}
@end
#endif
@implementation Application (Admin)
- (void)createTransFor:(NSString *)ps;
{ NSString *s,*sql,*result;
PBEO *eo;
s = [ps stringWithoutLeadingWhiteSpace];
s = [s stringWithoutTrailingWhiteSpace]; // Bug in MySQL:Trailing white space geht beim speichern verloren
if(!FILLED(s))return;
sql = [NSSWF @"select text0 from translationsm where text0 = BINARY '%@'",[s mysqlEscapedString]];
result = singleValueSQL(sql);
if(!FILLED(result)){ eo = NEW_EO(@"translationsm");
[eo tvfk(s,@"text0")];
[eo tvfk(@"J",@"collect_trans")];
INSRT(eo);
}else{ sql = [NSSWF @"update translationsm set collect_trans = 'J' where text0 = BINARY '%@'",[s mysqlEscapedString]];
SQL(sql);
}
}
- (void)convertWithEnumerator:(NSDirectoryEnumerator *)e extension:(NSString *)extension path:(NSString *)path;
{ NSString *file,*content;
NSAutoreleasePool *pool = nil;
while ((file = [e nextObject])) { pool = [[NSAutoreleasePool alloc]init];
if ([[file pathExtension] iE:extension] && ![file rangeOfString:@".svn"].length){ NSString *fn = [NSSWF @"%@%@/%@",MANDANTPATH,path,[file stringWithForwardSlashes]];
content = [NSSWCOF fn];
if(![content WTF:fn])LOG(([NSSWF @"FAILED:%@",fn]));
}
[pool release];
}
}
- (void)convertToUTF8;
{// alle Texte, die von Hand editiert sein koennen, in UTF8 ohne BOM konvertieren
NSDirectoryEnumerator *e;
e = [[NSFileManager defaultManager]enumeratorAtPath:[NSSWF @"%@/Scripts",MANDANTPATH]];
[self convertWithEnumerator:e extension:@"script" path:@"/Scripts"];
e = [[NSFileManager defaultManager]enumeratorAtPath:[NSSWF @"%@/Resources/Hilfe",MANDANTPATH]];
[self convertWithEnumerator:e extension:@"txt" path:@"/Resources/Hilfe"];
e = [[NSFileManager defaultManager]enumeratorAtPath:[NSSWF @"%@/Templates",MANDANTPATH]];
[self convertWithEnumerator:e extension:@"htmlwod" path:@"/Templates"];
e = [[NSFileManager defaultManager]enumeratorAtPath:[NSSWF @"%@/Druck",MANDANTPATH]];
[self convertWithEnumerator:e extension:@"cpdf" path:@"/Druck"];
}
- (void)instantiateAllModules;
{ NSArray *a = [[_APP availableBundles]sortedArrayUsingKeyOrderArray:[NSArray soaFrom:@"name"]];
int i,j;
// alle bundles instantiieren und rendern; fuellt damit transDict
#warning todo: Register durchsteppen und damit portlets aktivieren
for(i=0,j=[a count];i<j;i++){ PBWOBundle *b = [a oai:i];
PBWOEditor *pbe;
NSAutoreleasePool *pool;
WOResponse *resp;
pool = [[NSAutoreleasePool alloc]init];
resp = [[[WOResponse alloc]init]autorelease];
NS_DURING;
pbe = MODUL([b name]);
LOGS([b name]);
[pbe _template]; //erzwingt laden von htmlwod
[[currentComponent context]setCurrentComponent:pbe];
[pbe performInitialSearch];
[pbe appendToResponse:resp inContext:[currentComponent context]];
[pbe saveLif];
NS_HANDLER;
LOGS_Ex(([NSSWF @"ging schief:%@",[b name]]));
NS_ENDHANDLER;
[pool release];
}
[[currentComponent context]setCurrentComponent:currentComponent];
}
- (void)stripCRInDir:(NSString *)dir suffix:(NSString *)suffix;
{ NSArray *a = [myFM directoryDeepContentsAtPath:[NSSWF @"%@/%@",MANDANTPATH,dir] suffixes:[NSArray arrayWithObject:suffix] skips:[NSArray arrayWithObject:@".svn"] fullName:YES];
int i,j;
for(i=0,j=[a count];i<j;i++){ NSString *fn = [NSSWF @"%@/%@/%@",MANDANTPATH,dir,[[a oai:i]stringWithForwardSlashes]];
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
[[[NSSWCOF fn] stringWithout0xD] WTF:fn];
[pool release];
}
}
- (void)stripCR;
{// CR machen immer wieder Probleme in .idm .lif .script .cpdf beim Mergen und bei svn; daher weg damit
[self stripCRInDir:@"LayoutsUsers" suffix:@"lif"];
[self stripCRInDir:@"Scripts" suffix:@"script"];
[self stripCRInDir:@"Druck" suffix:@"cpdf"];
[self stripCRInDir:@"Templates" suffix:@"htmlwod"];
[self stripCRInDir:@"Resources/Hilfe" suffix:@"txt"];
}
- (void)logObsoleteLifs;
{ NSArray *a = [myFM directoryContentsAtPath:[NSSWF @"%@/%@",MANDANTPATH,@"LayoutsUsers/Administrator"] suffixes:[NSArray arrayWithObject:@".lif"] skips:[NSArray arrayWithObject:@".svn"] fullName:NO];
int i,j;
for(i=0,j=[a count];i<j;i++){ NSString *s = [a oai:i];
if(![_APP bundleWithName:s])LOG(s);
}
}
- (NSString *)processFileLogiTrans:(NSString *)s;
{ NSArray *a = [s componentsSeparatedByString:@"\n"];
int i,j;
LMA;
for(i=0,j=[a count];i<j;i++){ NSString *line = [a oai:i];
NSRange myRange;
myRange = [line rangeOfString:@"logi \""];
if(myRange.length){ NSMutableString *ms = [NSMutableString stringWithString:line];
[ms replaceCharactersInRange:myRange withString:@"logi <trans>\""];
[lma addObject:ms];
continue;
}
myRange = [line rangeOfString:@"logi '"];
if(myRange.length){ NSMutableString *ms = [NSMutableString stringWithString:line];
[ms replaceCharactersInRange:myRange withString:@"logi <trans>'"];
[lma addObject:ms];
continue;
}
[lma addObject:line];
}
return [lma componentsJoinedByString:@"\n"];
}
- (void)logiTransWithEnumerator:(NSDirectoryEnumerator *)e extension:(NSString *)extension path:(NSString *)path;
{ NSString *file,*content;
NSAutoreleasePool *pool = nil;
while ((file = [e nextObject])) { pool = [[NSAutoreleasePool alloc]init];
if ([[file pathExtension] iE:extension] && ![file rangeOfString:@".svn"].length){ NSString *fn = [NSSWF @"%@/%@",path,[file stringWithForwardSlashes]];
content = [NSSWCOF fn];
content = [self processFileLogiTrans:content];
if(![content WTF:fn])LOG(([NSSWF @"FAILED:%@",fn]));
}
[pool release];
}
}
- (void)logiTrans;
{// logi " zu logi <trans>"
// logi ' zu logi <trans>'
NSDirectoryEnumerator *e;
NSString *path;
path = [NSSWF @"%@/Scripts",MANDANTPATH];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self logiTransWithEnumerator:e extension:@"script" path:path];
path = [NSSWF @"%@/Druck",MANDANTPATH];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self logiTransWithEnumerator:e extension:@"cpdf" path:path];
}
- (void)processCollectTrans:(NSString *)s;
{ NSRange r,r1;
NSString *s1;
s = [s stringWithout0xD];
r = [s rangeOfString:@"<trans>"];
while(r.length){ s = [s substringFromIndex:r.location + r.length];
if([s hasSecurePrefix:@"\""]){ s = [s substringFromIndex:1];
r = [s rangeOfString:@"\n"];
}else{ if([s hasSecurePrefix:@"'"]){ s = [s substringFromIndex:1];
}else{ if([s hasSecurePrefix:@"$"]){ // keine Scriptvariablen r = [s rangeOfString:@"<trans>"];
continue;
}
}
r = [s rangeOfString:@","];
r1 = [s rangeOfString:@"\n"];
if(r1.length && r.length){ if(r1.location < r.location)r = r1;
}else{ if(!r.length)r=r1;
}
}
if(!r.length)r.location=[s length]-1;
s1 = [s substringToIndex:r.location];
if(![lookup ofk:s1]){ [lookup setObject:@"x" forKey:s1];
LOG(([NSSWF @">>>>>>>>>>>> %@",s1]));
[self createTransFor:s1];
}
s = [s substringFromIndex:r.location + r.length];
r = [s rangeOfString:@"<trans>"];
}
}
- (void)collectTransWithEnumerator:(NSDirectoryEnumerator *)e extension:(NSString *)extension path:(NSString *)path;
{ NSString *file,*content;
NSAutoreleasePool *pool = nil;
while ((file = [e nextObject])) { pool = [[NSAutoreleasePool alloc]init];
if ([[file pathExtension] iE:extension] && ![file rangeOfString:@".svn"].length){ NSString *fn = [NSSWF @"%@/%@",path,[file stringWithForwardSlashes]];
content = [NSSWCOF fn];
LOG(fn);
[self processCollectTrans:content];
}
[pool release];
}
}
- (void)processCollectHTMLTrans:(NSString *)s;
{ NSRange r;
s = [s stringWithout0xD];
r = [s rangeOfString:@"<|"];
while(r.length){ s = [s substringFromIndex:r.location + r.length];
r = [s rangeOfString:@"|>"];
if(r.length){ NSString *s1 = [s substringToIndex:r.location];
if(![lookup ofk:s1]){ [lookup setObject:@"x" forKey:s1];
LOG(([NSSWF @">>>>>>>>>>>> %@",s1]));
[self createTransFor:s1];
}
s = [s substringFromIndex:r.location + r.length];
}
r = [s rangeOfString:@"<|"];
}
}
- (void)collectHTMLTransWithEnumerator:(NSDirectoryEnumerator *)e extension:(NSString *)extension path:(NSString *)path;
{ NSString *file,*content;
NSAutoreleasePool *pool = nil;
while ((file = [e nextObject])) { pool = [[NSAutoreleasePool alloc]init];
if ([[file pathExtension] iE:extension] && ![file rangeOfString:@".svn"].length){ NSString *fn = [NSSWF @"%@/%@",path,[file stringWithForwardSlashes]];
content = [NSSWCOF fn];
LOG(fn);
[self processCollectHTMLTrans:content];
}
[pool release];
}
}
- (void)processCollectObjCTrans:(NSString *)s;
{ NSRange r;
r = [s rangeOfString:@"TRANSLATION(@\""];
while(r.length){ s = [s substringFromIndex:r.location + r.length];
r = [s rangeOfString:@"\")"];
if(r.length){ NSString *s1 = [s substringToIndex:r.location];
if(![lookup ofk:s1]){ [lookup setObject:@"x" forKey:s1];
LOG(([NSSWF @">>>>>>>>>>>> %@",s1]));
[self createTransFor:s1];
}
s = [s substringFromIndex:r.location + r.length];
}
r = [s rangeOfString:@"TRANSLATION(@\""];
}
}
- (void)collectObjCTransWithEnumerator:(NSDirectoryEnumerator *)e extension:(NSString *)extension path:(NSString *)path;
{ NSString *file,*content;
NSAutoreleasePool *pool = nil;
while ((file = [e nextObject])) { pool = [[NSAutoreleasePool alloc]init];
if ([[file pathExtension] iE:extension] && ![file rangeOfString:@".svn"].length){ NSString *fn = [NSSWF @"%@/%@",path,[file stringWithForwardSlashes]];
content = [NSSWCOF fn];
LOG(fn);
[self processCollectObjCTrans:content];
}
[pool release];
}
}
- (void)processCollectLIFTrans:(NSString *)s;
{// a|200|Detail-Ansicht betrag_brutto
NSArray *a = [s componentsSeparatedByString:@"\n"];
int i,j;
for(i=0,j=[a count];i<j;i++){ NSArray *a2 = [[[[a oai:i] componentsSeparatedByString:@"\t"] firstObject]componentsSeparatedByString:@"|"];
NSString *s1;
if([a2 count]==3){ s1 = [a2 oai:2];
if([lookup ofk:s1])continue;
[lookup setObject:@"x" forKey:s1];
LOG(([NSSWF @">>>>>>>>>>>> %@",s1]));
[self createTransFor:s1];
}
}
}
- (void)collectLIFTransWithEnumerator:(NSDirectoryEnumerator *)e extension:(NSString *)extension path:(NSString *)path;
{ NSString *file,*content;
NSAutoreleasePool *pool = nil;
while ((file = [e nextObject])) { pool = [[NSAutoreleasePool alloc]init];
if ([[file pathExtension] iE:extension] && ![file rangeOfString:@".svn"].length){ NSString *fn = [NSSWF @"%@/%@",path,[file stringWithForwardSlashes]];
content = [NSSWCOF fn];
LOG(fn);
[self processCollectLIFTrans:content];
}
[pool release];
}
}
- (void)collectTrans;
{// alle <trans> strings sammeln: <trans>"... bis zeilenende; <trans>'... bis comma oder Zeilenende; <trans>... bis comma oder Zeilenende;
NSDirectoryEnumerator *e;
NSString *path;
[lookup removeAllObjects];
SQL(@"update translationsm set collect_trans = 'N'");
LOG(@".......<trans>");
path = [NSSWF @"%@/Scripts",MANDANTPATH];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self collectTransWithEnumerator:e extension:@"script" path:path];
path = [NSSWF @"%@/Druck",MANDANTPATH];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self collectTransWithEnumerator:e extension:@"cpdf" path:path];
// <| ... |> aus htmlwod
LOG(@".......<| ... |>");
path = [NSSWF @"%@/Templates",MANDANTPATH];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self collectHTMLTransWithEnumerator:e extension:@"htmlwod" path:path];
// TRANSLATION(@"...") aus .m
LOG(@".......TRANSLATION()");
path = [NSSWF @"%@/Local/Projects/Aprica2",[_APP nextRoot]];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self collectObjCTransWithEnumerator:e extension:@"m" path:path];
// Registernamen aus LIF
LOG(@".......LIF");
path = [NSSWF @"%@/LayoutsUsers",MANDANTPATH];
e = [[NSFileManager defaultManager]enumeratorAtPath:path];
[self collectLIFTransWithEnumerator:e extension:@"lif" path:path];
// Modul Unterbereiche werden sowieso nach dem Einloggen uebersetzt
}
@end
@implementation Application (Scripting)
- (NSArray *)scriptNames;
{ return scriptNames;
}
- (NSString *)currentScriptName;
{ NSString *s = [scriptNames lastObject];
if(!FILLED(s))return @"_no_scipt";
return s;
}
- (NSString *)hasRestString;
{ return (restString != nil?@"J":@"N");
}
- (NSMutableDictionary *)scriptDict;
{ return scriptDict;
}
- (NSMutableDictionary *)matchingEndif;
{ return matchingEndif;
}
- (NSMutableDictionary *)matchingEndwhile;
{ return matchingEndwhile;
}
- (NSMutableDictionary *)matchingEndsub;
{ return matchingEndsub;
}
- (NSMutableDictionary *)matchingWhile;
{ return matchingWhile;
}
- (NSMutableDictionary *)matchingEndfor;
{ return matchingEndfor;
}
- (NSMutableDictionary *)matchingForeach;
{ return matchingForeach;
}
- (NSMutableDictionary *)subNamed;
{ return subNamed;
}
- (NSMutableDictionary *)parmDict;
{ return parmDict;
}
/***********************************************************************/
// pdf-Druck , Script
- (NSString *)exprValue:(NSString *)s datasource:ds varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{ // wert von datasource holen; bei prefix %
// modifiers am ende
// keypath in s bereits ohne %
NSString *v;
BOOL bez = NO,provideEO=NO;
v = s;
if(!FILLED(s))return s;
if([s iE:@"datasource"])return ds; // sonderfall
if([s hasSecureSuffix:@".*bez"]){ //bezeichnung bez = YES;
s = [s substringToIndex:[s length] - 5];
}
if([s hasSecureSuffix:@".*eo"]){ //EO; wenn letztes keyPath-Element eine Relation ist, das ziel-eo statt dem foreignkey liefern provideEO = YES;
s = [s substringToIndex:[s length] - 4];
}
if([s hasSecurePrefix:@"*."]){ // obsolet s = [s substringFromIndex:2];
}
if([s hasSecurePrefix:@"datasource."]){ // obsolet s = [s substringFromIndex:11];
}
v = [self kpValueFrom:ds forKp:s bez:bez provideEO:provideEO varDict:varDict localVarDict:localVarDict];
return v;
}
- (NSString *)exprValue:(NSString *)s varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{ // wert von varDict holen; bei prefix $
// modifiers am ende
// keypath in s bereits ohne $
NSString *v;
BOOL bez = NO,provideEO=NO;
NSMutableDictionary *d2use;
if([s hasSecurePrefix:@"l_"] && localVarDict){ //kennzeichen f. lokale Variable in Subroutine d2use = localVarDict;
}else{ d2use = varDict;
}
v = s; // Vorbelegen; v wird am ende zurueckgegeben
if(!FILLED(s))return s;
if([s hasSecureSuffix:@".*bez"]){ //bezeichnung bez = YES;
s = [s substringToIndex:[s length] - 5];
}
if([s hasSecureSuffix:@".*eo"]){ //EO; wenn letztes keyPath-Element eine Relation ist, das ziel-eo statt dem foreignkey liefern provideEO = YES;
s = [s substringToIndex:[s length] - 4];
}
v = [self kpValueFrom:d2use forKp:s bez:bez provideEO:provideEO varDict:varDict localVarDict:localVarDict];
return v;
}
- (NSString *)kpValueFrom:(id)o forKp:(NSString *)keypath bez:(BOOL)bez provideEO:(BOOL)provideEO varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{ // keypath aufloesen
NSArray *kps;
id co;
int i,j;
PBDDTable *t;
PBDDAttribute *pba=nil;
NSString *kp,*kpv=nil;
if(!o || !FILLED(keypath))return EON;
// if([keypath iE:@"ma.lastObject"])LOGS(([NSSWF @"o:%@ class:%@ keypath:%@",[o description],[[o class]description],keypath]));
kps = [keypath componentsSeparatedByString:@"."];
j = [kps count];
co = o;
for(i=0;i<j;i++){ NSRange kpr;
kp = [kps oai:i];
pba = nil;
// kp kann auch embedded Variablen mit $... haben; kann auch komplett eine variable sein, mit $ am anfang
// z.B. bla$fasel$x$y oder $$fasel
kpr = [kp rangeOfString:@"$"];
if(kpr.length){ NSArray *kpvars = [kp componentsSeparatedByString:@"$"];
LMAN(kpvarsval);
int i1=0,j1;
if(kpr.location){ //prefix ohne $ [kpvarsval addObject:[kpvars firstObject]];
i1=1;
}
for(j1=[kpvars count];i1<j1;i1++){ NSString *kpvar = [kpvars oai:i1];
if([kpvar hasSecurePrefix:@"l_"] && localVarDict){ //kennzeichen f. lokale Variable in Subroutine kpvar = [localVarDict ofk:kpvar];
}else{ kpvar = [varDict ofk:kpvar];
}
if(FILLED(kpvar))[kpvarsval addObject:kpvar];
}
kp = [kpvarsval componentsJoinedByString:EON];
}
if([co isKindOfClass:[PBEO class]]){ NSString *effTn=nil;
kpv = [co vfk:kp]; //Wert aus dem EO
if(!FILLED(kpv))return EON; //geht nicht weiter
pba = [[co myTable] plainAttrNamed:kp]; //wg. bez-behandlung unten vor dem break
if(i==(j-1) && !provideEO)break; //letztes Element nicht aufloesen, sondern foreignkey liefern, wenn nicht explizit EO gewuenscht;
if(pba){ if((t = [pba relationTable])){ //relation verfolgen effTn = [t dbName];
}
if(effTn){ co = getEOPkValue(effTn,kpv);
if(!co)return nil; //damit es keine exception gibt; ein NSString wuerde unknown key exception geben
}else{ //normales attribut, geht mit nsstring weiter co = kpv;
}
}else{ co = kpv; //z.B. values oder descri
}
}else{ kpv = nil;
if(!([co isKindOfClass:[NSArray class]] || [co isKindOfClass:[NSString class]])){// mit Arrays und Strings udn Dictionaries geht's nicht so richtig
NS_DURING;
kpv = [co vfk:kp];
//tut bei Dictionaries nicht so richtig; z.B. allValues, allKeys, description etc.
// mit vfk kann man auch an BOOL Werte herangehen; liefert eine NSShortNumber 0 oder 1
if([kpv isKindOfClass:[NSNumber class]])kpv = [kpv description]; // wir wollen einen NSString
NS_HANDLER;
kpv = nil;
NS_ENDHANDLER;
}
if(!kpv){ kpv = [self scriptValueForTarget:co andMethod:kp];
}
co = kpv;
}
// LOGS(([NSSWF @"kpv:%@",kpv]));
}
//Nachbehandlung: *bez oder *eo
if(pba){ if([co isKindOfClass:[PBEO class]] && provideEO)return co;
if(bez)return [pba bezeichnungForValue:kpv];
}
return kpv;
}
- (void)determineOperands:(NSArray *)a1 datasource:(PBWOEditor *)datasource varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict into:(NSMutableArray *)ops;
{ // jeder Operand kann ein zusammengesetzter ausdruck sein
// <money>(($a + %b) / 16) - %*.bla
// operanden sind duch kommata getrennt und enthalten expressions, die wiederum mit operatoren verknuepft sein koennen
// der parser bricht die operanden an spaces auf, ermittelt die werte der expressions,
// fuehrt die operationen aus und formatiert am ende noch
// expressions koennen einen Modifier am ende drangehaengt haben
// der erste Operand, der mit doubleQuote beginnt, geht bis zum Ende der Zeile
int opc,j=[a1 count];
PBDate *pbd;
//" -> woertlich, $, % etc. ignorieren; gilt bis Rest der Zeile; funktioniert nur richtig, wenn am letzten Parameter spezifiziert
//formatting options auswerten
//<date> -> guiDate machen
//<week> -> Kalenderwoche
//<yw> -> Jahr/Kalenderwoche
//<year> -> Jahr 4-stellig
//<yy> -> Jahr 2-stellig
//<wdayn> -> Wochenname kurz
//<int> -> integer
//<floor> -> floor()
//<intnd> -> integer no decimalpoint
//<money> -> 2 NK
//<f1> -> 1 NK
//<f3> -> 3 NK
//<f1nd> -> 1 NK no decimalpoint
//<f2nd> -> 2 NK no decimalpoint
//<f3nd> -> 3 NK no decimalpoint
//<lit> oder ' literally bis Komma
//" literally bis Ende der Zeile
//<uc> uppercase
//<lc> lowercase
//<trans> Uebersetzen mit lang_script
//<trim..> abschneiden
//<str..> rechtsbuendig money laenge ... mit space padded
//<strs...> rechtsbuendig string laenge ... mit space padded
//<stl...> linksbuendig string laenge ... mit space padded
//<round2> -> auf 2 NK runden
for(opc=0;opc<j;opc++){ BOOL collectFlags = YES;
BOOL guidate=NO,guiint=NO,guiintnd=NO,guimoney=NO,guif1=NO,guif3=NO,week=NO,weekYear=NO,year=NO;
BOOL yy=NO,month=NO,wdayn=NO,lit=NO,rnd2=NO,ucFlag=NO,lcFlag=NO,dblQuote=NO;
BOOL trans=NO;
BOOL rnd1=NO;
BOOL f1nd=NO,f2nd=NO,f3nd=NO;
BOOL flr=NO,cl=NO;
int trim=0,str=0,strs=0,stl=0;
NSString *s=[a1 oai:opc],*rv=@"";
if(!FILLED(s)){ [ops addObject:@""]; continue;} if([s iE:@"%"]){ [ops addObject:@"%"]; continue;} if([s iE:@"%%"]){ [ops addObject:@"%"]; continue;} if([s iE:@"%datasource"]){ [ops addObject:datasource]; continue;} if([s iE:@"\\r\\n"] || [s iE:@"\"\\r\\n"]){ [ops addObject:@"\r\n"]; continue;} // cr + newline if([s iE:@"\\n"] || [s iE:@"\"\\n"]) { [ops addObject:@"\n"]; continue;}// newline if([s iE:@"\\t"] || [s iE:@"\"\\t"]){ [ops addObject:@"\t"]; continue;}// tab
//Formatierungsoptionen vorangestellt fuer ganzen Ausdruck; Reihenfolge egal;
while(collectFlags){ if([s hasSecurePrefix:@"\""]){ s = [s substringFromIndex:1];
dblQuote = YES;
break;
}
if([s hasSecurePrefix:@"<lit>"] && !lit){ //literally lit=YES;
s = [s substringFromIndex:5];
continue;
}
if([s hasSecurePrefix:@"'"] && !lit){ //literally lit=YES;
s = [s substringFromIndex:1];
continue;
}
if([s hasSecurePrefix:@"<trans>"]){ //translate standard trans=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<trim"]){ NSString *trims;
s = [s substringFromIndex:5];
trims = [s substringToIndex:3]; //z.B. 20>
trim=[trims intValue];
s = [s substringFromIndex:3];
continue;
}
if([s hasSecurePrefix:@"<strs"]){ // rechtsb. string s = [s substringFromIndex:5];
strs=[[s substringToIndex:3] intValue];
s = [s substringFromIndex:3];
continue;
}
if([s hasSecurePrefix:@"<str"]){ // rechtsb. money s = [s substringFromIndex:4];
str=[[s substringToIndex:3] intValue];
s = [s substringFromIndex:3];
continue;
}
if([s hasSecurePrefix:@"<stl"]){ // linksb. string s = [s substringFromIndex:4];
stl=[[s substringToIndex:3] intValue];
s = [s substringFromIndex:3];
continue;
}
if([s hasSecurePrefix:@"<date>"]){ guidate=YES;
s = [s substringFromIndex:6];
continue;
}
if([s hasSecurePrefix:@"<week>"]){ week=YES;
s = [s substringFromIndex:6];
continue;
}
if([s hasSecurePrefix:@"<month>"]){ month=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<yw>"]){ weekYear=YES;
s = [s substringFromIndex:4];
continue;
}
if([s hasSecurePrefix:@"<year>"]){ year=YES;
s = [s substringFromIndex:6];
continue;
}
if([s hasSecurePrefix:@"<yy>"]){ yy=YES;
s = [s substringFromIndex:4];
continue;
}
if([s hasSecurePrefix:@"<wdayn>"]){ wdayn=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<int>"]){ guiint=YES;
s = [s substringFromIndex:5];
continue;
}
if([s hasSecurePrefix:@"<round2>"]){ rnd2=YES;
s = [s secureSubstringFromIndex:8];
continue;
}
if([s hasSecurePrefix:@"<round1>"]){ rnd1=YES;
s = [s secureSubstringFromIndex:8];
continue;
}
if([s hasSecurePrefix:@"<intnd>"]){ guiintnd=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<money>"]){ guimoney=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<f1>"]){ guif1=YES;
s = [s substringFromIndex:4];
continue;
}
if([s hasSecurePrefix:@"<f3>"]){ guif3=YES;
s = [s substringFromIndex:4];
continue;
}
if([s hasSecurePrefix:@"<f1nd>"]){ f1nd=YES;
s = [s substringFromIndex:6];
continue;
}
if([s hasSecurePrefix:@"<f2nd>"]){ f2nd=YES;
s = [s substringFromIndex:6];
continue;
}
if([s hasSecurePrefix:@"<f3nd>"]){ f3nd=YES;
s = [s substringFromIndex:6];
continue;
}
if([s hasSecurePrefix:@"<floor>"]){ flr=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<ceil>"]){ cl=YES;
s = [s substringFromIndex:7];
continue;
}
if([s hasSecurePrefix:@"<uc>"]){ ucFlag=YES;
s = [s substringFromIndex:4];
continue;
}
if([s hasSecurePrefix:@"<lc>"]){ lcFlag=YES;
s = [s substringFromIndex:4];
continue;
}
collectFlags = NO;
}
if(dblQuote){ // wenn dblQuote, s und alle folgeoperanden zusammencatten und die Formatierung auf alle anwenden;
rv = [[a1 arrayFromIndex:opc + 1]componentsJoinedByString:@","];
if(FILLED(rv)){ rv = [NSSWF @"%@,%@",s,rv];
}else{ rv = s;
}
}else{ // Werte der einzelnen Ausdruecke beschaffen, Klammern, rechnen; rekursiv
if(lit){ //nicht parsen, sondern als woertlichen string interpretieren rv = s;
}else{ // wenn es der letzte Operand ist, trailing spaces und comments abschneiden
if(opc==(j-1))s = [s stringWithoutTrailingWSC];
rv = (NSString *)[[PBExpression expressionFromString:s] valueForDatasource:datasource varDict:varDict localVarDict:localVarDict];
}
}
if(!rv){ [ops addObject:@""];
continue;
}
// und formatieren
if(guidate){ rv = [rv guiDate];
}
if(week){ rv = NSS([[PBDate dateWithDBString:rv] weekOfYear]);
}
if(month){ rv = [[rv normalizedDate]nd_month];
}
if(weekYear){ pbd = [PBDate dateWithDBString:rv];
rv = [NSSWF @"%04i/%02i",[pbd yearForWeek],[pbd weekOfYear]];
}
if(year){ rv = [[rv normalizedDate]nd_year];
}
if(yy){ rv = [[[rv normalizedDate]nd_year]secureSubstringFromIndex:2];
}
if(wdayn){ rv = [[rv normalizedDate]nd_weekdayName];
}
if(guiint){ rv = NSS((int)round0([rv doubleValue]));
}
if(guiintnd){ rv = NSS([rv intValue]);
}
if(rnd2){ rv = [NSString dbFromDouble:[rv doubleValue]];
}
if(rnd1){ rv = [NSString dbFromDouble:[rv doubleValue] nak:1];
}
if(guimoney){ rv = [NSString dottedGuiFromDouble:[rv doubleValue] nak:2];
}
if(guif1){ rv = [NSString dottedGuiFromDouble:[rv doubleValue] nak:1];
}
if(guif3){ rv = [NSString dottedGuiFromDouble:[rv doubleValue] nak:3];
}
if(f1nd){ rv = [[NSSWF @"%0.1f",round1([rv doubleValue])]comma];
}
if(f2nd){ rv = [[NSSWF @"%0.2f",round2([rv doubleValue])]comma];
}
if(f3nd){ rv = [[NSSWF @"%0.3f",round3([rv doubleValue])]comma];
}
if(flr){ rv = [[NSSWF @"%0.0f",floor([rv doubleValue])]comma];
}
if(cl){ rv = [[NSSWF @"%0.0f",ceil([rv doubleValue])]comma];
}
if(ucFlag){ rv = [rv uppercaseString];
}
if(lcFlag){ rv = [rv lowercaseString];
}
if(trans){ rv = [_SESSION transScriptFor:rv];
}
// evt. noch kuerzen
if(trim && [rv length]>trim)rv = [rv substringToIndex:trim];
if(stl)rv = [rv stl:stl]; // linksb. string
if(str)rv = [rv str:str]; // rechtsb. money
if(strs)rv = [rv strs:strs]; // rechtsb. string
[ops addObject:rv];
if(dblQuote)break;
}
}
- (NSString *)valueFromExpression:(NSString *)s datasource:(PBWOEditor *)datasource varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{// loest eine einzelne Expression auf; verwendet dabei die entsprechende exprValue:... Methode
NSString *s1;
// feststellen, woher der wert geholt werden soll: $ = eigene Var., % = datasource; sonst woertlich
if([s length] < 2)return s; // z.B. "%"
if([s hasPrefix:@"$"]){ s = [s substringFromIndex:1];
if([s hasSecurePrefix:@"$"]){ // $$... varieblenname steht in einer variablen s = [s substringFromIndex:1];
s = [self exprValue:s varDict:varDict localVarDict:localVarDict];
}
s1 = [self exprValue:s varDict:varDict localVarDict:localVarDict];
}else{ if([s hasPrefix:@"%"] && ![s hasPrefix:@"%@"]){ // wg. spf %@ am Anfang moeglich s = [s substringFromIndex:1];
s1 = [self exprValue:s datasource:datasource varDict:varDict localVarDict:localVarDict];
}else{ return [s replace:@"<comma>" with:@","]; //woertlich; <comma> durch , ersetzen
}
}
if(!s1)return EON; // damit leere NSMutableStrings und NSMutableData nicht zu NSString werden
return s1;
}
- (void)determineTargetObject:(NSObject **)targetObject andKey:(NSString **)targetKey forKeyPath:(NSString *)keyPath datasource:(PBWOEditor *)datasource intern:(BOOL)intern varDict:(NSMutableDictionary *)varDict localVarDict:(NSMutableDictionary *)localVarDict;
{// fuer Wertzuweisungen: %bla.fasel.x.y,=,z ergibt [[[[datasource vfk:@"bla"]vfk@"fasel"]vfk:@"x"] takeValue:z forKey:@"y"]
// fuehrendes % oder $ schon weg; information steckt in intern-Flag
NSObject *co; //currentObject
NSArray *kps;
NSString *kp,*kpv; //keypart, keypart value
LMA;
int i,j;
*targetObject = nil;
*targetKey = nil;
if(!keyPath)return;
kps = [keyPath componentsSeparatedByString:@"."];
//erstmal variable keynamen aufloesen
j = [kps count];
for(i=0;i<j;i++){ NSRange kpr;
kp = [kps oai:i];
// kp kann auch embedded Variablen mit $... haben; kann auch komplett eine variable sein, mit $ am anfang
// z.B. bla$fasel$x$y oder $$fasel
kpr = [kp rangeOfString:@"$"];
if(kpr.length){ NSArray *kpvars = [kp componentsSeparatedByString:@"$"];
LMAN(kpvarsval);
int i1=0,j1;
if(kpr.location){ // prefix ohne $ [kpvarsval addObject:[kpvars firstObject]];
i1=1;
}
for(j1=[kpvars count];i1<j1;i1++){ NSString *kpvar = [kpvars oai:i1];
if([kpvar hasSecurePrefix:@"l_"] && localVarDict){ // kennzeichen f. lokale Variable in Subroutine kpvar = [localVarDict ofk:kpvar];
}else{ kpvar = [varDict ofk:kpvar];
}
if(FILLED(kpvar))[kpvarsval addObject:kpvar];
}
kp = [kpvarsval componentsJoinedByString:EON];
}
if(!kp)kp=EON;
[lma addObject:kp];
}
if(intern){ // geht auf varDict
co = varDict;
if([keyPath hasSecurePrefix:@"l_"]){ if(localVarDict)co = localVarDict;
}
}else{ co = datasource;
}
if([[lma firstObject]iE:@"*"]){// %*.
// ist die Datasource mit gemeint; nur noch bei EOs; co bleibt die datasource
[lma removeObjectAtIndex:0];
}
if([[lma firstObject]iE:@"datasource"]){// %datasource.
// ist die Datasource mit gemeint; doppelt gemoppelt
[lma removeObjectAtIndex:0];
}
while([lma count]>1){ PBDDAttribute *pba=nil;
kp = [lma firstObject];
if([co isKindOfClass:[PBEO class]]){ NSString *effTn=nil;
kpv = [co vfk:kp];
if(!FILLED(kpv)){ LOGS(([NSSWF @"leerer Key %@ an %@ fuer %@",kp,[lma description],keyPath]));
return; //geht nicht weiter
}
pba = [[(PBEO *)co myTable] plainAttrNamed:kp];
if(pba){ PBDDTable *t;
if((t = [pba relationTable])){ //relation verfolgen effTn = [t dbName];
}
if(effTn){ co = getEOPkValue(effTn,kpv);
if(!co)return; //damit es keine exception gibt; ein NSString wuerde unknown key exception geben
}else{ //normales attribut, geht mit nsstring weiter co = kpv;
}
}else{ co = kpv; //z.B. values oder descri
}
}else{ kpv = nil;
if(!([co isKindOfClass:[NSArray class]] || [co isKindOfClass:[NSString class]])){// mit Arrays und Strings udn Dictionaries geht's nicht so richtig
NS_DURING;
kpv = [co vfk:kp];
//tut bei Dictionaries nicht so richtig; z.B. allValues, allKeys, description etc.
// mit vfk kann man auch an BOOL Werte herangehen; liefert eine NSShortNumber 0 oder 1
if([kpv isKindOfClass:[NSNumber class]])kpv = [kpv description]; // wir wollen einen NSString
NS_HANDLER;
kpv = nil;
NS_ENDHANDLER;
}
if(!kpv){ kpv = [self scriptValueForTarget:co andMethod:kp];
}
co = kpv;
}
[lma removeObjectAtIndex:0];
}
*targetObject = co;
*targetKey = [lma firstObject];
}
- (NSString *)currentPDFPath;
{ return [NSSWF @"%@/temp/%@_%@.pdf",RESOURCEPATH,[_SESSION sessionID],currentTempName];
}
- (PBPDFDoc *)preparePBPDF;
{ PBPDFDoc *pdf;
pageCount = 0;
scale = 10;
pages = 1000;
pdf = [PBPDFDoc newPDF];
[self setCurrentTempName:[self tempName]]; //currentTempName wird in naechster methode gebraucht
return pdf;
}
- (NSArray *)pdfStatementsNamed:(NSString *)v datasource:(PBWOEditor *)datasource;
{ NSArray *a;
a = [[_APP scriptDict] ofk:v];
if(!a){ LOGS(([NSSWF @"Druckformular %@ nicht gefunden",v]));
return nil;
}
return a;
}
- (void)ohnePreview;
{//zuletzt gedrucktes PDF in spoolpath und nicht in Acrobat; nach finishPBPDF;
NSString *spoolPath = [NSSWF @"%@/Spool/%@_%@.pdf",MANDANTPATH,[_SESSION sessionID],currentTempName];
if(pageCount){ [myFM createAllDirsAtPath:[spoolPath stringByDeletingLastPathComponent]];
[myFM copyPath:[self currentPDFPath] toPath:spoolPath handler:nil];
[self setUrlToOpenInNewBrowser:nil];
}
}
- (void)finischPBPDF:(PBPDFDoc *)pdf;
{ NSString *path = [self currentPDFPath];
NSString *url;
NSData *renderedPDF=nil;
// das pdf kann sich selbst rendern in sein File
if(![pdf wasRendered]){ renderedPDF = [pdf renderPDF];
if(!renderedPDF){ LOGI(TRANSLATION(@"Druck hat keine Seiten erzeugt"));
return;
}
}
[renderedPDF writeToFile:path atomically:YES];
if([[configDict ofk:@"always_embedding"]iE:@"J"] || [pdf needsFontEmbedding]){// durch pdftk und gs pipen
// pdftk a.pdf output c.pdf
// C:\seat1ERP\Local\bin\gs\gs8.53\bin\gswin32.exe -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=g.pdf c.pdf
NSString *pdftk = [[_APP configDict]ofk:@"pdftk"];
NSString *gs = [[_APP configDict]ofk:@"gs"];
NSString *sys;
if(!FILLED(pdftk))pdftk = @"pdftk";
if(!FILLED(gs))gs = @"gs";
sys = [NSSWF @"%@ %@ output %@_c",pdftk,path,path];
SYSTEM(sys);
sys = [NSSWF @"%@ -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=%@ %@_c",gs,path,path];
SYSTEM(sys);
}
url = [NSSWF @"/Aprica2_%@/temp/%@_%@.pdf",mandant,[_SESSION sessionID],currentTempName];
if(![_APP isBatch]){ [self setUrlToOpenInNewBrowser:url];
}
}
- (NSMutableDictionary *)druckPDFNamed:(NSString *)v datasource:(PBWOEditor *)datasource parmDict:(NSMutableDictionary *)p_parmDict;
{ NSArray *a = nil;
PBPDFDoc *pbpdf=nil;
NSMutableDictionary *resultDict;
NSString *currentPDFVorgang;
PBEO *currentPDFEmpfaenger;
a = [self pdfStatementsNamed:v datasource:datasource];
if(!a)return nil;
pbpdf = [self preparePBPDF];
resultDict = [self executeScriptNamed:v statements:a datasource:datasource parmDict:p_parmDict pdf:pbpdf continueMode:NO];
[self finischPBPDF:pbpdf];
// falls in resultdict currentPDFEmpfaenger, currentPDFVorgang vorhanden sind:document erzeugen u. zuordnen
// funktioniert nur, wenn nicht in einem PDF mehrere Dokumente fuer mehrere Empfaenger vorhanden sind
currentPDFEmpfaenger = [resultDict ofk:@"currentPDFEmpfaenger"];
currentPDFVorgang = [resultDict ofk:@"currentPDFVorgang"];
if(FILLED(currentPDFVorgang)){// falls es kein document mit dieser document_id gibt, eines erzeugen wie wenn pdf upgeloaded worden waere
[parmDict setObject:currentPDFVorgang forKey:@"p_vorgang"];
[parmDict setObject:[self currentPDFPath] forKey:@"p_path"];
if(FILLED(currentPDFEmpfaenger)){ [parmDict setObject:currentPDFEmpfaenger forKey:@"p_empfaenger"];
}else{ [parmDict removeObjectForKey:@"p_empfaenger"];
}
[parmDict setObject:resultDict forKey:@"p_resultDict"];
[_APP executeScriptNamed:@"archivePDF" datasource:(PBWOEditor *)self parmDict:parmDict];
}
return resultDict;
}
- (int)pages;
{ return pages;
}
- (int)subNamed:(NSString *)s in:(NSArray *)a name:(NSString *)v;
{ int i,j;
NSString *s2,*s1;
s1 = [NSSWF @"%@%@",v,s];
if((s2=[[self subNamed] ofk:s1])){ return [s2 intValue];
}
for(i=0,j=[a count];i<j;i++){ s2 = [a oai:i];
if([s2 hasSecurePrefix:@"sub "]){ if([s iE:[s2 substringFromIndex:4]]){ [[self subNamed] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
}
}
LOGS(([NSSWF @"sub named %@ not found",s]));
return j;
}
- (int)matchingEndifFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ return [self matchingEndifFrom:i orElse:NO in:a name:v];
}
- (int)matchingEndifOrElseFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ return [self matchingEndifFrom:i orElse:YES in:a name:v];
}
- (int)matchingEndifFrom:(int)i orElse:(BOOL)yn in:(NSArray *)a name:(NSString *)v;
{ int nest = 0;
int j = [a count];
NSString *s,*s1;
s1 = [NSSWF @"%@%i",v,i];
if((s=[[self matchingEndif] ofk:s1])){ return [s intValue];
}
i++;
for(;i<j;i++){ s = [a oai:i];
if(yn && [s hasSecurePrefix:@"else"] && !nest){ [[self matchingEndif] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
if([s hasSecurePrefix:@"endif"]){ if(!nest){ [[self matchingEndif] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
nest--;
if(nest < 0){ LOGS(([NSSWF @"nesting Error endif from %i in %@",i,v]));
return j;
}
continue;
}
if([s hasSecurePrefix:@"if "]){ nest++;
continue;
}
}
LOGS(([NSSWF @"nesting Error endif not found from %i in %@",i,v]));
return j;
}
- (int)matchingEndwhileFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ int nest = 0;
int j = [a count];
NSString *s,*s1;
s1 = [NSSWF @"%@%i",v,i];
if((s=[[self matchingEndwhile] ofk:s1])){ return [s intValue];
}
i++;
for(;i<j;i++){ s = [a oai:i];
if([s hasSecurePrefix:@"endwhile"]){ if(!nest){ [[self matchingEndwhile] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
nest--;
if(nest < 0){ LOGS(([NSSWF @"nesting Error endwhile from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
continue;
}
if([s hasSecurePrefix:@"while "]){ nest++;
continue;
}
}
LOGS(([NSSWF @"nesting Error endwhile not found from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
- (int)matchingEndsubFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ int j = [a count];
NSString *s,*s1;
s1 = [NSSWF @"%@%i",v,i];
if((s=[[self matchingEndsub] ofk:s1])){ return [s intValue];
}
i++;
for(;i<j;i++){ s = [a oai:i];
if([s hasSecurePrefix:@"endsub"]){ [[self matchingEndsub] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
}
LOGS(([NSSWF @"endsub not found from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
- (int)matchingWhileFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ int nest = 0;
int j = [a count];
NSString *s,*s1;
s1 = [NSSWF @"%@%i",v,i];
if((s=[[self matchingWhile] ofk:s1])){ return [s intValue];
}
i--;
for(;i>=0;i--){ s = [a oai:i];
if([s hasSecurePrefix:@"while "]){ if(!nest){ [[self matchingWhile] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
nest--;
if(nest < 0){ LOGS(([NSSWF @"nesting Error while from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
continue;
}
if([s hasSecurePrefix:@"endwhile"]){ nest++;
continue;
}
}
LOGS(([NSSWF @"nesting Error while not found from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
- (int)matchingEndforFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ int nest = 0;
int j = [a count];
NSString *s,*s1;
s1 = [NSSWF @"%@%i",v,i];
if((s=[[self matchingEndfor] ofk:s1])){ return [s intValue];
}
i++;
for(;i<j;i++){ s = [a oai:i];
if([s hasSecurePrefix:@"endfor"]){ if(!nest){ [[self matchingEndfor] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
nest--;
if(nest < 0){ LOGS(([NSSWF @"nesting Error endfor from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
continue;
}
if([s hasSecurePrefix:@"foreach "]){ nest++;
continue;
}
}
LOGS(([NSSWF @"nesting Error endfor not found from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
- (int)matchingForeachFrom:(int)i in:(NSArray *)a name:(NSString *)v;
{ int nest = 0;
int j = [a count];
NSString *s,*s1;
s1 = [NSSWF @"%@%i",v,i];
if((s=[[self matchingForeach] ofk:s1])){ return [s intValue];
}
i--;
for(;i>=0;i--){ s = [a oai:i];
if([s hasSecurePrefix:@"foreach "]){ if(!nest){ [[self matchingForeach] setSecureObject:NSS(i) forKey:s1]; //in Cache merken
return i;
}
nest--;
if(nest < 0){ LOGS(([NSSWF @"nesting Error foreach from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
continue;
}
if([s hasSecurePrefix:@"endfor"]){ nest++;
continue;
}
}
LOGS(([NSSWF @"nesting Error foreach not found from %i in %@ \nstatments:%@",i,v,[a componentsJoinedByString:@"\n"]]));
return j;
}
- (NSDictionary *)splitScriptIntoSubScripts:(NSArray *)a defaultScriptName:(NSString *)defaultScriptName;
{ NSString *scriptBaseName=nil;
LMD;
int i,j;
NSMutableArray *lma=nil;
if([defaultScriptName rangeOfString:@"/"].length){ scriptBaseName = [[defaultScriptName stringByDeletingLastPathComponent]stringWithForwardSlashes];
}
for(i=0,j=[a count];i<j;i++){ NSString *s = [a oai:i];
if([s hasSecurePrefix:@"subScript:"]){ NSString *ssn = [s substringFromIndex:[@"subScript:" length]];
if(scriptBaseName)ssn=[NSSWF @"%@/%@",scriptBaseName,ssn];
lma = [NSMutableArray arrayWithCapacity:100];
[lmd setObject:lma forKey:ssn];
}else{ if(lma)[lma addObject:s]; //subscriptarray in place
}
}
return lmd;
}
- (NSMutableDictionary *)loadScriptFilesIntoDict:(NSMutableDictionary *)dict dirName:(NSString *)dirName suffix:(NSString *)suffix;
{//alle scipt files in dir; rekursiv;
//dirName ist Script oder Druck
// returned ein Dictionary mit den geladenen Scripts, um changedScripts analysieren zu koennen
int i,j;
NSString *s,*baseDir;
NSArray *filesToLoad;
NSArray *a1;
LMD;
// suffix ist schon mit .
nestinglevel = 0;
[infiniteDetection removeAllObjects];
[gma removeAllObjects];
[logs removeAllObjects];
NS_DURING;
baseDir = [NSSWF @"%@/%@",MANDANTPATH,dirName];
filesToLoad = [myFM directoryDeepContentsAtPath:baseDir suffixes:[NSArray arrayWithObject:suffix] skips:nil fullName:YES newer:lastReload];
for(i=0,j=[filesToLoad count];i<j;i++){ s = [[filesToLoad oai:i]stringWithForwardSlashes];
if([s rangeOfString:@".svn"].length)continue; //keine svn Files laden
if(lastReload){ [scriptFileNames addObjectUniq:s];
}else{ [scriptFileNames addObject:s];
}
if([[s lastPathComponent]hasSecurePrefix:@"_"])continue; // ein Import
if((a1 = [self loadScriptFileNamed:s dirName:dirName suffix:suffix])){ NSString *scriptName = [[s stringByDeletingPathExtension]stringWithForwardSlashes];
if([suffix iE:@".script"]){ NSDictionary *d = [self splitScriptIntoSubScripts:a1 defaultScriptName:scriptName];
//mehrere Scripts in einem File
//z.B.:
//subScript:didInsert
//....
if([d count]){ [dict addEntriesFromDictionary:d];
[lmd addEntriesFromDictionary:d];
continue;
}
}
if([dict ofk:scriptName] && !lastReload){ LOG(([NSSWF @"#### doppelter Name Script und Druck: %@",scriptName]));
}
[dict setSecureObject:a1 forKey:scriptName];
[lmd setSecureObject:a1 forKey:scriptName];
}else{ LOGS(([NSSWF @"could not load file %@",s]));
}
}
if([[configDict ofk:@"logscriptnames"]iE:@"J"])[[logs componentsJoinedByString:@"\n"]writeToFile:[NSSWF @"%@/all_%@.txt",TEMPDIR,suffix]];
NS_HANDLER;
LOGS_Ex(@"laden fehlgeschlagen");
NS_ENDHANDLER;
return lmd;
}
- (void)loadScriptFiles;
{ int i,j;
NSString *fn,*path,*file;
LOG(@"loading ScriptFiles for searching");
// nach reloadScripts; .script u. .cpdf komplett reinladen, um sie durchsuchen zu koennen; gleiche reihenfolge wie scriptFileNames;
[scriptFiles removeAllObjects];
for(i=0,j=[scriptFileNames count];i<j;i++){ fn = [scriptFileNames oai:i];
if([fn hasSecureSuffix:@".cpdf"]){ path = [NSSWF @"%@/Druck/%@",MANDANTPATH,fn];
}else{ path = [NSSWF @"%@/Scripts/%@",MANDANTPATH,fn];
}
file = [NSSWCOF path];
if(!file)file=@"";
[scriptFiles addObject:file];
}
}
- (void)loadTemplateFiles;
{ int i,j;
NSString *fn,*path,*file;
LOG(@"loading TemplateFiles for searching");
// Templates komplett reinladen, um sie durchsuchen zu koennen; gleiche reihenfolge wie templateFileNames;
[templateFiles removeAllObjects];
for(i=0,j=[templateFileNames count];i<j;i++){ fn = [templateFileNames oai:i];
path = [NSSWF @"%@/Templates/%@",MANDANTPATH,fn];
file = [NSSWCOF path];
if(!file)file=@"";
[templateFiles addObject:file];
}
}
- (NSArray *)findInFiles:(NSString *)s;
{ LMA;
int i,j;
NSString *fn,*file;
if(![scriptFiles count])[self loadScriptFiles];
for(i=0,j=[scriptFiles count];i<j;i++){ fn = [scriptFileNames oai:i];
file = [scriptFiles oai:i];
if([file rangeOfString:s].length)[lma addObject:fn];
}
return lma;
}
- (NSArray *)findInTemplates:(NSString *)s;
{ LMA;
int i,j;
NSString *fn,*file;
if(![templateFiles count])[self loadTemplateFiles];
for(i=0,j=[templateFiles count];i<j;i++){ fn = [templateFileNames oai:i];
file = [templateFiles oai:i];
if([file rangeOfString:s].length)[lma addObject:fn];
}
return lma;
}
- (NSArray *)loadScriptFileNamed:(NSString *)dn dirName:(NSString *)dirName suffix:(NSString *)suffix;
{ NSString *pathf;
NSString *s;
LMA;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSString *baseDir = [NSSWF @"%@/%@",MANDANTPATH,dirName];
if([infiniteDetection ofk:dn]){ LOGS(([NSSWF @"endlosschleife %@ %@",dn,dirName]));
[pool release];
return nil; //endlos-Schleife
}
[infiniteDetection setSecureObject:EON forKey:dn];
[gma addObject:dn];
[logs addObject:[gma componentsJoinedByString:@"->"]];
pathf = [NSSWF@"%@/%@",baseDir,dn];
s = [NSSWCOF pathf];
if(!s){ LOGS(([NSSWF @"file %@ nicht gefunden",pathf]));
[infiniteDetection removeObjectForKey:dn];
[gma secureRemoveLastObject];
[pool release];
return nil;
}
[lma addObjectsFromArray:[self statementsForScript:s dirName:dirName suffix:suffix]];
[infiniteDetection removeObjectForKey:dn];
[gma secureRemoveLastObject];
[pool release];
return lma;
}
- (NSArray *)statementsForScript:(NSString *)script dirName:(NSString *)dirName suffix:(NSString *)suffix;
{ // kommentare rausfiltern, imports aufloesen
// uebersprungene Zeilen mit leerem Statement drinlassen, um Source-Linenumbers zu behalten
LMA;
NSArray *a = [script componentsSeparatedByString:@"\n"];
int i,j = [a count];
BOOL inComment = NO;
for(i=0;i<j;i++){ NSString *s = [a oai:i];
// drinlassen wg. Textverarbeitung if(!FILLED(s))continue; //Leerzeilen
s = [s stringWithoutWindowsShit];
s = [s stringWithoutLeadingWhiteSpace];
// if([s hasPrefix:@"#"])continue; sind jetzt Preprocessor Anweisungen;
if([s hasPrefix:COMMENT]){ [lma addObject:@""]; continue;} // if([s hasPrefix:ENDCOMMENT]){ inComment = NO;
[lma addObject:@""]; continue;
}
if([s hasPrefix:STARTCOMMENT]){ if([s hasSecureSuffix:ENDCOMMENT]){ [lma addObject:@""]; continue;
}
inComment = YES;
[lma addObject:@""]; continue;
}
if(inComment){ [lma addObject:@""]; continue;} if([s hasSecurePrefix:@"erklaerung"]){ [lma addObject:@""]; continue;} if([s hasSecurePrefix:@"label "]){ [lma addObject:@""]; continue;} if([s length]>6 && [s hasPrefix:@"import"]){ NSString *s1;
NSArray *a1;
NSString *pathf;
a1 = [s componentsSeparatedByString:@" "];
if([a1 count]<2)continue;
s1 = [a1 lastObject]; //name der zu importierenden Datei; $mandant im Filename wird durch mandantennr ersetzt
s1 = [s1 replace:@"$mandant" with:[_APP mandant]];
// wo sucht man imports?
// 1. im Mandanten-Directory
pathf = [NSSWF @"%@/%@/%@%@",MANDANTPATH,dirName,s1,suffix];
if([myFM fileExistsAtPath:pathf]){//im Mandantendirectory suchen
if((a1 = [self loadScriptFileNamed:[s1 stringByAppendingString:suffix] dirName:dirName suffix:suffix])){ [lma addObjectsFromArray:a1];
continue;
}
}
LOGS(([NSSWF @"import %@ nicht gefunden! %@",s1,pathf]));
continue;
}
[lma addObject:s];
}
return lma;
}
- (void)clearCacheForScriptNamed:(NSString *)scriptName;
{// f. Temp-Script
NSString *s = [@"Script_" stringByAppendingString:scriptName];
[matchingEndif removeAllEntriesWithPrefix:s];
[matchingEndwhile removeAllEntriesWithPrefix:s];
[matchingEndsub removeAllEntriesWithPrefix:s];
[matchingWhile removeAllEntriesWithPrefix:s];
[subNamed removeAllEntriesWithPrefix:s];
[matchingEndfor removeAllEntriesWithPrefix:s];
[matchingForeach removeAllEntriesWithPrefix:s];
}
- (void)reloadChangedScripts;
{ NSDictionary *d;
LOG(@"reloading changed Scripts");
[scriptFiles removeAllObjects];
[scriptErrors removeAllObjects];
[matchingEndif removeAllObjects];
[matchingEndwhile removeAllObjects];
[matchingEndsub removeAllObjects];
[matchingWhile removeAllObjects];
[subNamed removeAllObjects];
[matchingEndfor removeAllObjects];
[matchingForeach removeAllObjects];
d = [self loadScriptFilesIntoDict:scriptDict dirName:@"Druck" suffix:@".cpdf"];
[self analyzeScriptsIn:d into:scriptDictAnalyzed];
d = [self loadScriptFilesIntoDict:scriptDict dirName:@"Scripts" suffix:@".script"];
[self analyzeScriptsIn:d into:scriptDictAnalyzed];
[self setLastReload:[NSDate date]];
[scriptFileNames sortUsingSelector:@selector(compareCaseInsensitive:)];
}
- (void)reloadScripts;
{ NSArray *a = [scriptDict ofk:@"scripting/bu_reload_scripts"];
[a retain];
LOG(@"reloading all Scripts");
[self setLastReload:nil];
[scriptDict removeAllObjects];
[scriptDictAnalyzed removeAllObjects];
[scriptFileNames removeAllObjects];
[scriptFiles removeAllObjects];
[scriptErrors removeAllObjects];
[matchingEndif removeAllObjects];
[matchingEndwhile removeAllObjects];
[matchingEndsub removeAllObjects];
[matchingWhile removeAllObjects];
[subNamed removeAllObjects];
[matchingEndfor removeAllObjects];
[matchingForeach removeAllObjects];
[self loadScriptFilesIntoDict:scriptDict dirName:@"Druck" suffix:@".cpdf"];
[self loadScriptFilesIntoDict:scriptDict dirName:@"Scripts" suffix:@".script"];
[self loadScriptsForAttributes];
[self analyzeScriptsIn:scriptDict into:scriptDictAnalyzed];
[self setLastReload:[NSDate date]];
[scriptFileNames sortUsingSelector:@selector(compareCaseInsensitive:)];
}
- (void)loadScriptsForAttributes;
{ /*
aufgerufen nachdem die Scripts aus den Files geladen sind
alle plainAttributes durchgehen:
bei Buttons: wenn Expression leer: tablename/attributename ist Scriptname; setzen;
wenn Expression eine Zeile: .cpdf isDruck=YES; sonst ist die Zeile der Scriptname; scriptName setzen;
wenn mehrere Zeilen: script unter tablename-attributname ins scriptDict, scriptName setzen;
bei TVCSELOBJ:
wenn Expression eine Zeile: wenn .script hintendran, scriptName setzen;
sonst PBExpression setzen
wenn mehrere Zeilen: script unter tablename-attributname ins scriptDict, scriptName setzen;
im EO bei valueForKey: wenn nicht im values-Dict.: PBExpression? scriptName? script mit datasource=EO aufrufen
bei Buttons: isDruck? script mit richtiger Methode (druck oder script) mit datasource=PBWOEditor aufrufen
*/
NSArray *a = [myDD plainAttributes];
int i,j;
NSString *expression;
for(i=0,j=[a count];i<j;i++){ PBDDAttribute *pbat = [a oai:i];
expression = [pbat expression];
if(!FILLED(expression) && ![pbat isButton])continue; // schnelle vorab-pruefung
if([pbat isButton]){ if(FILLED(expression)){ if([expression rangeOfString:@"\n"].length){ // mehrzeilig; ganzes script liegt in expression
[pbat setScriptName:[NSSWF @"%@-%@",[[pbat myTable] dbName],[pbat dbName]]];
if(![scriptDict ofk:[pbat scriptName]]){ // bei Buttons aus mehrfach verwendeten abstract tables kann es sein, dass script bereits vorliegt
// imports aufloesen, Kommentare raus
[scriptDict setObject:[self statementsForScript:expression dirName:@"Scripts" suffix:@".script"] forKey:[pbat scriptName]];
}
}else{ // einzeilig: nur der Scriptname liegt in expression
if([expression hasSecureSuffix:@".cpdf"]){ [pbat setIsDruck:YES];
[pbat setScriptName:[expression stringWithoutSuffix:@".cpdf"]];
}else if([expression hasSecureSuffix:@".script"]){ [pbat setScriptName:[expression stringWithoutSuffix:@".script"]];
}else{ //ohne suffix -> script annehmen
[pbat setScriptName:expression];
}
}
}else{ // wenn Expression leer: dbName ist Name des scripts im Hauptmodul-Directory, welches so heisst wie die Tabelle
[pbat setScriptName:[NSSWF @"%@/%@",[[pbat myTable] dbName],[pbat dbName]]];
}
// pruefen, ob Script da ist;
if(![scriptDict ofk:[pbat scriptName]])LOG(([NSSWF @"*** script missing: %@",[pbat scriptName]]));
continue;
}
if([pbat targetTyp] == ATTVCSELOBJ){ // ist es nur 1 Zeile, dann als expression interpretieren
// bei mehreren Zeilen als Script ausfuehren; $_rv ist ergebnis
if(![expression rangeOfString:@"\n"].length){ if([expression hasSecurePrefix:@"SQL:"])continue;
if([expression hasSecureSuffix:@".script"]){ [pbat setScriptName:[expression stringWithoutSuffix:@".script"]];
}else{ [pbat setPbexpression:[PBExpression expressionFromString:expression]];
}
}else{ // mehrzeilig; ganzes script liegt in expression
// Script ins Scriptdict, dann muss es nicht jedesmal geparsed werden
[pbat setScriptName:[NSSWF @"%@-%@",[[pbat myTable] dbName],[pbat dbName]]];
if(![scriptDict ofk:[pbat scriptName]]){ // bei Attributen aus mehrfach verwendeten abstract tables kann es sein, dass script bereits vorliegt
// imports aufloesen, Kommentare raus
[scriptDict setObject:[self statementsForScript:expression dirName:@"Scripts" suffix:@".script"] forKey:[pbat scriptName]];
}
}
}
}
}
- (NSMutableDictionary *)executeScriptNamed:(NSString *)s1 datasource:(PBWOEditor *)datasource parmDict:(NSMutableDictionary *)p_parmDict;
{// das Script mit Name s1 ausfuehren, das bereits geladen ist
NSArray *a2;
a2 = [scriptDict ofk:s1];
if(!a2){ // bei Events ist es eher normal, dass das script nicht da ist
return p_parmDict;
}
[scriptStatistic setObject:NSS([[scriptStatistic ofk:s1]intValue] + 1) forKey:s1];
return [self executeScriptNamed:s1 statements:a2 datasource:(PBWOEditor *)datasource parmDict:p_parmDict pdf:nil continueMode:NO];
}
- (void)provideEnvironmentInVardict:(NSMutableDictionary *)varDict;
{ NSCalendarDate *date = [NSCalendarDate date];
[varDict setSecureObject:MANDANTPATH forKey:@"_MANDANTPATH"];
if(CURRENTUSER)[varDict setSecureObject:CURRENTUSER forKey:@"_user"];
[varDict setSecureObject:myFM forKey:@"_myFM"];
[varDict setSecureObject:[date descriptionWithCalendarFormat:@"%Y%m%d000000"] forKey:@"_today"];
}
- (NSMutableDictionary *)executeScriptNamed:(NSString *)v script:(NSString *)s1 datasource:(PBWOEditor *)datasource parmDict:(NSMutableDictionary *)p_parmDict;
{//das Script namens v ausfuehren, dessen source in s1 enthalten ist;
//greift nicht auf bereits geladene scripts in scriptDict zurueck
//imports werden aufgeloest
//name muss eindeutig sein wg. matchingEndif etc.
NSArray *a;
if(!FILLED(s1))return p_parmDict;
if(!FILLED(v))return p_parmDict;
a = [self statementsForScript:s1 dirName:@"Scripts" suffix:@".script"]; // imports aufloesen, Kommentare raus
return [self executeScriptNamed:v statements:a datasource:(PBWOEditor *)datasource parmDict:p_parmDict pdf:nil continueMode:NO];
}
- (NSMutableDictionary *)continueScript;
{ [_SESSION setDialogMode:NO]; // die einzige Stelle, wo dialogMode zurueckgesetzt wird; solange dialogMode YES ist, wird kein anderes Script ausgefuehrt;
if(![_SESSION cs_v])return nil; // kein script zum fortsetzen
return [self executeScriptNamed:[_SESSION cs_v] statements:[_SESSION cs_a] datasource:(PBWOEditor *)[_SESSION cs_datasource] parmDict:[_SESSION cs_p_parmDict] pdf:nil continueMode:YES];
if(![_SESSION dialogMode]){ // wenn nicht erneut in DialogMode, das zeug freigeben [_SESSION setCs_v:nil];
[_SESSION setCs_a:nil];
[_SESSION setCs_datasource:nil];
[_SESSION setCs_p_parmDict:nil];
[_SESSION setCs_stack:nil];
[_SESSION setCs_varDictStack:nil];
[_SESSION setCs_varDict:nil];
[_SESSION setCs_localVarDict:nil];
[_SESSION setCs_foreachStack:nil];
}
}
- (NSMutableDictionary *)executeScriptNamed:(NSString *)v statements:(NSArray *)a datasource:(PBWOEditor *)datasource parmDict:(NSMutableDictionary *)p_parmDict pdf:(PBPDFDoc *)pdf continueMode:(BOOL)continueMode;
{// ein fertig vorbereitetes script ausfuehren; einzelne Zeilen sind in statements
// imports sind aufgeloest, kommentare raus gefiltert
NSString *s;
NSString *op = @"NOOP";
NSArray *a1;
LMAN(ops);
NSString *op1=nil,*op2=nil,*op3=nil,*op4=nil;
NSString *opx;
NSRange r;
LMAN(stack); // returnstack des program counter
LMAN(varDictStack); // localVardict
LMAN(foreachStack); // enthaelt Foreach-Objekte
NSMutableDictionary *varDict = [NSMutableDictionary dictionaryWithCapacity:100],*localVarDict=nil;
BOOL debug = NO; //wenn YES, einzelne Statements loggen
NSAutoreleasePool *localPool = nil;
int i,j,stc=0,ii,jj; // i ist der program counter
NSString *scriptTyp = (pdf?@"PDF_":@"Script_");
NSString *lookupName = [NSSWF @"%@%@",scriptTyp,v]; // verhinderung namespace collision mit pdf; v ist der name des scripts;
// PDF-Variablen
NSString *lastFont;
NSString *dash;
float lastSize = 11.0;
float lineWidth = 1.0;
float lastEndpos = 0.0; //von Textstrings
float lastYpos = 0.0; //von Textstrings
float ulx1 = 0.0;
int fromTop = 842;
int alignment;
BOOL underlinePending = NO;
NSString *dfn=nil;
NSString *pn;
NSString *fn_ext;
NSString *path;
if([_SESSION dialogMode])return varDict; // keine weiteren Scripts nachdem Ja/Nein geklickt wurde
if(pdf){ lastFont = [@"Helvetica" retain];
dash = [@"[ ] 0" retain];
pn = [[v componentsSeparatedByString:@"/"]componentsJoinedByString:@"_"];
fn_ext = [NSSWF @"%@_%@.pdf",[_SESSION sessionID],currentTempName];
path = [self currentPDFPath];
[self setCurrentPDFName:v];
xOffset = 0;
yOffset = 0;
[self setRestString:nil];
[varDict setObject:[NSSWF @"/Aprica2_%@/temp/%@_%@.pdf",mandant,[_SESSION sessionID],currentTempName]forKey:@"_url"];
[varDict setObject:fn_ext forKey:@"_fn_ext"];
[varDict setObject:currentTempName forKey:@"_ts"];
[varDict setObject:pn forKey:@"_name"];
[varDict setObject:path forKey:@"_path"];
[varDict setObject:[path stringWithBackSlashes] forKey:@"_path_back_slash"];
[varDict setObject:lastFont forKey:@"_lastFont"];
[varDict setObject:@"11" forKey:@"_lastSize"];
// dBase style printing
[varDict setObject:@"0" forKey:@"?line"];
[varDict setObject:@"10" forKey:@"?size"];
[varDict setObject:@"100" forKey:@"?leftMargin"];
[varDict setObject:@"120" forKey:@"?topMargin"];
[varDict setObject:@"40" forKey:@"?cr"];
[varDict setObject:@"Courier" forKey:@"?font"];
}
if(continueMode){ // Script wieder fortsetzen; stack = [_SESSION cs_stack];
varDictStack = [_SESSION cs_varDictStack];
varDict = [_SESSION cs_varDict];
localVarDict = [_SESSION cs_localVarDict];
foreachStack = [_SESSION cs_foreachStack];
debug = [_SESSION cs_debug];
i = [_SESSION cs_i];
j = [_SESSION cs_j];
// LOGS(([NSSWF @"i=%i j=%i",i,j]));
stc = 0;
[varDict setObject:[_SESSION _rv] forKey:@"_rv"];
}else{ [_SESSION inc_scriptStackDepth];
if([[[_APP configDict]ofk:@"logscriptnames"]iE:@"J"] && ![v rangeOfString:@"-"].length){ LOG(([NSSWF @"%@> start %@ %@",[@"---------------------" secureSubstringToIndex:[_SESSION scriptStackDepth]],scriptTyp,v]));
}else{ if([_APP logActions] && ([_SESSION scriptStackDepth]==1)){ LOG(([NSSWF @"-> start Script %@",v]));
}
}
[scriptNames addObject:v];
[self provideEnvironmentInVardict:varDict];
[varDict addEntriesFromDictionary:p_parmDict];
i=0;
j=[a count];
}
NS_DURING;
for(;i<j;i++){ if(!(stc%3000)){ [localPool release];
localPool = [[NSAutoreleasePool alloc]init];
}
stc++;
s = [a oai:i];
if(!FILLED(s))continue;
// kommentare sind hier schon rausgefiltert
if(debug){ LOGS(([NSSWF @"--- %@",s]));
}
if([s hasSecurePrefix:@"#"])continue; // preprocessor, script validator
if([s hasSecurePrefix:@"debug"]){ debug=YES;
continue;
}
if([s hasSecurePrefix:@"nodebug"] || [s hasSecurePrefix:@"enddebug"]){ debug=NO;
continue;
}
if([s hasSecurePrefix:@"endif"]){ continue;
}
// Wertzuweisungen
if([s hasPrefix:@"$"] || [s hasPrefix:@"%"]){ //Variable setzen $ bla,=,1; % extern, $ intern NSString *varName,*val1,*s1;
BOOL intern = [s hasPrefix:@"$"];
double varVal=0;
NSObject *targetObject; // f. [targetObject takeValue: forKey:targetKey]
NSString *targetKey;
NSObject *oldObject;
s1 = [s substringFromIndex:1];
a1 = [s1 componentsSeparatedByString:@","];
if([a1 count]<3)goto BADSTATEMENT;
varName = [a1 oai:0];
[self determineTargetObject:&targetObject andKey:&targetKey forKeyPath:varName datasource:datasource intern:intern varDict:varDict localVarDict:localVarDict];
if(!targetObject){ LOGS(([NSSWF @"targetObject nicht erhalten von: %@",varName]));
goto BADSTATEMENT;
}
if(!targetKey){ LOGS(([NSSWF @"targetKey nicht erhalten von: %@",varName]));
goto BADSTATEMENT;
}
oldObject = [targetObject vfk:targetKey]; // fuer a,au,+,-,/,*,d+,d-
op = [[a1 oai:1]lowercaseString]; // der operand
//der erste Operand, der mit doubleQuote beginnt, geht bis zum Ende der Zeile
[ops removeAllObjects];
[self determineOperands:[a1 arrayFromIndex:2] datasource:datasource varDict:varDict localVarDict:localVarDict into:ops];
op1 = op2 = op3 = op4 = 0;
op1 = [ops firstObject];
if([ops count]>1)op2 = [ops oai:1];
if([ops count]>2)op3 = [ops oai:2];
if([ops count]>3)op4 = [ops oai:3];
if([op iE:@"spf"]){ //sprintf NSString *fs = op1; //formatString;
LMA;
for(ii=1,jj=[ops count];ii<jj;ii++){ s1 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"Parm %i: %@",ii,s1]));
}
if([s1 isKindOfClass:[NSArray class]]){ [lma addObjectsFromArray:(NSArray *)s1];
}else{ [lma addObject:s1];
}
}
s1 = [NSString stringWithFormat:fs andParmStrings:lma];
}else if([op iE:@"="]){ // string u. numerisch gleichermassen s1 = [ops firstObject];
}else if([op iE:@"ml"]){ // multi line string ab naechster Zeile bis \end LMAN(mla);
i++;
while(i<[a count]){ s1 = [a oai:i];
if([s1 iE:@"\\end"]){ break;
}
[mla addObject:s1];
i++;
}
s1 = (NSString *)mla;
}else if([op iE:@"=:"] || [op iE:@":="]){ // zuweisung formatiert nach EO (der linke operand muss ein EO feld sein) s1 = [ops firstObject];
s1 = [[[(PBEO *)targetObject myTable] plainAttrNamed: targetKey] formatStringValue:s1];
}else if([op iE:@"a"]){ //append string(s), add Objects s1 =(NSString *)oldObject;
if(!s1)s1 = EON;
for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *s2 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"Parm %i: %@",ii,s2]));
}
if([s1 isKindOfClass:[NSMutableString class]]){ [(NSMutableString *)s1 appendString:[s2 description]];
continue;
}
if([s1 isKindOfClass:[NSString class]]){ s1 = [s1 stringByAppendingString:[s2 description]];
continue;
}
if([s1 isKindOfClass:[NSMutableArray class]]){ if([s2 isKindOfClass:[NSArray class]]){ [(NSMutableArray *)s1 addObjectsFromArray:(NSArray *)s2];
}else{ [(NSMutableArray *)s1 addObject:s2];
}
continue;
}
if([s1 isKindOfClass:[NSMutableSet class]]){ [(NSMutableSet *)s1 addObject:s2];
continue;
}
if([s1 isKindOfClass:[NSMutableData class]]){ if([s2 isKindOfClass:[NSData class]]){ [(NSMutableData *)s1 appendData:(NSData *)s2];
}else if([s2 isKindOfClass:[NSString class]]){ [(NSMutableData *)s1 appendData:(NSData *)[s2 dataUsingEncoding:NSUTF8StringEncoding]];
}else{ LOGS(([NSSWF @"%@ cannot be appended to a MutableData",[s2 description]]));
}
continue;
}
if([s1 isKindOfClass:[NSMutableDictionary class]]){ if([s2 isKindOfClass:[NSDictionary class]]){ [(NSMutableDictionary *)s1 addEntriesFromDictionary:(NSDictionary *)s2];
}
continue;
}
}
}else if([op iE:@"au"]){ //addUniq; nur fuer Arrays s1 =(NSString *)oldObject;
if(![s1 isKindOfClass:[NSMutableArray class]]){ LOGS(@"not a NSMutableArray");
goto BADSTATEMENT;
}
for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *s2 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"Parm %i: %@",ii,s2]));
}
if(!s2)continue;
if([s2 isKindOfClass:[NSArray class]]){ [(NSMutableArray *)s1 addObjectsUniq:(NSArray *)s2];
}else{ [(NSMutableArray *)s1 addObjectUniq:s2];
}
}
}else if([op iE:@"ah"]){ //append hex; einzelne Bytes unsigned char c;
s1 =(NSString *)oldObject;
if(![s1 isKindOfClass:[NSMutableData class]]){ LOGS(@"not a NSMutableData");
goto BADSTATEMENT;
}
for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *s2 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"Parm %i: %@",ii,s2]));
}
if(!s2)continue;
if(![s2 isKindOfClass:[NSString class]])continue;
if([s2 length]!=2)continue;
c = [s2 hexValue];
[(NSMutableData *)s1 appendBytes:&c length:1];
}
}else if([op iE:@"find"]){// find,string,suchstring,{start,option} suchstring in string ab Position start suchen;// liefert position innerhalb string oder -1 falls nicht
// gefunden;
// option: ci = case insensitive
int find_start = [op3 intValue];
if(!FILLED(op1) || !FILLED(op2) || [op2 length] > [op1 length] || (find_start > ([op1 length] - [op2 length]))){ s1 =@"-1";
}else if([op1 iE:op2]){ s1 =@"0";
}else{ unsigned mask = 0;
NSRange r;
if([op4 iE:@"ci"])mask = NSCaseInsensitiveSearch;
if(find_start){ NSRange searchRange = {find_start,[op1 length]-find_start}; r = [op1 rangeOfString:op2 options:mask range:searchRange];
}else{ r = [op1 rangeOfString:op2 options:mask];
}
if(!r.length){ s1 =@"-1";
}else{ s1 = NSS(r.location);
}
}
}else if([op iE:@"ss"]){ //ss substring string,von,laenge if([a1 count] != 5)goto BADSTATEMENT;
s1 = [op1 secureSubstringFromIndex:[op2 intValue]];
if(![[op3 lowercaseString] iE:@"e"]){ s1 = [s1 secureSubstringToIndex:[op3 intValue]];
}
}else if([op iE:@"geteopkvalue"]){ //eo fetchen if([a1 count] != 4)goto BADSTATEMENT;
if(FILLED(op1) && FILLED(op2)){ s1 = (NSString *)getEOPkValue(op1,op2); //ist ein eo eigentlich
}else{ s1 = nil; //damit es keine exception gibt, wenn pkValue nicht gefuellt
}
}else if([op iE:@"geteoq"]){ //getEOQ,entityName,Qualifier if([a1 count] != 4)goto BADSTATEMENT;
if(op2 && ![op2 isKindOfClass:[PBSQLQualifier class]])goto BADSTATEMENT;
s1 = (NSString *)getEOQ(op1,(PBSQLQualifier *)op2);
}else if([op iE:@"geteoqf"]){ //getEOQf,entityName,Qualifierformat if([a1 count] != 4)goto BADSTATEMENT;
s1 = (NSString *)getEOQf(op1,op2);
}else if([op iE:@"geteosq"]){ //getEOsQ,entityName,Qualifier if([a1 count] != 4)goto BADSTATEMENT;
if(op2 && ![op2 isKindOfClass:[PBSQLQualifier class]])goto BADSTATEMENT;
s1 = (NSString *)getEOsQ(op1,(PBSQLQualifier *)op2);
}else if([op iE:@"geteosqf"]){ //getEOsQf,entityName,Qualifierformat if([a1 count] != 4)goto BADSTATEMENT;
s1 = (NSString *)getEOsQf(op1,op2);
}else if([op iE:@"geteosqsoa"]){ //getEOsQSoa,entityName,Qualifier,soa; optionaler limit-Count if([a1 count] < 5)goto BADSTATEMENT;
if(FILLED(op2) && ![op2 isKindOfClass:[PBSQLQualifier class]])goto BADSTATEMENT;
if(op3 && ![op3 isKindOfClass:[NSArray class]])goto BADSTATEMENT;
if(!FILLED(op2))op2=nil;
s1 = (NSString *)[_APP getEOs:op1 qualifier:(PBSQLQualifier *)op2 offset:0 count:[op4 intValue] soa:(NSArray *)op3];
}else if([op iE:@"soafrom"]){ //$name,soaFrom,op1,... macht sortorder Array in $name; op1... sind die feldnamen mit angehaengtem :a bzw. :d LMA;
for(ii=0,jj=[ops count];ii<jj;ii++){ s1 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"soa-Key %i: %@",ii,s1]));
}
[lma addObject:s1];
}
s1 = (NSString *)[NSArray soaADFrom:[lma componentsJoinedByString:@","]];
}else if([op iE:@"newfile"]){ // liefert Filehandle [@"" WTF:op1];
if(![myFM fileExistsAtPath:op1]){ LOG(([NSSWF @"konnte File %@ nicht anlegen",op1]));
goto BADSTATEMENT;
}
s1 = (NSString *)[NSFileHandle fileHandleForUpdatingAtPath:op1];
[(NSFileHandle *)s1 seekToEndOfFile];
}else if([op iE:@"neweo"]){ // s1 = (NSString *)NEW_EO(op1);
}else if([op iE:@"newstring"]){ // int capacity=[op1 intValue];
if(capacity <10)capacity=10;
if(capacity > 1000)capacity=1000;
s1 = (NSString *)[NSMutableString stringWithCapacity:capacity];
[(NSMutableString *)s1 setString:@""];
}else if([op iE:@"newdata"]){ // int capacity=[op1 intValue];
if(capacity <1000)capacity=1000;
if(capacity > 1000000)capacity=1000000;
s1 = (NSString *)[NSMutableData dataWithCapacity:capacity];
}else if([op iE:@"newarraye"]){ // Array aus elementen s1 = [NSMutableArray arrayWithCapacity:10];
for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *s2 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"Parm %i: %@",ii,s2]));
}
if([s2 isKindOfClass:[NSArray class]]){ [(NSMutableArray *)s1 addObjectsFromArray:(NSArray *)s2];
}else{ [(NSMutableArray *)s1 addObject:s2];
}
}
}else if([op iE:@"cat"]){ // string aus elementen mit " " vercattet s1 = [NSMutableArray arrayWithCapacity:10];
for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *s2 = [ops oai:ii];
if(debug){ LOGS(([NSSWF @"Parm %i: %@",ii,s2]));
}
if([s2 isKindOfClass:[NSArray class]]){ [(NSMutableArray *)s1 addObjectsFromArray:(NSArray *)s2];
}else{ [(NSMutableArray *)s1 addObject:s2];
}
}
s1 = [(NSArray *)s1 componentsJoinedByString:@" "];
}else if([op iE:@"newarray"]){ // int capacity=[op1 intValue];
if(capacity <10)capacity=10;
if(capacity > 1000)capacity=1000;
s1 = (NSString *)[NSMutableArray arrayWithCapacity:capacity];
}else if([op iE:@"class"]){ // class pointer s1 = (NSString *)NSClassFromString(op1);
}else if([op iE:@"newdict"]){ // int capacity=[op1 intValue];
if(capacity <10)capacity=10;
if(capacity > 1000)capacity=1000;
s1 = (NSString *)[NSMutableDictionary dictionaryWithCapacity:capacity];
}else if([op iE:@"newset"]){ // int capacity=[op1 intValue];
if(capacity <10)capacity=10;
if(capacity > 1000)capacity=1000;
s1 = (NSString *)[NSMutableSet setWithCapacity:capacity];
}else if([op iE:@"count"]){ // if([op1 isKindOfClass:[NSString class]]){ s1 = NSS([op1 length]);
}else if([op1 respondsToSelector:@selector(count)]){ s1 = NSS([(NSArray *)op1 count]);
}else{ s1 = @"0";
}
}else if([op iE:@"oai"]){ //$v,oai,$array,$index if([a1 count]!=4){ goto BADSTATEMENT;
}else{ int index;
if(![op1 respondsToSelector:@selector(objectAtIndex:)]){ goto BADSTATEMENT;
}
if([op2 respondsToSelector:@selector(intValue)]){ index = [op2 intValue];
}else{ goto BADSTATEMENT;
}
if(index < [(NSArray *)op1 count]){ s1 = [(NSArray *)op1 oai:index];
}else{ s1 = nil;
}
}
}else if([op iE:@"ofk"]){ //$v,ofk,$dict,$key if([a1 count]!=4){ goto BADSTATEMENT;
}else{ if(![op1 respondsToSelector:@selector(objectForKey:)]){ goto BADSTATEMENT;
}
if(!op2)goto BADSTATEMENT;
s1 = (NSString *)[(NSDictionary *)op1 ofk:op2];
}
}else if([op iE:@"css"]){ //$v,css,$string,$sep if([a1 count]!=4){ goto BADSTATEMENT;
}else{ if(![op1 respondsToSelector:@selector(componentsSeparatedByString:)]){ goto BADSTATEMENT;
}
if(!FILLED(op2))goto BADSTATEMENT;
if(![op2 isKindOfClass:[NSString class]])goto BADSTATEMENT;
s1 = (NSString *)[op1 componentsSeparatedByString:op2];
}
}else if([op iE:@"cjs"]){ //$v,cjs,$array,$join if([a1 count]!=4){ goto BADSTATEMENT;
}else{ if(![op1 respondsToSelector:@selector(componentsJoinedByString:)]){ goto BADSTATEMENT;
}
if(!op2)goto BADSTATEMENT;
if(![op2 isKindOfClass:[NSString class]])goto BADSTATEMENT;
s1 = [(NSArray *)op1 componentsJoinedByString:op2];
}
}else if([op iE:@"cai"]){ //$v,cai,$string,$index if([a1 count]!=4){ goto BADSTATEMENT;
}else{ int index;
if(![op1 respondsToSelector:@selector(characterAtIndex:)]){ goto BADSTATEMENT;
}
if([op2 respondsToSelector:@selector(intValue)]){ index = [op2 intValue];
}else{ goto BADSTATEMENT;
}
if(index < [op1 length]){ unichar c = [op1 characterAtIndex: index];
s1 = [NSString stringWithCharacters:&c length:1];
}else{ s1 = EON; // nie nil zurueckgeben
}
}
}else if([op iE:@"allk"]){ //$v,allk,$dict if(![op1 respondsToSelector:@selector(allKeys)]){ goto BADSTATEMENT;
}
s1 = (NSString *)[(NSDictionary *)op1 allKeys];
}else if([op iE:@"description"]){ //$v,description,$o s1 = [op1 description];
}else if([op iE:@"modul"]){ //modul,modulName liefert das Modul namens modulNa s1 = MODUL(op1);
}else if([op iE:@"allv"]){ //$v,allv,$dict if(![op1 respondsToSelector:@selector(allValues)]){ goto BADSTATEMENT;
}
s1 = (NSString *)[(NSDictionary *)op1 allValues];
}else if([op iE:@"q"] || [op iE:@"sqlq"]){ //$name,q,op1 macht pbsqlqualifier mit qualifierformat op1 s1 = (NSString *)[PBSQLQualifier qualifierWithString:op1];
}else if([op iE:@"qand"]){ //qand,array macht einen and-qualifier if(![op1 isKindOfClass:[NSArray class]])goto BADSTATEMENT;
s1 = (NSString *)[PBSQLQualifier andQualifierWithArray:(NSArray *)op1];
}else if([op iE:@"qor"]){ //qor,array macht einen or-qualifier if(![op1 isKindOfClass:[NSArray class]])goto BADSTATEMENT;
s1 = (NSString *)[PBSQLQualifier orQualifierWithArray:(NSArray *)op1];
}else if([op iE:@"allq"]){ // allQualifier s1 = (NSString *)PBALLQ;
}else if([op iE:@"nothingq"]){ // Nothing-Qualifier s1 = (NSString *)PBNOTHINGQ;
}else if([op iE:@"setfetchcond"]){ //$name,setFetchCond,op1,op2,op3,op4[,op5] enspricht: qualifier,entityName,soa,handle,limit; liefert J oder N; int fetchlimit=0;
if([a1 count]<6){ LOGS((@"Usage: $name,setFetchCond,qualifier,entityName,soa,handle[,limit]"));
goto BADSTATEMENT;
}
if(!FILLED(op3))op3 = nil;
if(!FILLED(op4))op4 = nil;
if([a1 count]>6)fetchlimit = [[ops oai:4]intValue];
if([_APP setFetchCond:(PBSQLQualifier *)op1 forTable:[myDD tableNamed:op2] soa:(NSArray *)op3 handle:op4 limit:fetchlimit]){ s1=@"J";
}else{ s1=@"N";
}
}else if([op iE:@"nextmdforhandle"]){ //$name,nextMDForHandle,op1 liefert in $name das MD bzw. nil, wenn nix mehr da s1 = (NSString *)[_APP nextMDForHandle:op1];
}else if([op iE:@"nexteoforhandle"]){ //$name,nextMDForHandle,op1 liefert in $name das EO bzw. nil, wenn nix mehr da s1 = (NSString *)[_APP nextEOForHandle:op1];
}else if([op iE:@"swcof"]){ //string with contents of file if(![myFM fileExistsAtPath:op1]){ s1=EON;
}else{ s1 = [NSSWCOF op1];
}
}else if([op iE:@"attributes"]){ //file-Attribute s1 = EON;
if([myFM fileExistsAtPath:op1]){ s1 = (NSString *)[myFM fileAttributesAtPath:op1 traverseLink:NO]; //ist ein dictionary eigentlich
}
}else if([op iE:@"lookup"]){ //in tabelle nachschlagen NSString *lookupDictName,*lookupRow,*lookupCol;
NSDictionary *lookupDict;
if([a1 count]!=5){ LOGS((@"Usage: lookup,$lookupName,$row,$col"));
goto BADSTATEMENT;
}
lookupDictName = op1;
lookupRow = op2;
lookupCol = op3;
lookupDict = [varDict ofk:lookupDictName]; //liegt immer im globalen
if(!lookupDict){ LOGS(([NSSWF @"no such lookupDict:%@ ",lookupDictName]));
goto BADSTATEMENT;
}
s1 = [[lookupDict ofk:lookupRow]ofk:lookupCol];
if(!s1)s1=EON;
}else if([op iE:@"singlevaluesql"]){ //getSingleValueAsResultFrom s1 = [_APP getSingleValueAsResultFrom:op1];
}else if([op iE:@"singlerecordsql"]){ //getDictAsResultFrom s1 = (NSString *)[_APP getDictAsResultFrom:op1];
}else if([op iE:@"arraysql"]){ //macht getArrayAsResultFrom:sql, liefert ein array of dictionaries s1 = (NSString *)[_APP getArrayAsResultFrom:op1];
}else if([op iE:@"arraysqls"]){ //macht getArrayAsResultFrom:sql, liefert ein array of strings s1 = (NSString *)[_APP getStringArrayAsResultFrom:op1];
}else if([op iE:@"nowformat"]){ //now with format s1 = (NSString *)[[NSCalendarDate date]descriptionWithCalendarFormat:op1];
}else if([op iE:@"tablenamed"]){ //Tabelle besorgen if(!FILLED(op1))goto BADSTATEMENT;
s1 = (NSString *)[myDD tableNamed:op1];
}else if([op iE:@"d+"]){ // date add; oldObject muss ein normalizedDate sein if(!FILLED(op1))goto BADSTATEMENT;
if(!FILLED(op2))goto BADSTATEMENT; // y,m,d,w,wd,H,M,S
if(!oldObject)goto BADSTATEMENT;
s1 = (NSString *)[(NSString *)oldObject nd_by_adding:[op1 intValue] interval:op2];
}else if([op iE:@"d-"]){ // date add; oldObject muss ein normalizedDate sein if(!FILLED(op1))goto BADSTATEMENT;
if(!FILLED(op2))goto BADSTATEMENT; // y,m,d,w,wd,H,M,S
if(!oldObject)goto BADSTATEMENT;
s1 = (NSString *)[(NSString *)oldObject nd_by_adding:[op1 intValue] * -1 interval:op2];
}else if([op iE:@"dd"]){ // date difference; op1 u. op2 muessen normalizedDate sein if(!FILLED(op1))goto BADSTATEMENT;
if(!FILLED(op2))goto BADSTATEMENT;
s1 = [NSSWF @"%f",[(NSString *)op2 nd_deltaSecondsTo:op1]]; // op1 - op2
}else{ if([a1 count]>3)goto BADSTATEMENT;
val1 = op1;
if(!oldObject)oldObject=EON;
varVal = [(NSString *)oldObject doubleValue];
if([op iE:@"+"]){ s1 = [NSSWF @"%f",(varVal+[val1 doubleValue])];
}else if([op iE:@"-"]){ s1 = [NSSWF @"%f",(varVal-[val1 doubleValue])];
}else if([op iE:@"*"]){ s1 = [NSSWF @"%f",(varVal*[val1 doubleValue])];
}else if([op iE:@"/"] && [val1 doubleValue]!=0.0){ s1= [NSSWF @"%f",(varVal/[val1 doubleValue])];
}else if([op iE:@"m"] && [val1 intValue]){ s1= [NSSWF @"%i",((int)varVal%[val1 intValue])];
}else{ LOGS((@"falscher Zuweisungsbefehl"));
goto BADSTATEMENT;
}
}
//s1 koennte auch nil sein, was dann eine exception gibt, wenn man es ins varDict tun will
if(!s1 && [targetObject isKindOfClass:[NSMutableDictionary class]]){ [(NSMutableDictionary *)targetObject removeObjectForKey:targetKey];
}else{ NS_DURING;
[targetObject takeValue:s1 forKey:targetKey];
NS_HANDLER;
LOGS_Ex(([NSSWF @"value %@ keyPath: %@",s1,varName]));
NS_ENDHANDLER;
}
if(debug){ LOGS(([NSSWF @"%@ neu: %@",varName,s1]));
}
continue;
}
// -----------------------------------------------------------------------------------------
// sonstige Befehle:
// Aufbau:Befehl [, Space, Operanden mit Komma getrennt]
[ops removeAllObjects];
op1 = op2 = op3 = op4 = 0;
r = [s rangeOfString:@" "];
if(r.length){ op = [[s substringToIndex:r.location]lowercaseString];
[self determineOperands:[[s substringFromIndex:(r.location + r.length)]componentsSeparatedByString:@","] datasource:datasource varDict:varDict localVarDict:localVarDict into:ops];
if([ops count])op1 = [ops oai:0];
if([ops count]>1)op2 = [ops oai:1];
if([ops count]>2)op3 = [ops oai:2];
if([ops count]>3)op4 = [ops oai:3];
}else{ op = [s lowercaseString];
}
// ###
if([op iE:@"say"] || [op iE:@"sayw"]){ // in scratchpad schreiben say clear; say x,y,{l,r},value; sayw x,y,{l,r},w,value NSMutableArray *scratchpad;
unichar c = 160; //
NSString *l_s = [NSString stringWithCharacters:&c length:1];
int l_i,l_j;
BOOL vw = [op iE:@"sayw"];
int x=[op1 intValue],y=[op2 intValue],msl,w=0;
NSString *ms=EON;
NSRange msr;
scratchpad = [p_parmDict ofk:@"scratchpad"];
if(([ops count]==1 && [op1 iE:@"clear"]) || !scratchpad){ NSString *s80 = [NSString stringWith:80 timesString:l_s];
if(!scratchpad){ if(debug)LOG(@"create new scratchpad");
scratchpad = [NSMutableArray arrayWithCapacity:25];
[p_parmDict setObject:scratchpad forKey:@"scratchpad"];
for(l_i=0;l_i<25;l_i++){ NSMutableString *lms=[NSMutableString stringWithCapacity:80];
[lms setString:s80];
[scratchpad addObject:lms];
}
if([op1 iE:@"clear"])continue;
}
if([op1 iE:@"clear"]){ if(debug)LOG(@"clearing scratchpad");
for(l_i=0;l_i<25;l_i++){ [[scratchpad oai:l_i] setString:s80];
}
continue;
}
}
if([ops count]<(vw?5:4)){ LOG(@"say insufficient operands"); goto BADSTATEMENT;}; if(x<0 || x>=80){ LOG(@"say x out of range"); goto BADSTATEMENT;} if(y<0 || y>=25){ LOG(@"say y out of range"); goto BADSTATEMENT;} if(vw)w=[op4 intValue];
ms = [ops oai:(vw?4:3)];
for(l_i=(vw?5:4),l_j=[ops count];l_i<l_j;l_i++){ //mutable strings stuerzen ab bei methode cString, wenn
//sie umlaute enthalten, die appended wurden
ms = [ms stringByAppendingString:[ops oai:l_i]];
}
if(w>0 && [ms length]>w)ms=[ms substringToIndex:w];
msl = [ms length];
if([op3 iE:@"l"]){ if(x + msl > 80){ ms = [ms substringToIndex:(80 - x)];
msl = [ms length];
}
msr.location = x;
}else{ if(x - msl + 1 < 0){ ms = [ms substringFromIndex:msl - x - 1];
msl = [ms length];
}
msr.location = x-msl+1;
}
msr.length = msl;
if(debug)LOG(([NSSWF @"ms=%@ msr.location=%i msr.length=%i",ms,msr.location,msr.length]));
[[scratchpad oai:y]replaceCharactersInRange:msr withString:[ms replace:@" " with:l_s]];
continue;
}
if([op iE:@"updat_eo"]){ //eo updaten PBEO *eo;
if(!FILLED(op1))goto BADSTATEMENT;
eo = (PBEO *)op1; //das eo
if(eo && [eo isKindOfClass:[PBEO class]]){ UPDAT(eo);
}
continue;
}
if([op iE:@"delet_eo"]){ //eo delete PBEO *eo;
if(!FILLED(op1))goto BADSTATEMENT;
eo = (PBEO *)op1; //das eo
if(eo && [eo isKindOfClass:[PBEO class]]){ DELET(eo);
}
continue;
}
if([op iE:@"insrt_eo"]){ //eo insert PBEO *eo;
if(!FILLED(op1))goto BADSTATEMENT;
eo = (PBEO *)op1; //das eo
if(eo && [eo isKindOfClass:[PBEO class]]){ INSRT(eo);
}
continue;
}
if([op iE:@"system"]){ //shell commando; NSString *_rv;
if(!FILLED(op1))goto BADSTATEMENT;
_rv = NSS(SYSTEM(op1));
[varDict setObject:_rv forKey:@"_rv"];
continue;
}
if([op iE:@"suchexternal"]){ // suchexternal modul,q fuehrt Suchexternal mit Qualifier q aus PBWOEditor *e;
if([ops count]!=2)goto BADSTATEMENT;
e = (PBWOEditor *)op1;
if(![e respondsToSelector:@selector(suchSuccessfulExternalQ:)]){ LOGI(([NSSWF TRANSLATION(@"Modul %@ kann nicht suchen"),[e name]]));
goto BADSTATEMENT;
}
if(!([op2 isKindOfClass:[PBSQLQualifier class]])){ LOGS(([NSSWF @"kein Qualifier:%@",op2]));
goto BADSTATEMENT;
}
if([e suchSuccessfulExternalQ:(PBSQLQualifier *)op2]){ if([datasource isKindOfClass:[PBWOEditor class]])[e setCallingModul:datasource]; //koennte auch ein Portlet sein
[datasource bringToFront:e];
}
continue;
}
if([op iE:@"executestring"]){ //anderes Script, das in einem String liegt ausfuehren mit derselben datasource u. parmdict; Name muss eindeutig sein, imports werden aufgeloest; varDict des gerufenen Scripts kommt in _rv zurureck// op1 = Name, op2 = script-Inhalt
NSDictionary *rd,*rv;
if([ops count]!=2)goto BADSTATEMENT;
rd = [_APP executeScriptNamed:op1 script:op2 datasource:datasource parmDict:p_parmDict];
rv = [rd ofk:@"scriptRC"];
if(rv){ [varDict setObject:rv forKey:@"scriptRC"]; //rueckgabewert
}
[varDict setObject:rd forKey:@"_rv"];
continue;
}
if([op iE:@"execute"]){ //anderes Script ausfuehren mit derselben datasource u. parmdict; script wird nur im scriptDict gesucht; varDict des gerufenen Scripts kommt in _rv zurureck NSDictionary *rd,*rv;
if(!FILLED(op1))goto BADSTATEMENT;
rd = [_APP executeScriptNamed:op1 datasource:datasource parmDict:p_parmDict];
rv = [rd ofk:@"scriptRC"];
if(rv){ [varDict setObject:rv forKey:@"scriptRC"]; //rueckgabewert
}
[varDict setObject:rd forKey:@"_rv"];
continue;
}
if([op hasSecurePrefix:@"log"]){ //ausdruck loggen; vorangestelltes "" nimmt den String woertlich NSString *s1;
if(![ops count])goto BADSTATEMENT;
s1 = [ops componentsJoinedByString:@" "]; // sollten strings drin sein
if([op iE:@"log"]){ LOGS(s1);
continue;
}
if([op iE:@"logi"]){ LOGI(s1);
continue;
}
if([op iE:@"logs"]){ LOG(s1);
continue;
}
continue;
}
if([op iE:@"lookupbegin"]){ NSString *lookupDictName = op1;
NSMutableDictionary *lud;
NSArray *colKeys=nil;
NSString *fs = @"\t";
int ckc = 0;
if(!FILLED(lookupDictName)){ LOGS(@"missing lookupDictName");
goto BADSTATEMENT;
}
lud = [NSMutableDictionary dictionaryWithCapacity:10];
[varDict setSecureObject:lud forKey:lookupDictName]; //immer global
while(++i<j){ NSArray *a1,*a2;
NSMutableDictionary *rowDict;
NSString *s = [a oai:i];
NSString *slc = [s lowercaseString];
if(!FILLED(s))continue; //Kommentarzeilen sind schon rausgefiltert
if(debug){ LOGS(([NSSWF @"--- %@",s]));
}
if([slc hasSecurePrefix:@"lookupend"])break;
if([slc hasSecurePrefix:@"lookupfs "]){ //custom fieldseparator NSString *s1 = [s substringFromIndex:9];
if(FILLED(s1))fs = s1;
continue;
}
if(!colKeys){ colKeys = [s componentsSeparatedByString:fs];
ckc = [colKeys count];
if(ckc <2){ LOGS(@"keine Spalten");
goto BADSTATEMENT;
}
continue;
}
a1 = [s componentsSeparatedByString:fs];
if([a1 count] < 2)continue; //Keine Zeilenwerte
a2 = [[a1 firstObject] componentsSeparatedByString:@","]; //schluesseliste; wenn nur ein schluessel auch ok
rowDict = [NSMutableDictionary dictionaryWithCapacity:10];
for(ii=1,jj=[a1 count];ii<jj && ii<ckc;ii++){ //anzahl colkeys kann unterschiedlich sein wie anzahl der zeilenwerte [rowDict setSecureObject:[a1 oai:ii] forKey:[colKeys oai:ii]];
}
for(ii=0,jj=[a2 count];ii<jj;ii++){ NSString *rowKey = [a2 oai:ii];
[lud setSecureObject:rowDict forKey:rowKey];
}
}
continue;
}
if([op iE:@"matrixbegin"]){ NSString *matrixName = op1;
NSMutableArray *matrix;
NSString *fs = @"\t";
if(!FILLED(matrixName)){ LOGS(@"missing matrixName");
goto BADSTATEMENT;
}
matrix = [NSMutableArray arrayWithCapacity:10];
[varDict setSecureObject:matrix forKey:matrixName]; //immer global
while(++i<j){ NSArray *a1;
NSString *s = [a oai:i];
NSString *slc = [s lowercaseString];
if(!FILLED(s))continue; //Kommentarzeilen sind schon rausgefiltert
if(debug){ LOGS(([NSSWF @"--- %@",s]));
}
if([slc hasSecurePrefix:@"matrixend"])break;
if([slc hasSecurePrefix:@"lookupfs "]){ //custom fieldseparator NSString *s1 = [s substringFromIndex:9];
if(FILLED(s1))fs = s1;
continue;
}
a1 = [s componentsSeparatedByString:fs];
[matrix addObject:a1];
}
continue;
}
if([op iE:@"diaconfirm"]){ //Alertbox mit String, ja/nein if(!FILLED(op1))op1 = TRANSLATION(@"Sind Sie sicher?");
if(!FILLED(op2))op2 = TRANSLATION(@"Zurueck");
if(!FILLED(op3))op3 = TRANSLATION(@"Weiter");
[_SESSION setConfirmString:op1];
[_SESSION setConfirmBack:op2];
[_SESSION setConfirmContinue:op3];
[_SESSION setDialogMode:YES]; // sorgt dafuer, dass Status des Script archiviert wird u. danach forgesetzt werden kann
[_SESSION setDialogSubMode:0];
i++;
break;
}
if([op iE:@"diaalert"]){ //Alertbox; nur zu bestaetigen if(!FILLED(op1))op1 = @"Achtung";
[_SESSION setConfirmString:op1];
[_SESSION setDialogMode:YES]; // sorgt dafuer, dass Status des Script archiviert wird u. danach forgesetzt werden kann
[_SESSION setDialogSubMode:1];
i++;
break;
}
if([op iE:@"gosub"]){ // sprungziel muss konstant sein if(!FILLED(op1))goto BADSTATEMENT;
[stack insertObject:NSS(i) atIndex:0];
if(localVarDict)[varDictStack insertObject:localVarDict atIndex:0];
localVarDict = [[NSMutableDictionary alloc]initWithCapacity:10];
i = [self subNamed:op1 in:a name:lookupName];
continue;
}
if(([op hasSecurePrefix:@"endsub"] || [op hasSecurePrefix:@"return"] || [op iE:@"sub"])){// subroutinen koennen in Code eingestreut werden; einfach ueberlesen bis endsub
if([op iE:@"sub"]){ i = [self matchingEndsubFrom:i in:a name:lookupName]; //hinter subroutine pos.
continue;
}
// endsub oder return ohne sub ist bloed
if(![stack count]){ i = j; //nix im stack-> abbruch
goto BADSTATEMENT;
}
i = [[stack firstObject]intValue];
[stack removeObjectAtIndex:0];
[localVarDict release];
localVarDict = [varDictStack firstObject];
if([varDictStack count])[varDictStack removeObjectAtIndex:0];
continue;
}
if(([op hasSecurePrefix:@"else"])){ i = [self matchingEndifFrom:i in:a name:lookupName]; //wg. continue -> i++
continue;
}
if([op hasSecurePrefix:@"continuefor"]){ i = [self matchingEndforFrom:i in:a name:lookupName] - 1; // bei endfor weitermachen wg. continue -> i++
continue;
}
if(([op hasSecurePrefix:@"endwhile"] || [op hasSecurePrefix:@"continue"])){ i = [self matchingWhileFrom:i in:a name:lookupName]-1; //wg. continue -> i++ -> while ...
continue;
}
if([op hasSecurePrefix:@"breakfor"]){ [foreachStack secureRemoveLastObject];
i = [self matchingEndforFrom:i in:a name:lookupName]; // bei endfor weitermachen wg. continue -> i++
continue;
}
if([op hasSecurePrefix:@"break"]){ i = [self matchingEndwhileFrom:i in:a name:lookupName]; //hinter Schleife pos.
continue;
}
if([op iE:@"rao"]){ //remove all objects if(![op1 respondsToSelector:@selector(removeAllObjects)])goto BADSTATEMENT;
[(NSMutableArray *)op1 removeAllObjects];
continue;
}
if([op iE:@"rofk"]){ //rofk Dict,key if([ops count]!=2)goto BADSTATEMENT;
if(![op1 isKindOfClass:[NSMutableDictionary class]])goto BADSTATEMENT;
[(NSMutableDictionary *)op1 removeObjectForKey:op2];
continue;
}
if([op iE:@"sort"]){ //sort Array,soa if([ops count]!=2)goto BADSTATEMENT;
if(![op1 isKindOfClass:[NSMutableArray class]])goto BADSTATEMENT;
if(![op2 isKindOfClass:[NSArray class]])goto BADSTATEMENT;
[(NSMutableArray *)op1 sortUsingKeyOrderArray:(NSArray *)op2];
continue;
}
if([op iE:@"roai"]){ //roai Array,index int index;
if([ops count]!=2)goto BADSTATEMENT;
if(![op1 isKindOfClass:[NSMutableArray class]])goto BADSTATEMENT;
index = [op2 intValue];
if([(NSArray *)op1 count] > index){ [(NSMutableArray *)op1 removeObjectAtIndex:index];
}
continue;
}
if([op iE:@"ioai"]){ //ioai Array,index,o int index;
if([ops count]!=3)goto BADSTATEMENT;
if(![op1 isKindOfClass:[NSMutableArray class]])goto BADSTATEMENT;
index = [op2 intValue];
if((int)[(NSArray *)op1 count] > (index - 1)){ [(NSMutableArray *)op1 insertObject:op3 atIndex:index];
}else{ [(NSMutableArray *)op1 addObject:op3];
}
continue;
}
if([op iE:@"wtf"]){ //write to file: String,Path,[encoding(default:utf8)] NSStringEncoding enc;
NSData *data;
if([ops count]<2)goto BADSTATEMENT;
if([ops count]>3)goto BADSTATEMENT;
if(!([op2 isKindOfClass:[NSString class]] || [op2 isKindOfClass:[NSFileHandle class]]))goto BADSTATEMENT;
if(op3){ /*
CP1252 NSWindowsCP1252StringEncoding
ISOLatin1 NSISOLatin1StringEncoding
ISOLatin2 NSISOLatin2StringEncoding
Unicode NSUnicodeStringEncoding
ASCII NSNonLossyASCIIStringEncoding
*/
if([op3 iE:@"CP1252"]){ enc = NSWindowsCP1252StringEncoding;
}else if([op3 iE:@"ISOLatin1"]){ enc = NSISOLatin1StringEncoding;
}else if([op3 iE:@"ISOLatin2"]){ enc = NSISOLatin2StringEncoding;
}else if([op3 iE:@"Unicode"]){ enc = NSUnicodeStringEncoding;
}else if([op3 iE:@"ASCII"]){ enc = NSNonLossyASCIIStringEncoding;
}else{ LOGS(([NSSWF @"unsupported encoding: %@; use: CP1252, ISOLatin1, ISOLatin2, Unicode, ASCII",op3]));
goto BADSTATEMENT;
}
}else{ enc = NSUTF8StringEncoding;
}
data = [op1 dataUsingEncoding:enc allowLossyConversion:YES];
if([op2 isKindOfClass:[NSString class]]){ [data writeToFile:op2 atomically:YES];
}else{ [(NSFileHandle *)op2 writeData:data];
[(NSFileHandle *)op2 synchronizeFile];
}
continue;
}
if([op hasSecurePrefix:@"ps"]){ // veraltet!!! nicht mehr nehmen!!! ps sender message; psr = mit returnwert// Perform selector;
// returnwert darf nur ein NSObject sein, kein int oder double
SEL sel;
BOOL mitRW = [op iE:@"psr"];
NSObject *rw = nil;
if([ops count]<2)goto BADSTATEMENT;
if ([op2 iE:@"nil"]){ op2 = nil;
}
if ([op3 iE:@"nil"]){ op3 = nil;
}
if ([op4 iE:@"nil"]){ op4 = nil;
}
sel = SECURE_SELECTOR_FROM_STRING(op2);
if(!sel){ LOGS(([NSSWF @"selector ungueltig:%@;",op2]));
goto BADSTATEMENT;
}
if(![op1 respondsToSelector:sel]){ LOGS(([NSSWF @"%@ does not respond to selector:%@;",[op1 description],op2]));
goto BADSTATEMENT;
}
if([ops count]==2){ if(mitRW){ rw = [op1 performSelector:sel];
}else{ [op1 performSelector:sel];
}
}else if([ops count]==3){ if(mitRW){ rw = [op1 performSelector:sel withObject:op3];
}else{ [op1 performSelector:sel withObject:op3];
}
}else if([ops count]==4){ if(mitRW){ rw = [op1 performSelector:sel withObject:op3 withObject:op4];
}else{ [op1 performSelector:sel withObject:op3 withObject:op4];
}
}else{ goto BADSTATEMENT;
}
if(mitRW && rw){ [varDict setObject:rw forKey:@"_rv"];
}else{ [varDict setObject:EON forKey:@"_rv"];
}
continue;
}
if([op iE:@"invk"]){ //invk object message arg1, arg2, ...// NSInvocation;
static NSString *is_nil = @"aprica_script:nil placeholder";
NSMethodSignature *sig;
NSInvocation *invk;
NSMutableArray *args;
SEL sel;
const char *type;
id rw = EON;
int i,n; // overrides i in outer loop
if([ops count]<2)goto BADSTATEMENT;
args = (id)[NSMutableArray array];
for(ii=2,jj=[ops count];ii<jj;ii++){ id invk_op = [ops oai:ii];
if ([invk_op isKindOfClass:[NSString class]] && [invk_op iE:@"nil"]){ invk_op = is_nil;
}
[args addObject: invk_op];
}
sel = SECURE_SELECTOR_FROM_STRING(op2);
if(!sel){ LOGS(([NSSWF @"selector ungueltig:%@;",op2]));
goto BADSTATEMENT;
}
if(![op1 respondsToSelector:sel]){ LOGS(([NSSWF @"%@ does not respond to selector:%@;",[op1 description],op2]));
goto BADSTATEMENT;
}
sig = [op1 methodSignatureForSelector: sel];
if(!sig){ LOGS(([NSSWF @"keine signatur fuer selector:%@;",op2]));
goto BADSTATEMENT;
}
invk = [NSInvocation invocationWithMethodSignature: sig];
[invk setTarget: op1];
[invk setSelector: sel];
for(i=0,n=[args count]; i<n; i++){ type = [sig getArgumentTypeAtIndex: i+2];
if (*type=='r') type++; // ignore const qualifier
switch (*type) { case _C_ID:
case _C_CLASS:
{ id a = [args oai: i];
// a kann auch z.B. ein PBEO sein, dann kann dieses nicht mit NSString verglichen werden
if ([a isKindOfClass:[NSString class]] && [a iE: is_nil]) a=nil;
[invk setArgument: &a atIndex: i+2];
break;
}
case _C_SEL:
{ id a = [args oai: i];
SEL v = 0;
if ([a isKindOfClass: [NSString class]]) { v = SECURE_SELECTOR_FROM_STRING(a);
if (!v) { LOGS(([NSSWF @"selector ungueltig:%@;",op2]));
goto BADSTATEMENT;
}
} else if ([a respondsToSelector: @selector(pointerValue)]) { v = [a pointerValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to pointerValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_CHR: // We currently assume BOOL (Apple) which can cause problems for selectors that use true chars.
{ id a = [args oai: i];
char v;
if (![a respondsToSelector: @selector(boolValuePB3)]) { LOGS(([NSSWF @"argument %i: %@ does not respond to boolValuePB3;", i, [a description]]));
goto BADSTATEMENT;
}
v = [a boolValuePB3] ? YES : NO;
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_UCHR: // We currently assume BOOL (GNU) which can cause problems for selectors that use true chars.
{ id a = [args oai: i];
unsigned char v;
if (![a respondsToSelector: @selector(boolValuePB3)]) { LOGS(([NSSWF @"argument %i: %@ does not respond to boolValuePB3;", i, [a description]]));
goto BADSTATEMENT;
}
v = [a boolValuePB3] ? YES : NO;
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_SHT:
{ id a = [args oai: i];
short v;
if ([a isKindOfClass: [NSString class]]) { v = [a intValue];
} else if ([a respondsToSelector: @selector(shortValue)]) { v = [a shortValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to shortValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_USHT:
{ id a = [args oai: i];
unsigned short v;
if ([a isKindOfClass: [NSString class]]) { v = [a intValue];
} else if ([a respondsToSelector: @selector(unsignedShortValue)]) { v = [a unsignedShortValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to unsignedShortValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_INT:
{ id a = [args oai: i];
int v;
if ([a respondsToSelector: @selector(intValue)]) { v = [a intValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to intValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_UINT:
{ id a = [args oai: i];
unsigned int v;
if ([a isKindOfClass: [NSString class]]) { v = [a intValue];
} else if ([a respondsToSelector: @selector(unsignedIntValue)]) { v = [a unsignedIntValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to unsignedIntValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_LNG:
{ id a = [args oai: i];
long v;
if ([a isKindOfClass: [NSString class]]) { v = [a intValue];
} else if ([a respondsToSelector: @selector(longValue)]) { v = [a longValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to longValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_ULNG:
{ id a = [args oai: i];
unsigned long v;
if ([a isKindOfClass: [NSString class]]) { v = [a intValue];
} else if ([a respondsToSelector: @selector(unsignedLongValue)]) { v = [a unsignedLongValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to unsignedLongValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_FLT:
{ id a = [args oai: i];
float v;
if ([a respondsToSelector: @selector(floatValue)]) { v = [a floatValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to floatValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_DBL:
{ id a = [args oai: i];
double v;
if ([a respondsToSelector: @selector(doubleValue)]) { v = [a doubleValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to doubleValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_PTR:
{ id a = [args oai: i];
void *v;
if ([a respondsToSelector: @selector(pointerValue)]) { v = [a pointerValue];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to pointerValue;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
case _C_CHARPTR:
{ id a = [args oai: i];
const char *v;
if ([a respondsToSelector: @selector(cString)]) { v = [a cString];
} else { LOGS(([NSSWF @"argument %i: %@ does not respond to cString;", i, [a description]]));
goto BADSTATEMENT;
}
[invk setArgument: &v atIndex: i+2];
break;
}
default:
{ LOGS(([NSSWF @"argument %i: %@ has unsupported type '%s';", i, [a description], type]));
goto BADSTATEMENT;
}
}
}
[invk invoke];
type = [sig methodReturnType];
if (*type == 'r') type++; // skip const qualifier
switch (*type) { case _C_ID:
case _C_CLASS:
{ [invk getReturnValue: &rw];
break;
}
case _C_SEL:
{ SEL v;
[invk getReturnValue: &v];
rw = NSStringFromSelector(v);
break;
}
case _C_CHR: // We assume bool (Apple)
{ BOOL v;
[invk getReturnValue: &v];
rw = (v) ? @"J" : @"N";
break;
}
case _C_UCHR: // We assume bool (GNU)
{ unsigned char v;
[invk getReturnValue: &v];
rw = (v) ? @"J" : @"N";
break;
}
case _C_SHT:
{ short v;
[invk getReturnValue: &v];
// rw = [[NSNumber numberWithShort: v] description];
rw = NSS(v);
break;
}
case _C_USHT:
{ unsigned short v;
[invk getReturnValue: &v];
// rw = [[NSNumber numberWithUnsignedShort: v] description];
rw = NSS(v);
break;
}
case _C_INT:
{ int v;
[invk getReturnValue: &v];
rw = NSS(v);
break;
}
case _C_UINT:
{// warum durch NSNumber schleusen?
unsigned int v;
[invk getReturnValue: &v];
// rw = [[NSNumber numberWithUnsignedInt: v] description];
rw = NSS(v);
break;
}
case _C_LNG:
{ long v;
[invk getReturnValue: &v];
// rw = [[NSNumber numberWithLong: v] description];
rw = NSS(v);
break;
}
case _C_ULNG:
{ unsigned long v;
[invk getReturnValue: &v];
// rw = [[NSNumber numberWithUnsignedLong: v] description];
rw = NSS(v);
break;
}
case _C_FLT:
{ float v;
double d;
[invk getReturnValue: &v];
d = v; // ensure promotion rules are used correctly
rw = NSSD(d);
break;
}
case _C_DBL:
{ double v;
[invk getReturnValue: &v];
rw = NSSD(v);
break;
}
case _C_PTR:
{ void *v;
[invk getReturnValue: &v];
rw = [NSValue valueWithPointer: v];
break;
}
case _C_CHARPTR:
{ char *v;
[invk getReturnValue: &v];
rw = [NSString stringWithCString: v];
break;
}
case _C_VOID:
{ rw = EON;
break;
}
default:
{ LOGS(([NSSWF @"return value of type '%s' for selector %@ unsupported;", type, NSStringFromSelector(sel)]));
goto BADSTATEMENT;
break;
}
}
if (rw) { [varDict setObject:rw forKey:@"_rv"];
} else { [varDict removeObjectForKey:@"_rv"];
}
continue;
}
if([op iE:@"foreach"]){ // item,array[,index]// es muss der Zustand eines foreach-Statements gehalten werden;
// auf einem Stack
// beim erreichen eines foreach statements wird ein foreach-Objekt erzeugt und auf den Stack gelegt
// es enthaelt das Array, Name des Item, Name des Index, eigenen Index mit 0 initialisiert
// x
// dann wird geprueft, ob der interne Index >= [array count];
// ist dies nicht der Fall, wird ins varDict das [array oai:index] unter dem Name des item gestellt
// ins varDict kommt auch der interne index unter dem name, der angegeben wurde;
// dann wird der interne index im foreachObjekt erhoeht und mit dem naechsten Statement forgefahren
// ansonsten wird das foreach-Objekt vom Stack genommen und hinter dem endfor weitergemacht;
//
// bei endfor wird das foreach-Objekt ermittelt; es ist das oberste auf dem Stack; dann geht es bei x weiter;
// bei continuefor wird zum naechsten endfor gesprungen
// bei breakfor wird das foreach-Objekt vom Stack genommen und hinter dem endfor weitergemacht
Foreach *fe;
if([ops count]<2)goto BADSTATEMENT;
if([op2 isKindOfClass:[NSArray class]] && [(NSArray *)op2 count]){ fe = [[[Foreach alloc]init]autorelease];
[fe setItemName:op1];
[fe setA:(NSArray *)op2];
if(FILLED(op3)){ [fe setIndexName:op3];
[varDict setObject:NSS([fe index]) forKey:[fe indexName]];
}
if(localVarDict && [[fe itemName]hasSecurePrefix:@"l_"]){ [localVarDict setObject:[[fe a] oai:[fe index]] forKey:[fe itemName]];
}else{ [varDict setObject:[[fe a] oai:[fe index]] forKey:[fe itemName]];
}
[fe setIndex:[fe index]+1];
[foreachStack addObject:fe];
}else{ i = [self matchingEndforFrom:i in:a name:lookupName]; // hinter endfor weitermachen wg. continue -> i++
}
continue;
}
if([op hasSecurePrefix:@"endfor"]){ Foreach *fe = [foreachStack lastObject];
if(!fe)goto BADSTATEMENT;
if([fe index] < [[fe a]count]){ if(FILLED([fe indexName])){ [varDict setObject:NSS([fe index]) forKey:[fe indexName]];
}
if(localVarDict && [[fe itemName]hasSecurePrefix:@"l_"]){ [localVarDict setObject:[[fe a] oai:[fe index]] forKey:[fe itemName]];
}else{ [varDict setObject:[[fe a] oai:[fe index]] forKey:[fe itemName]];
}
[fe setIndex:[fe index]+1];
i = [self matchingForeachFrom:i in:a name:lookupName]; // hinter foreach weitermachen wg. continue -> i++
}else{ [foreachStack secureRemoveLastObject];
}
continue;
}
if(([op hasSecurePrefix:@"end"])){ i = j; //ende des druck; wg. continue -> i++
continue;
}
if(( [op iE:@"if"]) || ([op iE:@"while"])){ //bedingt ausfuehren if exp1,op,exp2 bzw. while-Schleife NSString *vgl;
double d1,d2;
BOOL negate = NO;
BOOL erg=NO;
if([ops count]<3)goto BADSTATEMENT;
vgl = op2;
if([vgl hasSecurePrefix:@"!"] && ![vgl iE:@"!="]){ negate=YES;
vgl = [vgl substringFromIndex:1];
}
if(debug){ if([vgl iE:@"in"]){ LOGS(([NSSWF @"op1=%@ op3=%@... %@;",op1,op3,[[ops arrayFromIndex:2]description]]));
}else{ LOGS(([NSSWF @"op1=%@ op3=%@;",op1,op3]));
}
}
if([vgl iE:@"in"]){ // Auflistung alternativer Werte for(ii=2,jj=[ops count];ii<jj;ii++){ opx = [ops oai:ii];
if([opx isKindOfClass:[NSArray class]]){ erg = (NSNotFound != [(NSArray *)opx indexOfObject:op1]);
}else{ erg = ([op1 iE:opx] || (!FILLED(op1) && !FILLED(opx)));
}
if(erg) break;
}
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"eq"]){ //string Vergleich erg = ([op1 iE:op3] || (!FILLED(op1) && !FILLED(op3)));
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"ne"]){ //string Vergleich erg = (![op1 iE:op3] || (!FILLED(op1) && FILLED(op3)));
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"prefix"]){ //hasPrefix erg = ([op1 hasSecurePrefix:op3]);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"suffix"]){ //hasSuffix erg = ([op1 hasSecureSuffix:op3]);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"FILLED"]){ //test auf gefuellt; geht fuer alle Objekte; erg = (FILLED(op1));
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"FILLEDNUM"]){ //test auf gefuellt und numerisch <> 0; geht fuer alle Objekte; erg = ((FILLED(op1)) && ![op1 iE:@"0"]);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"exists"]){ //test auf File existent erg = ([myFM fileExistsAtPath:op1]);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"contains"]){ //containsObject: testen for(ii=2,jj=[ops count];ii<jj;ii++){ opx = [ops oai:ii];
if([opx isKindOfClass:[NSArray class]]){ int iii,jjj;
for(iii=0,jjj=[(NSArray *)opx count];iii<jjj;iii++){ erg = ([(id)op1 containsObject:[(NSArray *)opx oai:iii]]);
if(erg){ break;
}
}
}else{ erg = ([(id)op1 containsObject:opx]);
}
if(erg){ break;
}
}
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"like"]){ //mit wildcards erg = ([op1 isLike:op3]);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"=="] || [vgl iE:@"="]){ //numerisch Vergleich; auch falsch geschrieben d1 = [op1 doubleValue];
d2 = [op3 doubleValue];
erg = (d1 == d2);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"!="]){ //numerisch Vergleich d1 = [op1 doubleValue];
d2 = [op3 doubleValue];
if(d1 != d2)continue;
}else if([vgl iE:@">"]){ //numerisch Vergleich d1 = [op1 doubleValue];
d2 = [op3 doubleValue];
erg = (d1 > d2);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"<"]){ //numerisch Vergleich d1 = [op1 doubleValue];
d2 = [op3 doubleValue];
erg = (d1 < d2);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@">="] || [vgl iE:@"=>"]){ //numerisch Vergleich d1 = [op1 doubleValue];
d2 = [op3 doubleValue];
erg = (d1 >= d2);
if(negate)erg=!erg; if(erg)continue;
}else if([vgl iE:@"<="] || [vgl iE:@"=<"]){ //numerisch Vergleich d1 = [op1 doubleValue];
d2 = [op3 doubleValue];
erg = (d1 <= d2);
if(negate)erg=!erg; if(erg)continue;
}else{ goto BADSTATEMENT;
}
if([op iE:@"if"]){ i = [self matchingEndifOrElseFrom:i in:a name:lookupName];
}else{ i = [self matchingEndwhileFrom:i in:a name:lookupName];
}
continue;
}
if([op iE:@"dbnr"]){ //setzt dbnr [_APP setDbNr:[op1 intValue]];
continue;
}
if([op hasSecurePrefix:@"autorelease"]){ [localPool release];
localPool = [[NSAutoreleasePool alloc]init];
continue;
}
if([op iE:@"lang"]){ //setzt Script-Sprache abweichend von user-sprache fuer <trans> [_SESSION setLang_script:[op1 intValue]];
continue;
}
if([op iE:@"fieldon"]){ for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *fieldName = [ops oai:ii];
// fieldOn * braucht man nicht, dafuer gibt's allFieldsOn
if([fieldName hasSecureSuffix:@"*"]){ NSArray *fields = [datasource fassos];
int i2,j2;
fieldName = [fieldName stringWithoutLastChar];
for(i2=0,j2=[fields count];i2<j2;i2++){ NSString *dbName = [[fields oai:i2]dbName];
if([dbName hasSecurePrefix:fieldName]){ [[datasource disabledFieldNames]removeObjectForKey:dbName];
[[datasource enabledFieldNames]setObject:@"" forKey:dbName];
}
}
}else{ [[datasource disabledFieldNames]removeObjectForKey:fieldName];
[[datasource enabledFieldNames]setObject:@"" forKey:fieldName];
}
}
continue;
}
if([op iE:@"fieldoff"]){ for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *fieldName = [ops oai:ii];
// fieldOff * braucht man nicht, dafuer gibt's allFieldsOff
if([fieldName hasSecureSuffix:@"*"]){ NSArray *fields = [datasource fassos];
int i2,j2;
fieldName = [fieldName stringWithoutLastChar];
for(i2=0,j2=[fields count];i2<j2;i2++){ NSString *dbName = [[fields oai:i2]dbName];
if([dbName hasSecurePrefix:fieldName]){ [[datasource disabledFieldNames]setObject:@"" forKey:dbName];
[[datasource enabledFieldNames]removeObjectForKey:dbName];
}
}
}else{ [[datasource disabledFieldNames]setObject:@"" forKey:fieldName];
[[datasource enabledFieldNames]removeObjectForKey:fieldName];
}
}
continue;
}
if([op iE:@"markerror"]){ for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *fieldName = [ops oai:ii];
[[[datasource fassosByName]ofk:fieldName]markError];
}
continue;
}
if([op iE:@"optionstd"]){ if([ops count]!=1)goto BADSTATEMENT;
{ PBWOAsso *pbas = [[datasource fassosByName]ofk:op1];
if(!pbas)continue;
if(![pbas hasVL])continue;
[[pbas _vl]removeAllObjects];
[[pbas _vl] addObjectsFromArray:[[pbas pba] vl]];
}
continue;
}
if([op iE:@"optionadd"]){ if([ops count]<3)goto BADSTATEMENT;
{ PBWOAsso *pbas = [[datasource fassosByName]ofk:op1];
if(!pbas)continue;
if(![pbas hasVL])continue;
if(!FILLED(op4))op4 = op3;
[[pbas _vl] addObject:[PBVLO pbvloWithValue:op2 bez0:op3 bez1:op4]];
}
continue;
}
if([op iE:@"optionrem"]){ if([ops count]!=2)goto BADSTATEMENT;
{ PBWOAsso *pbas = [[datasource fassosByName]ofk:op1];
NSMutableArray *pbas_vl;
if(!pbas)continue;
if(![pbas hasVL])continue;
pbas_vl = [pbas _vl];
{ int ii,jj;
for(ii=0,jj=[pbas_vl count];ii<jj;ii++){ PBVLO *pbvlo = [pbas_vl oai:ii];
if([[pbvlo value]iE:op2]){ [pbas_vl removeObjectAtIndex:ii];
break;
}
}
}
}
continue;
}
if([op hasSecurePrefix:@"allfieldson"]){ [datasource setAllFieldsDisabled:NO];
continue;
}
if([op hasSecurePrefix:@"allfieldsoff"]){ [datasource setAllFieldsDisabled:YES];
continue;
}
if([op hasSecurePrefix:@"allfieldsvisible"]){ [[datasource hiddenFieldNames]removeAllObjects];
continue;
}
if([op iE:@"fieldvisible"]){ for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *fieldName = [ops oai:ii];
if([fieldName iE:@"*"]){ [[datasource hiddenFieldNames]removeAllObjects];
continue;
}
if([fieldName hasSecureSuffix:@"*"]){ NSArray *fields = [datasource fassos];
int i2,j2;
fieldName = [fieldName stringWithoutLastChar];
for(i2=0,j2=[fields count];i2<j2;i2++){ NSString *dbName = [[fields oai:i2]dbName];
if([dbName hasSecurePrefix:fieldName])[[datasource hiddenFieldNames]removeObjectForKey:dbName];
}
}else{ [[datasource hiddenFieldNames]removeObjectForKey:fieldName];
}
}
continue;
}
if([op iE:@"fieldinvisible"]){ for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *fieldName = [ops oai:ii];
if([fieldName iE:@"*"]){ NSArray *fields = [datasource fassos];
int i2,j2;
for(i2=0,j2=[fields count];i2<j2;i2++){ NSString *dbName = [[fields oai:i2]dbName];
[[datasource hiddenFieldNames]setObject:@"" forKey:dbName];
}
continue;
}
if([fieldName hasSecureSuffix:@"*"]){ NSArray *fields = [datasource fassos];
int i2,j2;
fieldName = [fieldName stringWithoutLastChar];
for(i2=0,j2=[fields count];i2<j2;i2++){ NSString *dbName = [[fields oai:i2]dbName];
if([dbName hasSecurePrefix:fieldName])[[datasource hiddenFieldNames]setObject:@"" forKey:dbName];
}
}else{ [[datasource hiddenFieldNames]setObject:@"" forKey:fieldName];
}
}
continue;
}
if([op iE:@"registerinvisible"]){ for(ii=0,jj=[ops count];ii<jj;ii++){ NSString *fieldName = [ops oai:ii];
if([fieldName hasSecurePrefix:@">"]){ [datasource removeRegisterActionWithGuiName:fieldName];
}else{ [[datasource boxNameArray] removeObject:fieldName];
}
}
continue;
}
if([op hasSecurePrefix:@"registervisible"]){ [datasource restoreBoxNameArray];
continue;
}
if([op iE:@"createbutton"]){ [datasource setCreate_ButtonIsDisabled:[[op1 lowercaseString]iE:@"off"]];
continue;
}
if([op iE:@"duplicatebutton"]){ [datasource setDuplicate_ButtonIsDisabled:[[op1 lowercaseString]iE:@"off"]];
continue;
}
if([op iE:@"deletebutton"]){ [datasource setDelete_ButtonIsDisabled:[[op1 lowercaseString]iE:@"off"]];
continue;
}
if([op iE:@"sql"]){ //sql commando; vorangestelltes "" nimmt den String woertlich if(FILLED(op1))[_APP evaluateSQL:op1];
continue;
}
if(!pdf)goto BADSTATEMENT;
// =====================================================================================
// Druck-Kommandos
// damit kann man sich selbst ein limit setzen, um z.B. Benutzereingaben, die zuviel Seiten produzieren wuerden, abzubrechen
if([op iE:@"pages"]){ pages = [op1 intValue];
continue;
}
if([op hasSecurePrefix:@"newpageqm"]){ if(pageCount >= pages){ LOGI(([NSSWF TRANSLATION(@"max. Seitenanzahl %i f. Druck ueberschritten"),pages]));
break;
}
[varDict setObject:@"0" forKey:@"?line"];
[pdf addPage];
[CP setRotate:270];
[CP setMediaBox:PBPDF_qm];
pageCount++;
fromTop = 2835;
continue;
}
if([op hasSecurePrefix:@"newpagequer"]){ if(pageCount >= pages){ LOGI(([NSSWF TRANSLATION(@"max. Seitenanzahl %i f. Druck ueberschritten"),pages]));
break;
}
[varDict setObject:@"0" forKey:@"?line"];
[pdf addPage];
[CP setRotate:270];
[CP setMediaBox:PBPDF_A4quer];
pageCount++;
fromTop = 595;
continue;
}
if([op hasSecurePrefix:@"newpagea5quer"]){ if(pageCount >= pages){ LOGI(([NSSWF TRANSLATION(@"max. Seitenanzahl %i f. Druck ueberschritten"),pages]));
break;
}
[varDict setObject:@"0" forKey:@"?line"];
[pdf addPage];
[CP setRotate:270];
[CP setMediaBox:PBPDF_A5quer];
pageCount++;
fromTop = 298;
continue;
}
if([op iE:@"newpagewh"]){ int w,h;
NSString *mediaString;
if(pageCount >= pages){ LOGI(([NSSWF TRANSLATION(@"max. Seitenanzahl %i f. Druck ueberschritten"),pages]));
break;
}
if([ops count]!=2)goto BADSTATEMENT;
w = mmtp([op1 intValue]);
h = mmtp([op2 intValue]);
// "0 0 842 595"
mediaString = [NSSWF @"0 0 %i %i",w,h];
[varDict setObject:@"0" forKey:@"?line"];
[pdf addPage];
[CP setMediaBox:mediaString];
pageCount++;
fromTop = h;
continue;
}
if([op hasSecurePrefix:@"newpage"]){ if(pageCount >= pages){ LOGI(([NSSWF TRANSLATION(@"max. Seitenanzahl %i f. Druck ueberschritten"),pages]));
break;
}
[varDict setObject:@"0" forKey:@"?line"];
[pdf addPage];
pageCount++;
fromTop = 842;
continue;
}
if([op hasSecurePrefix:@"lsn"]){ //linestyle normal APC(@"[ ] 0 d\n");
continue;
}
if([op iE:@"scale"]){ //scale 10 -> 1/10 mm; 1 -> 1 mm scale = [op1 intValue];
if(!scale)scale = 1;
continue;
}
if([op iE:@"sprache"]){ //obsolet continue;
}
if([op iE:@"o"]){ //Delta x,y-offset o 1,2//wird auf alle Koordinaten angewendet; globale Verschiebung;
//wirkt relativ auf bisherigen Offset;
if([ops count]!=2)goto BADSTATEMENT;
xOffset += [op1 intValue];
yOffset += [op2 intValue];
continue;
}
if([op iE:@"f"]){ //font f Arial,12 NSString *newFont = op1;
NSString *ls = op2;
if(![newFont iE:lastFont]){ [lastFont release];
lastFont = [newFont retain];
[varDict setObject:lastFont forKey:@"_lastFont"];
}
if(FILLED(ls)){ [varDict setObject:ls forKey:@"_lastSize"];
lastSize = [ls floatValue];
}
continue;
}
if([op iE:@"s"]){ //size s 12 NSString *ls = op1;
[varDict setObject:ls forKey:@"_lastSize"];
lastSize = [ls floatValue];
continue;
}
if([op iE:@"lc"]){ //lineColor lc 85 100 =weiss, 0 schwarz; CHECK_PGC;
lineColor = [op1 floatValue] / 100.0;
APC(([NSSWF @"%.4f G\n",lineColor]));
if(debug){ LOGS(([NSSWF @"linecolor neu: %.0f",lineColor * 100]));
}
continue;
}
if([op iE:@"lcrgb"] || [op iE:@"lc255"] || [op iE:@"lc#"] || [op iE:@"fcrgb"] || [op iE:@"fc255"] || [op iE:@"fc#"]){ // lineColor oder fillColor r,g,b 0..100; oder 255 oder XXXXXX float r,g,b;
CHECK_PGC;
if([op hasSuffix:@"#"]){ if([ops count]!=1)goto BADSTATEMENT;
if([op1 length]!=6){ LOGS(([NSSWF @"falsche Laenge:%@",op1])); goto BADSTATEMENT;} r = (float)[[op1 substringToIndex:2]hexValue] / 255;
g = (float)[[[op1 substringFromIndex:2]substringToIndex:2]hexValue] / 255;
b = (float)[[op1 substringFromIndex:4]hexValue] / 255;
}else{ float colorBase = (([op hasSuffix:@"255"])?255.0:100.0);
if([ops count]!=3)goto BADSTATEMENT;
r = [op1 floatValue] / colorBase;
g = [op2 floatValue] / colorBase;
b = [op3 floatValue] / colorBase;
}
if(debug){ LOGS(([NSSWF @"%@ :r %.4f g %.4f b %.4f",op,r,g,b]));
}
if(r > 1.0 || g > 1.0 || b > 1.0)goto BADSTATEMENT;
if([op hasPrefix:@"lc"]){ APC(([NSSWF @"%.4f %.4f %.4f RG\n", r, g, b]));
}else{ APC(([NSSWF @"%.4f %.4f %.4f rg\n", r, g, b]));
}
continue;
}
if([op iE:@"lw"]){ //lineWidth lw 30 -> 3 mm lineWidth = [op1 floatValue];
CHECK_PGC;
APC(([NSSWF @"%.4f w\n",mmtp(lineWidth)]));
if(debug){ LOGS(([NSSWF @"linewidth neu: %.0f",lineWidth]));
}
continue;
}
if([op iE:@"ls"]){ //linestyle x1,x2 float x1,x2;
if([ops count]!=2)goto BADSTATEMENT;
x1 = mmtp([op1 floatValue]);
x2 = mmtp([op2 floatValue]);
if(x1 <=0)x1 = 1;
if(x2 <=0)x2 = 1;
[dash release];
dash = [[NSSWF @"[%.3f %.3f] 0 d\n",x1,x2]retain];
APC(dash);
continue;
}
if([op iE:@"fc"]){ //fillColor fc 85 100 =weiss, 0 schwarz; CHECK_PGC;
fillColor = [op1 floatValue] / 100.0;
[varDict setObject:op1 forKey:@"_lastFillColor"];
APC(([NSSWF @"%.4f g\n",fillColor]));
if(debug){ LOGS(([NSSWF @"fillColor neu: %.0f",fillColor*100]));
}
continue;
}
if([op iE:@"rf"] || [op iE:@"rl"]){ //rahmen filled rf x,y,dx,dy x,y Koord., width, height mit current fillStroke oder rahmen leer float x,y,w,h;
CHECK_PGC;
if([ops count]!=4)goto BADSTATEMENT;
x = mmtp([op1 floatValue] + xOffset);
y = mmtpFromTop([op2 floatValue] + yOffset);
w = mmtp([op3 floatValue]);
h = mmtp([op4 floatValue]) * -1.0;
APC(([NSSWF @"%.3f %.3f %.3f %.3f re\n", x, y, w, h]));
if([op iE:@"rl"]){ APC(@"S\n");
}else{//rahmen unsichtbar und nur fuellen; danach wieder aktuelle linienbreite
APC((@"0 w\n"));
APC(@"f\n");
APC(([NSSWF @"%.4f w\n",mmtp(lineWidth)]));
}
if(debug){ LOGS(([NSSWF @"x y w h = %.0f %.0f %.0f %.0f",ptmm(x),ptmmFromTop(y),ptmm(w),ptmm((-1 * h))]));
}
continue;
}
if([op iE:@"kf"] || [op iE:@"kl"]){ //kreis filled lf x,y,r x,y Mittelp., Radius mit current fillStroke float x,y,r,kappa = 0.5522847498; // 4 segmente zeichnen s. http://www.whizkidtech.redprince.net/bezier/circle/kappa/
CHECK_PGC;
if([ops count]!=3)goto BADSTATEMENT;
x = mmtp([op1 floatValue] + xOffset);
y = mmtpFromTop([op2 floatValue] + yOffset);
r = mmtp([op3 floatValue]);
// 100 150 m begin path
// 100 83.333 200 83.333 200 150 c cubic bezier, 2 stuetzpunkte, zielpunkt
// 200 216.666 100 216.666 100 150 c
APC(([NSSWF @"%.3f %.3f m\n", x, y - r])); // start open
APC(([NSSWF @"%.3f %.3f %.3f %.3f %.3f %.3f c\n", x + kappa, y - r,x + r, y - kappa, x + r, y])); // ziel rechts
APC(([NSSWF @"%.3f %.3f %.3f %.3f %.3f %.3f c\n", x + r, y + kappa,x + kappa, y + r, x, y + r])); // ziel unten
APC(([NSSWF @"%.3f %.3f %.3f %.3f %.3f %.3f c\n", x - kappa, y + r,x - r, y + kappa, x - r, y])); // ziel links
APC(([NSSWF @"%.3f %.3f %.3f %.3f %.3f %.3f c\n", x - r, y - kappa,x - kappa, y - r, x, y - r])); // ziel oben
if([op iE:@"kl"]){ APC(@"S\n");
}else{ //rahmen unsichtbar und nur fuellen
APC((@"0 w\n"));
APC(@"f\n");
APC(([NSSWF @"%.4f w\n",mmtp(lineWidth)]));
}
if(debug){ LOGS(([NSSWF @"x y r = %.0f %.0f %.0f",ptmm(x),ptmmFromTop(y),ptmm(r)]));
}
continue;
}
if([op iE:@"lvb"]){ //line lvb x1,y1,x2,y2 2 pt. verbinden; mit current lineWidth u. grayStroke float x1,y1,x2,y2;
CHECK_PGC;
if([ops count]!=4)goto BADSTATEMENT;
x1 = mmtp([op1 floatValue] + xOffset);
y1 = mmtpFromTop([op2 floatValue] + yOffset);
x2 = mmtp([op3 floatValue] + xOffset);
y2 = mmtpFromTop([op4 floatValue] + yOffset);
APC(([NSSWF @"%.3f %.3f m\n", x1, y1]));
APC(([NSSWF @"%.3f %.3f l\n", x2, y2]));
APC(@"S\n");
if(debug){ LOGS(([NSSWF @"x1 y1 x2 y2 = %.0f %.0f %.0f %.0f",ptmm(x1),ptmmFromTop(y1),ptmm(x2),ptmmFromTop(y2)]));
}
continue;
}
if([op iE:@"l"]){ //line l x,y,o,l x,y Koord., orientation, length; mit current lineWidth u. grayStroke float x,y,ll;
NSString *l_op3;
CHECK_PGC;
if([ops count]!=4)goto BADSTATEMENT;
if([op1 iE:@"a"]){ //appendmode;Linie hinter text beginnen x = lastEndpos;
}else{ x = mmtp([op1 floatValue] + xOffset);
}
y = mmtpFromTop([op2 floatValue] + yOffset);
ll = mmtp([op4 floatValue]);
APC(([NSSWF @"%.3f %.3f m\n", x, y]));
l_op3 = [op3 lowercaseString];
if([l_op3 iE:@"x"] || [l_op3 iE:@"-"]){ x += ll;
}else{ y -= ll;
}
APC(([NSSWF @"%.3f %.3f l\n", x, y]));
APC(@"S\n");
if(debug){ LOGS(([NSSWF @"x y ll = %.0f %.0f %.0f",ptmm(x),ptmmFromTop(y),ptmm(ll)]));
}
continue;
}
if([op iE:@"?"] || [op iE:@"?b"]){ // print dBase style; ? str, ?b = bold float x,y;
int line = [[varDict ofk:@"?line"] intValue];
NSString *ms=EON;
NSString *font;
CHECK_PGC;
for(ii=0,jj=[ops count];ii<jj;ii++){ //mutable strings stuerzen ab bei methode cString, wenn
//sie umlaute enthalten, die appended wurden
ms = [ms stringByAppendingString:[ops oai:ii]];
}
x = mmtp([[varDict ofk:@"?leftMargin"] floatValue] + xOffset);
y = mmtpFromTop([[varDict ofk:@"?topMargin"] floatValue] + ([[varDict ofk:@"?cr"] floatValue] * line)+ yOffset);
if([op iE:@"?b"]){ font = @"Courier-Bold";
}else{ font = [varDict ofk:@"?font"];
}
[pdf setFont:font size:[[varDict ofk:@"?size"]floatValue]];
APC(@"\nBT\n");
[pdf text:ms x:x y:y rotate:0 align:0];
APC(@"ET\n");
line++;
[varDict setObject:NSS(line) forKey:@"?line"];
if(debug){ LOGS(([NSSWF @"? %@",ms]));
}
continue;
}
if([op iE:@"v"] || [op iE:@"vc"] || [op iE:@"vw"]){ //value v 20,45,r,%guiGesamtBetrag,...//vc = v compact; ohne spaces bei aufzaehlungen
//vw = width; maximale breite angeben
float x;
double rotation = 0.0;
NSString *formatOption;
NSString *ms=EON;
int maxWidth=0;
BOOL compact = [op iE:@"vc"];
BOOL vw = [op iE:@"vw"];
CHECK_PGC;
if([ops count]<(vw?5:4))goto BADSTATEMENT;
if(vw)maxWidth=mmtp([op4 intValue]);
ms = [ops oai:(vw?4:3)];
for(ii=(vw?5:4),jj=[ops count];ii<jj;ii++){ if(!compact)ms = [ms stringByAppendingString:@" "];
//mutable strings stuerzen ab bei methode cString, wenn
//sie umlaute enthalten, die appended wurden
ms = [ms stringByAppendingString:[ops oai:ii]];
}
if(!FILLED(ms))continue;
if([op1 iE:@"a"]){ //appendmode x=lastEndpos;
}else{ x = mmtp([op1 floatValue] + xOffset);
lastEndpos = x;
}
if(underlinePending && ulx1 == 0.0){ ulx1 = x;
}
lastYpos = mmtpFromTop([op2 floatValue] + yOffset);
formatOption =[op3 lowercaseString];
alignment=0;
if([formatOption iE:@"r"]){ alignment=1;
}
if([formatOption iE:@"c"]){ // center alignment=2;
}
if([formatOption hasSecurePrefix:@"d"]){ // drehung rotation = [[formatOption substringFromIndex:1]doubleValue];
}
[pdf setFont:lastFont size:lastSize];
if(maxWidth){ ms = [pdf stringOfWidth:maxWidth str:ms];
}
APC(@"\nBT\n");
lastEndpos += [pdf stringWidth:ms];
[pdf text:ms x:x y:lastYpos rotate:rotation align:alignment];
APC(@"ET\n");
if(debug){ LOGS(([NSSWF @"x y = %.0f %.0f; op1 = %@",ptmm(x),ptmmFromTop(lastYpos),ms]));
}
continue;
}
if([op hasSecurePrefix:@"render"]){ //in file rendern; script kann danach mit dem file was machen NSData *renderedPDF = [pdf renderPDF];
if(!renderedPDF){ LOGI(TRANSLATION(@"Druck hat keine Seiten erzeugt"));
continue;
}
[renderedPDF writeToFile:path atomically:YES];
continue;
}
if([op hasSecurePrefix:@"dont_render"]){ //finischPDF davon abhalten, das PDF rendern zu wollen [pdf setWasRendered:YES];
continue;
}
if([op hasSecurePrefix:@"ub"]){ //underline beginn; underlinePending = YES;
ulx1 = 0.0;
continue;
}
if([op hasSecurePrefix:@"ue"] && underlinePending){ //underline end; float uey = lastYpos - (mmtp(lastSize)/2.0);
APC(([NSSWF @"%.3f %.3f m\n", ulx1, uey]));
APC(([NSSWF @"%.3f %.3f l\n", lastEndpos, uey]));
APC(@"S\n");
underlinePending = NO;
continue;
}
if([op iE:@"b"] || [op iE:@"bf"]){ //box b 20,45,120,40,r,jumperText,... float x,y,w,h,yDraw,yEnd;
NSString *ms = EON;
NSString *formatOption,*lineStr;
BOOL isBf = [op iE:@"bf"];
CHECK_PGC;
if(isBf && !restString)continue;
if([ops count]<(isBf?5:6))goto BADSTATEMENT;
x = mmtp([op1 floatValue] + xOffset);
y = mmtpFromTop([op2 floatValue] + yOffset);
w = mmtp([op3 floatValue]);
h = 1;
if(!isBf){ [self setRestString:nil];
for(ii=5,jj=[ops count];ii<jj;ii++){ if(ii>5)ms = [ms stringByAppendingString:@" "]; // literal comma: <comma>
ms = [ms stringByAppendingString:[ops oai:ii]];
}
if(!FILLED(ms))continue;
[self setRestString:ms];
}
formatOption = [ops oai:4];
alignment=0;
if([formatOption iE:@"r"]){ alignment=1;
}
if([formatOption iE:@"c"]){ // center alignment=2;
}
APC(@"\nBT\n");
yDraw = y;
yEnd = y - h;
while(restString && (yDraw > yEnd)){// restString parsen, ob es ein pdf-kommando ist, um Font u. groesse umzusetzen
NSRange r = [restString rangeOfString:@"\n"];
NSString *embed;
if(r.length){ embed = [restString substringToIndex:r.location];
if([embed hasSecurePrefix:@".inline "]){ NSString *inlcmd = [embed substringFromIndex:8];
[self setRestString:[restString substringFromIndex:r.location + 1]];
if([inlcmd hasPrefix:@"f "]){ //font f Arial NSString *newFont = [inlcmd substringFromIndex:2];
if(![newFont iE:lastFont]){ [lastFont release];
lastFont = [newFont retain];
[varDict setObject:lastFont forKey:@"_lastFont"];
}
continue;
}
if([inlcmd hasPrefix:@"s "]){ //size s 12 NSString *ls = [inlcmd substringFromIndex:2];
lastSize = [ls floatValue];
[varDict setObject:ls forKey:@"_lastSize"];
continue;
}
// unknwon inline command
continue;
}
}
[pdf setFont:lastFont size:lastSize];
lineStr = [pdf stringOfWidthFullWord:w str:restString];
[pdf text:lineStr x:(alignment?x+w:x) y:yDraw rotate:0 align:alignment];
yDraw -= lastSize;
if([lineStr length] >= [restString length]){ [self setRestString:nil];
}else{ [self setRestString:[restString substringFromIndex:[lineStr length]]];
}
if(!FILLED([restString stringWithoutSpace]))[self setRestString:nil]; //trailing blanks nicht extra drucken
}
APC(@"ET\n");
if(debug){ LOGS(([NSSWF @"x y w h = %.0f %.0f %.0f %.0f",ptmm(x),ptmmFromTop(y),ptmm(w),ptmm((-1 * h))]));
}
continue;
}
if([op iE:@"dg"]){ NSString *gn;
gn = op1;
[dfn release];
if([gn length] && [gn rangeOfString:@"/"].length){ dfn = [gn retain]; // absoluter vollst. Pfad
}else{ //nur name relativ zum pdfImagePath; f. statische Icons wie z.B. Logos
dfn = [[NSSWF @"%@/Images/%@",RESOURCEPATH,gn]retain];
}
continue;
}
if([op iE:@"g"] || [op iE:@"gw"] || [op iE:@"gh"]){ //grafik g 1275,80,400,logo.jpg -> x,y,breite,pfad//gh = grafik height; hoehe angeben statt breite
float imgw=0.0,imgh=0.0,x,y;
NSString *fn,*gn;
CHECK_PGC;
if([ops count]!=4)goto BADSTATEMENT;
gn = op4;
if([gn length] && [gn hasSecurePrefix:@"/"]){ fn = gn; // absoluter vollst. Pfad
}else{ //nur name relativ zum pdfImagePath; f. statische Icons wie z.B. Logos
fn = [NSSWF @"%@/Images/%@",RESOURCEPATH,gn];
}
x = mmtp([op1 floatValue] + xOffset);
y = mmtpFromTop([op2 floatValue] + yOffset);
if([op iE:@"gh"]){ imgh = mmtp([op3 floatValue]);
}else{ imgw = mmtp([op3 floatValue]);
}
[pdf jpeg:fn x:x y:y w:&imgw h:&imgh];
if(debug){ LOGS(([NSSWF @"x y w = %.0f %.0f %.0f; fn = %@",ptmm(x),ptmmFromTop(y),ptmm(imgw),fn]));
}
continue;
}
BADSTATEMENT:
LOGS(([NSSWF @"%@:?? ---->%@<----",lookupName,s]));
LOGS(([NSSWF @"?? ---->%@<----",[s hexFormat]]));
}
NS_HANDLER;
LOGS_Ex(([NSSWF @"in executeScript"]));
NS_ENDHANDLER;
if(pdf){ [dfn release];
[dash release];
[lastFont release];
}
[localPool release];
// wenn dialogMode, Status des Scripts in Session speichern in der Hoffnung, dass diese Objekte mit archiviert u. auch wieder aktiviert werden; danach geht es auf jeden fall im continueScript weiter;
if([_SESSION dialogMode]){ [_SESSION setCs_v:v];
[_SESSION setCs_a:a];
[_SESSION setCs_datasource:datasource];
[_SESSION setCs_p_parmDict:p_parmDict];
[_SESSION setCs_stack:stack];
[_SESSION setCs_varDictStack:varDictStack];
[_SESSION setCs_varDict:varDict];
[_SESSION setCs_localVarDict:localVarDict];
[_SESSION setCs_foreachStack:foreachStack];
[_SESSION setCs_debug:debug];
[_SESSION setCs_i:i];
[_SESSION setCs_j:j];
}else{ if([[[_APP configDict]ofk:@"logscriptnames"]iE:@"J"] && ![v rangeOfString:@"-"].length){ LOG(([NSSWF @"<%@ end %@ %@",[@"---------------------" secureSubstringToIndex:[_SESSION scriptStackDepth]],scriptTyp,v]));
}else{ if([_APP logActions] && ([_SESSION scriptStackDepth]==1)){ LOG(([NSSWF @"<- end Script %@",v]));
}
}
[_SESSION dec_scriptStackDepth];
[scriptNames secureRemoveLastObject];
}
return varDict;
}
- (NSString *)scriptValueForTarget:co andMethod:(NSString *)kp;
{ id rw = EON;
NSMethodSignature *sig;
NSInvocation *invk;
SEL sel = SECURE_SELECTOR_FROM_STRING(kp);
const char *type;
if(!sel)return EON;
if(![co respondsToSelector:sel])return EON;
sig = [co methodSignatureForSelector:sel];
if(!sig)return EON;
invk = [NSInvocation invocationWithMethodSignature:sig];
[invk setTarget:co];
[invk setSelector:sel];
[invk invoke];
type = [sig methodReturnType];
if (*type == 'r') type++; /* skip const qualifier */
switch (*type) { case _C_ID:
case _C_CLASS:
{ [invk getReturnValue: &rw];
return rw;
}
case _C_SEL:
{ SEL v;
[invk getReturnValue: &v];
rw = NSStringFromSelector(v);
return rw;
}
case _C_CHR: /* We assume bool (Apple) */
{ BOOL v;
[invk getReturnValue: &v];
rw = (v) ? @"J" : @"N";
return rw;
}
case _C_UCHR: /* We assume bool (GNU) */
{ unsigned char v;
[invk getReturnValue: &v];
rw = (v) ? @"J" : @"N";
return rw;
}
case _C_SHT:
{ short v;
[invk getReturnValue: &v];
rw = NSS(v);
return rw;
}
case _C_USHT:
{ unsigned short v;
[invk getReturnValue: &v];
rw = NSS(v);
return rw;
}
case _C_INT:
{ int v;
[invk getReturnValue: &v];
rw = NSS(v);
return rw;
}
case _C_UINT:
{ unsigned int v;
[invk getReturnValue: &v];
rw = NSS(v);
return rw;
}
case _C_LNG:
{ long v;
[invk getReturnValue: &v];
rw = NSS(v);
return rw;
}
case _C_ULNG:
{ unsigned long v;
[invk getReturnValue: &v];
rw = NSS(v);
return rw;
}
case _C_FLT:
{ float v;
double d;
[invk getReturnValue: &v];
d = v; /* insure promotion rules are used correctly */
rw = NSSD(d);
return rw;
}
case _C_DBL:
{ double v;
[invk getReturnValue: &v];
rw = NSSD(v);
return rw;
}
case _C_PTR:
{ void *v;
[invk getReturnValue: &v];
rw = [NSValue valueWithPointer: v];
return rw;
}
case _C_CHARPTR:
{ char *v;
[invk getReturnValue: &v];
rw = [NSString stringWithCString: v];
return rw;
}
case _C_VOID:
{ rw = EON;
return rw;
}
}
return rw;
}
@end
@implementation Application (Kalender)
- (NSString *)isFeiertag:(NSString *)s;
{// feiertagDict fuellen mit Datum und Name
if(!s)return nil;
s = [s secureSubstringToIndex:8];
return [feiertagDict ofk:s];
}
- (void)renderTermine:(NSArray *)currentTermine into:(NSMutableArray *)alles viewType:(int)viewType;
{ NSString *linkf = @"<a style=\"white-space:normal; font-size:x-small;\" onClick=\"{ document.forms[0].clicked_event.value='%@'; document.forms[0].clicked_event_entity.value='%@'; sbm('action_script_clicked_event');}\" href=\"#\" title=\"%@\">%@</a>"; int i2,j2;
for(i2=0,j2=[currentTermine count];i2<j2;i2++){ TerminO *currentTermin = [currentTermine oai:i2];
NSString *s;
[alles addObject:[NSSWF @"<div class=\"KalenderTermin\" style=\"background-color:%@;\">", [[currentTermin empfaenger]vfk:@"farbe"]]];
[alles addObject:[NSSWF @"<span><img src=\"%@\" title=\"%@\">%@</span>",[currentTermin statusIconName],[currentTermin statusName],[currentTermin zeit]]];
[alles addObject:[currentTermin wiedervorlageS]];
[alles addObject:[currentTermin privatS]];
[alles addObject:[[currentTermin owner]vfk:@"kuerzel"]];
[alles addObject:[[currentTermin empfaenger]vfk:@"kuerzel"]];
if([currentTermin isHighPrio])[alles addObject:@"<span style=\"color:red;\">!!</span>"];
[alles addObject:@"<br>"];
s = [currentTermin beschreibung];
if(viewType==viewTypeD){ s = [s abbrevToLength:120];
}else{ s = [s abbrevToLength:60];
}
[alles addObject:[NSSWF linkf,[[currentTermin coveredEO]primaryKey],[[currentTermin coveredEO]entityName],TRANSLATION(@"zum Termin"),[s htmlEscapedString]]];
[alles addObject:@"</div>"];
}
}
- (void)renderWochentageInto:(NSMutableArray *)alles;
{ NSString *workdayf = @"<td class=\"KalenderHeader\">%@</td>";
NSString *sundayf = @"<td class=\"KalenderHeaderSunday\">%@</td>";
[alles addObject:@"<tr bgcolor=#EDEDED>"];
[alles addObject:[NSSWF @"<td class=\"KalenderHeaderKW\">%@</td>",TRANSLATION(@"KW")]];
[alles addObject:[NSSWF workdayf,TRANSLATION(@"Montag")]];
[alles addObject:[NSSWF workdayf,TRANSLATION(@"Dienstag")]];
[alles addObject:[NSSWF workdayf,TRANSLATION(@"Mittwoch")]];
[alles addObject:[NSSWF workdayf,TRANSLATION(@"Donnerstag")]];
[alles addObject:[NSSWF workdayf,TRANSLATION(@"Freitag")]];
[alles addObject:[NSSWF workdayf,TRANSLATION(@"Samstag")]];
[alles addObject:[NSSWF sundayf,TRANSLATION(@"Sonntag")]];
[alles addObject:@"</tr>"];
}
- (void)kalender:(PBWOEditor *)datasource;
{// termine in ma rendern; ist ein Portlet;
// parmDict: startingDate, viewType; parameter der Buttons
// kalenderHTML
LMAN(alles); // hier kommt fertiges html rein
int viewType = [[[datasource parmDict] ofk:@"viewType"]intValue];
NSString *startingDate = [[datasource parmDict] ofk:@"startingDate"];
NSString *buttonf = @"<a onClick=\"sbm('action_script_%@');\" href=\"#\" class=\"PBActionLink\" title=\"%@\">%@</a>"; NSString *buttonfp = @"<a onClick=\"{ document.forms[0].%@.value='%@'; sbm('action_script_%@');}\" href=\"#\" class=\"PBActionLink\" title=\"%@\">%@</a>"; NSString *buttonfpa = @"<a onClick=\"{ document.forms[0].%@.value='%@'; sbm('action_script_%@');}\" href=\"#\" class=\"PBActionLinkActive\" title=\"%@\">%@</a>"; NSString *buttonfp_kal = @"<a onClick=\"{ document.forms[0].%@.value='%@'; sbm('action_script_%@');}\" href=\"#\" class=\"PBActionLinkKal\" title=\"%@\">%@</a>"; NSString *zeitraumf = @"<INPUT id=target116 onFocus=document.forms[0].submitter.value='action_script_kalender_gehe_zu'; size=10 type=text style=\"font-size:10pt;\" title='gehe zu' name=\"PortletKalender_gehe_zu\" >"; // ESC-T fuer Tag eingeben
int startingYear,startingMonth;
int kw;
PBDate *startingPBDate,*renderDate,*pbd;
int i,i1;
LMDN(termine); // pro Tag ein Array von termin objects
BOOL uebernehmen = [[[datasource parmDict]ofk:@"uebernehmen"]iE:@"J"];
if(!FILLED(startingDate))startingDate = [_APP today];
{// zeitlich in Frage kommende Termine besorgen; zusaetzlich gefiltert um custom Qualifiers
LMAN(lmaq);
PBSQLQualifier *q;
NSString *startingDateT,*endingDate;
LMAN(tos); // termine objects
pbd = [PBDate dateWithDBString:startingDate];
if(viewType == viewTypeD){ startingDateT = startingDate;
[pbd addDay:1];
}else if(viewType == viewTypeW){ [pbd prevMonday];
startingDateT = [pbd dateAsDBString];
[pbd addDay:7];
}else{ [pbd erster];
startingDateT = [pbd dateAsDBString];
[pbd addDay:42];
}
endingDate = [pbd dateAsDBString];
q = [PBSQLQualifier qualifierWithString:[NSSWF @"(termin >= '%@' and termin < '%@') or (terminb > 0 and (termin <= '%@' and terminb >= '%@'))",startingDateT,endingDate,endingDate,startingDateT]];
[lmaq addObject:q];
q = [PBSQLQualifier qualifierWithString:[NSSWF @"(privat = 'N' or empfaenger = '%@')",CURRENTUSER]];
[lmaq addObject:q];
[[datasource parmDict] setObject:lmaq forKey:@"p_kalender_qarray"]; // f. Custom-Script, um eigene Qualifiers hinzuzufĂĽgen
[_APP executeScriptNamed:@"akte/addCustomQualifiers" datasource:datasource parmDict:[datasource parmDict]];
q = [PBSQLQualifier andQualifierWithArray:lmaq];
[tos addObjectsFromArray:[_APP termineFromEOs:getEOsQ(@"akte",q)]];
[[datasource parmDict] setObject:tos forKey:@"p_kalender_termine"]; // f. Custom-Script
[_APP executeScriptNamed:@"akte/addCustomTermine" datasource:datasource parmDict:[datasource parmDict]];
{// auf Tage einsortieren
int i,j;
TerminO *to;
NSMutableArray *lma;
for(i=0,j=[tos count];i<j;i++){ NSString *termin_date;
to = [tos oai:i];
termin_date = [[to termin]secureSubstringToIndex:8]; // evt. Zeit abschneiden;
lma = [termine ofk:termin_date];
if(!lma){ lma = [NSMutableArray arrayWithCapacity:10];
[termine setSecureObject:lma forKey:termin_date]; // array von Terminobjekten pro Tag
}
[lma addObject:to];
}
}
[[termine allObjects]makeObjectsPerformSelector:@selector(sort)];
}
startingPBDate = [startingDate pbdate];
startingYear = [startingPBDate year];
startingMonth = [startingPBDate month];
[alles addObject:@"<div>"];
[alles addObject:[NSSWF buttonf,@"clicked_today",TRANSLATION(@"auf Tagesdatum positionieren"),TRANSLATION(@"Heute")]];
[alles addObject:@"--"];
// parm-name, parm-value, action-name,tool-tip,gui
[alles addObject:[NSSWF buttonfp,@"clicked_year",NSS(startingYear-1),@"clicked_year",TRANSLATION(@"auf Jahr"),NSS(startingYear-1)]];
[alles addObject:[NSSWF buttonfpa,@"clicked_year",NSS(startingYear),@"clicked_year",TRANSLATION(@"auf Jahr"),NSS(startingYear)]];
[alles addObject:[NSSWF buttonfp,@"clicked_year",NSS(startingYear+1),@"clicked_year",TRANSLATION(@"auf Jahr"),NSS(startingYear+1)]];
[alles addObject:@"--"];
// Monats-Buttons
for(i=1;i<=12;i++){ NSString *f = buttonfp;
if(i==startingMonth)f=buttonfpa;
[alles addObject:[NSSWF f,@"clicked_month",([NSSWF @"%02i",i]),@"clicked_month",TRANSLATION(@"auf Monat"),[startingPBDate monthNameFor:i]]];
}
[alles addObject:@"--"];
[alles addObject:[NSSWF buttonf,@"clicked_backward",TRANSLATION(@"Frueher"),@"<<<"]];
[alles addObject:[NSSWF buttonf,@"clicked_forward",TRANSLATION(@"Spaeter"),@">>>"]];
[alles addObject:@"--"];
[alles addObject:zeitraumf];
[alles addObject:@"<br>"];
[alles addObject:@"<table class=Kalender>"];
switch(viewType){ case 1: // Woche
[self renderWochentageInto:alles];
renderDate = [startingDate pbdate];
[renderDate prevMonday];
kw = [renderDate weekOfYear];
[alles addObject:@"<tr bgcolor=#f8f8f8>"];
[alles addObject:@"<td style=\"padding:0px;\" bgcolor=#EDEDED valign=top>"];
[alles addObject:[NSSWF buttonfp,@"clicked_week",NSS(kw),@"clicked_week",TRANSLATION(@"zur Woche"),NSS(kw)]];
[alles addObject:@"</td>"];
//Tage der Wochen
for(i1=0;i1<7;i1++){ NSString *renderDateDB = [renderDate dateAsDBString];
NSString *ft = [_APP isFeiertag:renderDateDB];
if([[_APP today] iE:renderDateDB]){ [alles addObject:@"<td valign=top bgcolor=#D3D434 height=70>"];
}else{ [alles addObject:@"<td valign=top height=70>"];
}
if(uebernehmen){ [alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"uebernehmen",TRANSLATION(@"uebernehmen"),@"ueb"]];
}else{ [alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"add_event",TRANSLATION(@"neuer Termin hier"),@"+"]];
}
[alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"clicked_day",TRANSLATION(@"Tagessicht"),NSS([renderDate day])]];
if(!ft)ft=@" ";
[alles addObject:[NSSWF @" <span class=\"Feiertag\">%@</span>",ft]];
[self renderTermine:[termine ofk:[renderDateDB secureSubstringToIndex:8]] into:alles viewType:viewType];
[alles addObject:@"</td>"];
[renderDate addDay:1];
}
[alles addObject:@"</tr>"];
break;
case 2: // Tag
renderDate = [startingDate pbdate];
{ NSString *workdayf = @"<td class=\"KalenderHeaderW\">%@</td>";
NSString *sundayf = @"<td class=\"KalenderHeaderSundayW\">%@</td>";
NSString *fwdn = [renderDate fullWeekdayName];
[alles addObject:@"<tr bgcolor=#EDEDED>"];
[alles addObject:[NSSWF @"<td class=\"KalenderHeaderKW\">%@</td>",TRANSLATION(@"KW")]];
if(![fwdn iE:@"Sonntag"]){ [alles addObject:[NSSWF workdayf,TRANSLATION(fwdn)]];
}else{ [alles addObject:[NSSWF sundayf,TRANSLATION(fwdn)]];
}
[alles addObject:@"</tr>"];
kw = [renderDate weekOfYear];
[alles addObject:@"<tr bgcolor=#f8f8f8>"];
[alles addObject:@"<td style=\"padding:0px;\" bgcolor=#EDEDED valign=top>"];
[alles addObject:[NSSWF buttonfp,@"clicked_week",NSS(kw),@"clicked_week",TRANSLATION(@"zur Woche"),NSS(kw)]];
[alles addObject:@"</td>"];
{ NSString *renderDateDB = [renderDate dateAsDBString];
NSString *ft = [_APP isFeiertag:renderDateDB];
if([[_APP today] iE:renderDateDB]){ [alles addObject:@"<td valign=top bgcolor=#D3D434 height=70>"];
}else{ [alles addObject:@"<td valign=top height=70>"];
}
if(uebernehmen){ [alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"uebernehmen",TRANSLATION(@"uebernehmen"),@"ueb"]];
}else{ [alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"add_event",TRANSLATION(@"neuer Termin hier"),@"+"]];
}
[alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"clicked_day",TRANSLATION(@"Tagessicht"),NSS([renderDate day])]];
if(!ft)ft=@" ";
[alles addObject:[NSSWF @" <span class=\"Feiertag\">%@</span>",ft]];
[self renderTermine:[termine ofk:[renderDateDB secureSubstringToIndex:8]] into:alles viewType:viewType];
[alles addObject:@"</td>"];
}
break;
}
default: // Monat ----------------------------------------
[self renderWochentageInto:alles];
//Wochen im Monat
for(i=0;i<6;i++){ [alles addObject:@"<tr bgcolor=#f8f8f8>"];
[alles addObject:@"<td style=\"padding:0px;\" bgcolor=#EDEDED valign=top>"];
renderDate = [startingDate pbdate];
[renderDate erster];
[renderDate prevMonday];
[renderDate addWeek:i];
kw = [renderDate weekOfYear];
// parm-name, parm-value, action-name,tool-tip,gui
[alles addObject:[NSSWF buttonfp,@"clicked_week",NSS(kw),@"clicked_week",TRANSLATION(@"zur Woche"),NSS(kw)]];
[alles addObject:@"</td>"];
//Tage der Wochen
for(i1=0;i1<7;i1++){ NSString *renderDateDB = [renderDate dateAsDBString];
if([renderDate month]==startingMonth){ NSString *ft = [_APP isFeiertag:renderDateDB];
if([[_APP today] iE:renderDateDB]){ [alles addObject:@"<td valign=top bgcolor=#D3D434 height=70>"];
}else{ [alles addObject:@"<td valign=top height=70>"];
}
if(uebernehmen){ [alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"uebernehmen",TRANSLATION(@"uebernehmen"),@"ueb"]];
}else{ [alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"add_event",TRANSLATION(@"neuer Termin hier"),@"+"]];
}
[alles addObject:[NSSWF buttonfp_kal,@"clicked_day",renderDateDB,@"clicked_day",TRANSLATION(@"Tagessicht"),NSS([renderDate day])]];
if(!ft)ft=@" ";
[alles addObject:[NSSWF @" <span class=\"Feiertag\">%@</span>",ft]];
[self renderTermine:[termine ofk:[renderDateDB secureSubstringToIndex:8]] into:alles viewType:viewType];
}else{ [alles addObject:@"<td valign=top bgcolor=#EDEDED height=70>"];
}
[alles addObject:@"</td>"];
[renderDate addDay:1];
}
[alles addObject:@"</tr>"];
}
}
[alles addObject:@"</table>"];
[alles addObject:@"</div>"];
[alles addObject:@"<input name=\"clicked_week\" type=\"hidden\">"];
[alles addObject:@"<input name=\"clicked_day\" type=\"hidden\">"];
[alles addObject:@"<input name=\"clicked_month\" type=\"hidden\">"];
[alles addObject:@"<input name=\"clicked_year\" type=\"hidden\">"];
[alles addObject:@"<input name=\"clicked_event\" type=\"hidden\">"];
[alles addObject:@"<input name=\"clicked_event_entity\" type=\"hidden\">"];
[[datasource parmDict]setObject:[alles componentsJoinedByString:@""] forKey:@"kalenderHTML"];
}
- (NSArray *)termineFromEOs:(NSArray *)a;
{//eos von gleicher entity
int i,j;
NSString *en;
LMA;
PBEO *eo;
TerminO *to;
j = [a count];
if(!j)return nil;
en = [[a oai:0]entityName];
for(i=0;i<j;i++){ eo = [a oai:i];
if([en iE:@"akte"]){ //normale Termine NSString *von = [eo vfk:@"termin"],*bis = [eo vfk:@"terminb"];
if(FILLED(von)){ PBDate *pbd = [PBDate dateWithDBString:von],*pbd_von = [PBDate dateWithDBString:von],*pbd_bis=nil;
int i_von=[pbd_von dateAsLong];
int i_bis=i_von,i_max;
NSString *terminv = [pbd_von dateAsDBString];
NSString *terminzeitv = [pbd_von timeAsString];
NSString *terminb=@"",*terminzeitb=@"";
if(FILLED(bis)){ pbd_bis = [PBDate dateWithDBString:bis];
i_bis=[pbd_bis dateAsLong];
terminb=[pbd_bis dateAsDBString];
terminzeitb=[pbd_bis timeAsString];
}
if(i_bis < i_von)i_bis = i_von;
for(i_max=0;i_von <= i_bis && i_max < 60;i_von++,i_max++){ // zur Sicherheit: Termine max. 60 Tage lang
if((to = [[TerminO alloc]init])){ [to setTermin:[pbd dateAsDBString]]; // f. einsortieren
[to setTerminv:terminv]; // f. Anzeige
[to setTerminzeitv:terminzeitv];
[to setStatus:[[eo vfk:@"aktenstatus"]intValue]];
[to setBeschreibung:[eo vfk:@"aktentext"]];
[to setStichworte:[[eo values]ofk:@"stichworte"]];
[to setTerminb:terminb];
[to setTerminzeitb:terminzeitb];
[to setCoveredEO:eo];
[to setOwner:[eo dot:@"owner"]];
[to setEmpfaenger:[eo dot:@"empfaenger"]];
[to setPrio:[[eo vfk:@"aktenprio"]intValue]];
[to setWiedervorlage:[[eo vfk:@"wiedervor"]iE:SC_BOOL_TRUE]];
[to setPrivat:[[eo vfk:@"privat"]iE:SC_BOOL_TRUE]];
[lma addObject:to];
[to release];
}
[pbd addDay:1];
}
}
}
}
return lma;
}
@end
@implementation Application (DB)
- (void)createNPPModel;
{// ein ASCII File erzeugen mit allen Tabellen und Attributen des Modells fuer den notepad++ zum besseren Editieren von scripts
// phys. tabellen aufsteigend sortiert, plainAttributes mit $table.dbName,=, jew. mit Label davor
NSArray *ts = [[myDD tables]sortedArrayUsingKeyOrderArray:[NSArray soaFrom:@"dbName"]];
int i,j;
NSString *fn = [NSSWF @"%@/nppModel.script",MANDANTPATH];
LMA;
for(i=0,j=[ts count];i<j;i++){ PBDDTable *t = [ts oai:i];
NSArray *attrs = [t plainAttributes];
int i1,j1;
[lma addObject:[NSSWF @"label %@ %@",[t dbName],[t guiName]]];
for(i1=0,j1=[attrs count];i1<j1;i1++){ [lma addObject:[NSSWF @"$%@.%@,=,x",[t dbName],[[attrs oai:i1]dbName]]];
}
}
[[lma componentsJoinedByString:@"\n"]WTF:fn];
}
- (BOOL)isReferencedEO:(PBEO *)eo;
{// ermittelt, ob eo von einem anderen referenziert wird
if(!eo)return NO;
if(![eo isKindOfClass:[PBEO class]])return NO;
{ PBDDTable *t = [eo myTable];
NSArray *a = [t attributesReferencingMe];
int i,j;
for(i=0,j=[a count];i<j;i++){ PBDDAttribute *pba = [a oai:i];
NSString *sql;
NSString *s;
NSString *pkn = [[pba myTable]primaryKeyName];
if(!FILLED(pkn))continue;
sql = [NSSWF @"select %@ from %@ where %@ = '%@' limit 1",pkn,[[pba myTable]dbName],[pba dbName],[eo primaryKey]];
s = singleValueSQL(sql);
if(FILLED(s))return YES;
}
}
return NO;
}
- (NSArray *)referencingEO:(PBEO *)eo;
{// liefert ein Array von Dictionaries aller Tabellen mit primary Keys, die auf das eo verweisen; max. 100 insges.
// max. 10 pro Tabelle
// fuer Portlet "Objektverwendung"
// nach cdate absteigend sortiert soweit moeglich
LMA;
if(!eo)return lma;
if(![eo isKindOfClass:[PBEO class]])return lma;
{ PBDDTable *t = [eo myTable];
NSArray *a = [t attributesReferencingMe];
int i,j;
for(i=0,j=[a count];i<j;i++){ PBDDAttribute *pba = [a oai:i];
NSString *tableName = [[pba myTable]dbName];
NSString *guiTableName = [[pba myTable]guiName];
NSString *guiName = [pba guiName];
NSString *dbName = [pba dbName];
NSString *sql;
NSArray *a1;
int i1,j1;
if([[pba myTable]plainAttrNamed:@"cdate"]){ sql = [NSSWF @"select %@ from %@ where %@ = '%@' order by cdate desc limit 10",[[pba myTable]primaryKeyName],tableName,[pba dbName],[eo primaryKey]];
}else{ sql = [NSSWF @"select %@ from %@ where %@ = '%@' limit 10",[[pba myTable]primaryKeyName],tableName,[pba dbName],[eo primaryKey]];
}
a1 = [_APP getStringArrayAsResultFrom:sql];
for(i1=0,j1=[a1 count];i1<j1;i1++){ NSString *pk = [a1 oai:i1];
LMD;
[lmd setObject:pk forKey:@"primaryKey"];
[lmd setObject:tableName forKey:@"tableName"];
[lmd setObject:guiTableName forKey:@"guiTableName"];
[lmd setObject:guiName forKey:@"guiName"];
[lmd setObject:dbName forKey:@"dbName"];
[lma addObject:lmd];
if([lma count]>= 100)return lma;
}
}
}
return lma;
}
- (NSString *)attributAuflistungForTable:(PBDDTable *)t withDoku:(BOOL)withDoku;
{ NSString *s = EON;
int ii,jj;
NSArray *a1 = [t plainAttributes];
s = [s stringByAppendingFormat:@"----Tabelle %@ hat diese Attribute:\n\n",[t dbName]];
for(ii=0,jj=[a1 count];ii<jj;ii++){ PBDDAttribute *pba = [a1 oai:ii];
NSString *refdTableName,*line;
if(![pba isVisible])continue;
if([pba targetTyp] != ATTVCSELOBJ)continue;
refdTableName = [pba refdTableName];
line = [NSSWF @"%%selObj.%@ ",[pba dbName]];
line = [line substringToIndex:50];
if(FILLED(refdTableName)){ s = [s stringByAppendingFormat:@"%@ %@ --->%@\n",line,[pba guiName],refdTableName];
}else{ s = [s stringByAppendingFormat:@"%@ %@\n",line,[pba guiName]];
}
if([pba hasVL]){ int i1,j1;
s = [s stringByAppendingString:@"\tNV:::\n"];
for(i1=0,j1=[[pba vl] count];i1<j1;i1++){ PBVLO *pbvlo = [[pba vl]oai:i1];
s = [s stringByAppendingFormat:@"\t%@\t%@\n",[pbvlo value],[pbvlo bez]];
}
}
if(withDoku){ NSString *doku = [pba doku0];
if(FILLED(doku))s = [s stringByAppendingFormat:@"\t%@\n",doku];
}
}
return s;
}
- (NSString *)descriForEn:(NSString *)en pk:(NSString *)pk;
{ NSString *sql,*s=nil,*guiValue;
PBDDAttribute *da;
NSArray *a;
PBDDTable *t;
int i,j;
NSDictionary *d;
if(!en || !pk)return EON;
t = [MYDD tableNamedCheap:en];
if(!t)return EON;
a = [t descriAttributes];
if(![a count])return EON;
sql = [NSSWF @"select %@ from %@ where %@ = '%@'",[[a valuesForKey:@"dbName"]componentsJoinedByString:@","],en,[t primaryKeyName],[pk mysqlEscapedString]];
d = [self getDictAsResultFrom:sql];
if(!d)return EON;
for(i=0,j=[a count];i<j;i++){ da = [a oai:i];
guiValue = [d ofk:[da dbName]];
if(!s){ s = guiValue;
}else{ if([da hasVL]){ guiValue = [da bezeichnungForValue:guiValue];
}
s = [s stringByAppendingFormat:@"-%@",guiValue];
}
}
if(!s)s = EON;
return [s abbreviated40String];
}
///////////////////////////////////////////////////////////////////////////////////////////
// sequentielle Verarbeitungen
///////////////////////////////////////////////////////////////////////////////////////////
- (void)addFetchRequest:(NSDictionary *)fetchReq forHandle:(NSString *)handle;
{ if(!handle || !fetchReq)return;
if([seqAccesses ofk:handle]){ LOGS(([NSSWF @"handle %@ bereits in Gebrauch;",handle]));
return;
}
[seqAccesses setSecureObject:fetchReq forKey:handle];
}
- (NSDictionary *)fetchReqForHandle:(NSString *)handle;
{ return [seqAccesses ofk:handle];
}
- (void)endFetchingForHandle:(NSString *)handle;
{ NSDictionary *fetchReq = [self fetchReqForHandle:handle];
PBMySQLChannel *ac;
if(!fetchReq)return;
ac = [fetchReq objectForKey:SC_channel];
if([ac isFetchInProgress])[ac cancelFetch];
[seqAccesses removeObjectForKey:handle];
}
- (BOOL)establishConnection;
{ [self closeAllChannels];
if(([self freshChannel]!=nil)){ return YES;
}else{ LOGS(@"freshChannel nicht bekommen");
}
return NO;
}
- (BOOL)setFetchCond:(PBSQLQualifier *)q forTable:(PBDDTable *)myTable soa:(NSArray *)soa handle:(NSString *)handle;
{ return [self setFetchCond:(PBSQLQualifier *)q forTable:(PBDDTable *)myTable soa:(NSArray *)soa handle:(NSString *)handle limit:0];
}
- (BOOL)setFetchCond:(PBSQLQualifier *)q forTable:(PBDDTable *)myTable soa:(NSArray *)soa handle:(NSString *)handle limit:(int)limit;
{ PBMySQLChannel *ac;
NSDictionary *fetchReq;
NSString *wc,*lc = @"";
NSString *s;
NSString *ttn;
if(!handle){ LOGS((@"handle nicht angegeben"));
return NO;
}
[self endFetchingForHandle:handle]; //zur sicherheit evt. alte handle beenden
wc = [q string];
if(!wc)wc=@"";
if(FILLED(wc))wc = [NSSWF @" where %@",wc];
if(limit)lc = [NSSWF @" limit %i",limit];
//temp table aufbauen, gesamten Satz reinstellen;
//damit muss nicht nochmal mit pk auf echte Table zugegriffen werden
ttn = [[NSSWF @"tmp_%@",handle]lowercaseString]; //lower, da tablenamen generell lowercase gemacht werden
[self evaluateSQL:[NSSWF @"drop temporary table if exists %@",ttn]];
s = [NSSWF @"create temporary table %@ select * from %@ %@ %@",ttn,[myTable dbName],wc,lc];
if(![self evaluateSQL:s])return NO;
if(!(ac = [self freshChannel]))return NO;
if(![ac selectQualifier:nil forTable:myTable tn:ttn offset:0 count:0 soa:soa])return NO;
fetchReq = [NSDictionary dwok:ac,SC_channel,myTable,SC_pbt,@"YES",@"forUpdate",nil,nil];
[self addFetchRequest:fetchReq forHandle:handle];
return YES;
}
- (PBEO *)nextEOForHandle:(NSString *)handle;
{ //liefert autoreleastes EO;
// daher immer schoen mit AutoreleasePools arbeiten;
// nach dem letzten wird fetch autom. endFetchingForHandle: gemacht
//letzte erfolgreich verwendete channel wird gemerkt f. evt. update
NSDictionary *fetchReq = [self fetchReqForHandle:handle];
PBDDTable *myTable = (PBDDTable *)[fetchReq objectForKey:SC_pbt];
NSString *entityName = [myTable dbName],*pk;
NSMutableDictionary *md;
PBEO *eo=nil;
PBMySQLChannel *ac;
if(!fetchReq || !myTable){ LOG(@"no fetchReq or table");
return nil;
}
ac = [fetchReq objectForKey:SC_channel];
if(![ac isFetchInProgress]){ [self endFetchingForHandle:handle];
return nil;
}
if(!(md=[ac fetchRow])){ //den naechsten key aus temp-table [self endFetchingForHandle:handle];
}else{ //md stammt evt. aus temptable, ist aber vollstaendig;
pk = [md ofk:[myTable primaryKeyName]];
eo = [self eoFromDict:md entityName:entityName];
[eo setWasFetched:YES];
}
return eo;
}
- (NSMutableDictionary *)nextMDForHandle:(NSString *)handle;
{ //liefert autoreleastes md;
NSDictionary *fetchReq = [self fetchReqForHandle:handle];
NSMutableDictionary *md;
PBMySQLChannel *ac;
if(!fetchReq)return nil;
ac = [fetchReq objectForKey:SC_channel];
if(![ac isFetchInProgress]){ [self endFetchingForHandle:handle];
return nil;
}
if(!(md=[ac fetchRow])){ //den naechsten key aus temp-table [self endFetchingForHandle:handle];
}
return md;
}
///////////////////////////////////////////////////////////////////////////////////////////
// EO-Umformungen
///////////////////////////////////////////////////////////////////////////////////////////
- (PBEO *)eoFromDict:(NSDictionary *)d entityName:(NSString *)entityName;
{ PBEO *eo;
eo = [[[PBEO alloc]initWithEntityName:entityName]autorelease];
if(!eo)return nil;
[eo useValuesFromDictionary:d];
return eo;
}
- (NSDictionary *)dictFromEO:(PBEO *)eo forKeys:(NSDictionary *)keyDict;
{// gewaehrleistet, dass nur DB-Felder im Dict sind; EO-Feldinhalte sind MySQL kompatibel
PBDDTable *myTable = [eo myTable];
NSArray *a = [keyDict allKeys];
PBDDAttribute *pba;
NSString *k;
NSString *s;
int i,j;
LMD;
if(![a count]){ // kein keyDict, ganzes EO
a = [myTable attributesDB];
for(i=0,j=[a count];i<j;i++){ pba = [a oai:i];
k = [pba dbName];
s = [eo vfk:k];
if(!FILLED(s)){ [lmd setSecureObject:EON forKey:k];
continue;
}
[lmd setSecureObject:s forKey:k];
}
}else{ // das viel kleinere keyDict abarbeiten
for(i=0,j=[a count];i<j;i++){ k = [a oai:i];
pba = [myTable plainAttrNamed:k];
if(!pba)continue; // nicht in Tabelle
if(![pba isDB])continue; // kein DB-Attr.
s = [eo vfk:k];
if(!FILLED(s)){ [lmd setSecureObject:EON forKey:k];
continue;
}
[lmd setSecureObject:s forKey:k];
}
}
return lmd;
}
///////////////////////////////////////////////////////////////////////////////////////////
// fetch methoden
///////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)refetchEO:(PBEO *)eo;
{ NSString *entityName = [eo entityName];
PBDDTable *myTable = [eo myTable];
NSMutableDictionary *md;
PBMySQLChannel *ac;
PBSQLQualifier *q;
if(!(eo))return NO;
if(!(myTable))return NO;
q = [eo pkq];
if([q typ]==PBSQLQnothing)return NO;
//restl. Werte beschaffen
if(!(ac = [self freshChannel]))return NO;
if(![ac selectQualifier:q forTable:myTable tn:[myTable dbName] offset:0 count:1 soa:nil])return NO;
if((md=[ac fetchRow])){ PBEO *eo1=[self eoFromDict:md entityName:entityName];
[[eo values]removeAllObjects];
[[eo values]addEntriesFromDictionary:[eo1 values]];
[eo setWasFetched:YES];
}else{ return NO;
}
if([ac isFetchInProgress])[ac cancelFetch];
return YES;
}
- (NSArray *)getBasicEOs:(PBSQLQualifier *)q entityName:(NSString *)entityName offset:(int)offset count:(int)count soa:(NSArray *)soa;
{// offset und count werden als limit beim select uebergeben
PBDDTable *myTable;
NSMutableDictionary *md;
PBEO *fetchedEO;
LMAS(ma,50);
PBMySQLChannel *ac;
if(!(myTable = [MYDD tableNamed:entityName]))return nil;
if(!(ac = [self freshChannel]))return nil;
if(![ac selectQualifier:q forTable:myTable tn:[myTable dbName] offset:offset count:count soa:soa]){ LOGS(@"select Attributes failed");
return nil;
}
while((md=[ac fetchRow])){ fetchedEO = [self eoFromDict:md entityName:entityName];
[ma addObject:fetchedEO];
[fetchedEO setWasFetched:YES];
}
if([ac isFetchInProgress])[ac cancelFetch];
return ma;
}
- (PBEO *)eoOfRelation:(NSString *)s forEo:(PBEO *)eo;
{ NSString *fk = [eo vfk:s];
PBDDAttribute *pba;
if(!eo)return nil;
if(![eo isKindOfClass:[PBEO class]])return nil;
pba = [[myDD tableNamed:[eo entityName]] plainAttrNamed:s];
if(!pba){ LOGS(([NSSWF @"keine Relation %@ in %@ fuer %@",s,[eo entityName],[eo description]]));
// PRINTCURRENTSTACK;
return nil;
}
if(!FILLED(fk))return nil;
return getEOPkValue([pba refdTableName],fk);
}
- (NSArray *)getEOs:(NSString *)entityName qualifier:(PBSQLQualifier *)q offset:(int)offset count:(int)count soa:(NSArray *)soa;
{ NSArray *a;
if([q typ] == PBSQLQnothing)return nil;
a = [self getBasicEOs:q entityName:entityName offset:offset count:count soa:soa];
return a;
}
/* code-beispiel
v = [NSSWF @"select %@ from %@ where %@ = '%@'",[kps oai:1],rtn,[[MYDD tableNamedCheap:rtn] primaryKeyName],v];
v = [_APP getSingleValueAsResultFrom:v];
*/
///////////////////////////////////////////////////////////////////////////////////////////
// low level sql
///////////////////////////////////////////////////////////////////////////////////////////
- (unsigned)evaluateSQL:(NSString *)s;
{//wenn kein result benoetigt wird, diese Methode nehmen
//stellt sicher, dass ein eventuelles result gefreed wird und der channel damit wieder zur verfuegung steht
//wird ein result benoetigt, die gleichnamige Methode am Channel aufrufen und selber dafuer sorgen, dass der fetch beendet wird;
PBMySQLChannel *ac;
unsigned result;
if(!FILLED(s))return 0;
if(!(ac = [self freshChannel])){ LOG(@"--- keinen Channel bekommen");
return 0;
}
if(!(ac = [self freshChannel]))return 0;
result = [ac evaluateSQL:s];
[ac cancelFetch];
return result;
}
- (NSString *)getSingleValueAsResultFrom:(NSString *)s;
{// returned single Value
// falls was nicht klappt, EON
PBMySQLChannel *ac;
NSString *rs;
unsigned result;
NSDictionary *d;
if(!FILLED(s))return EON;
if(!(ac = [self freshChannel]))return EON;
// LOGS(s);
result = [ac evaluateSQL:s];
if(![ac isFetchInProgress])return EON;
[ac setSelectedAttributes:[NSArray arrayWithObject:@"result"]];
d = [ac fetchRow];
[ac cancelFetch];
if(!d)return EON;
// LOGS([d description]);
rs = [[d allValues]firstObject];
if(!FILLED(rs))rs=EON;
return rs;
}
- (NSDictionary *)getDictAsResultFrom:(NSString *)s;
{// returned single dictionary
PBMySQLChannel *ac;
unsigned result;
NSDictionary *d;
if(!FILLED(s))return nil;
if(!(ac = [self freshChannel])){ LOG(@"keinen Channel bekommen.");
return nil;
}
result = [ac evaluateSQL:s];
if(![ac isFetchInProgress])return nil;
[ac setSelectedAttributes:[ac describeResults]];
d = [ac fetchRow];
[ac cancelFetch];
return d;
}
- (NSArray *)getArrayAsResultFrom:(NSString *)s;
{// returned array of dictionaries
PBMySQLChannel *ac;
unsigned result;
NSDictionary *d;
LMA;
if(!FILLED(s))return lma;
if(!(ac = [self freshChannel]))return lma;
result = [ac evaluateSQL:s];
if(![ac isFetchInProgress])return lma;
[ac setSelectedAttributes:[ac describeResults]];
while((d=[ac fetchRow])){ [lma addObject:d];
}
[ac cancelFetch];
return lma;
}
- (NSArray *)getStringArrayAsResultFrom:(NSString *)s;
{ NSArray *a3 = [_APP getArrayAsResultFrom:s]; //das sind dictionaries
LMAN(lma3);
int i3,j3;
for(i3=0,j3=[a3 count];i3<j3;i3++){ [lma3 addObject:[[[a3 oai:i3]allObjects]firstObject]];
}
return lma3;
}
///////////////////////////////////////////////////////////////////////////////////////////
// EO Handling
///////////////////////////////////////////////////////////////////////////////////////////
- (void)copyPosFrom:(PBEO *)k1 to:(PBEO *)k2 posEn:(NSString *)posEn;
{// nach
PBEO *p2,*p1;
NSArray *a;
int i,j;
if(!k1 || !k2)return;
a = [self positionenFor:k1 posEn:posEn];
for(i=0,j=[a count];i<j;i++){ p1 = [a oai:i];
p2 = NEW_EO(posEn);
[p2 takeValuesOfSameNameFromEo:p1];
[p2 tvfk([k2 primaryKey],@"masterkey")]; //Kopfkey 2 in neue pos haengen
[p2 tvfk(nil,[p2 primaryKeyName])];
[parmDict setObject:k1 forKey:@"p_k1"];
[parmDict setObject:k2 forKey:@"p_k2"];
[parmDict setObject:p1 forKey:@"p_p1"];
//will/didInsert/didCreate macht keinen Sinn, weil diese davon ausgehen, den PBWOPosEditor oder einen PBWOEditor als datasource zu haben
[parmDict setObject:p2 forKey:@"p_eo"];
[_APP executeScriptNamed:[NSSWF @"%@/willCopyPos",[currentComponent name]] datasource:(PBWOEditor *)currentComponent parmDict:parmDict];
INSRT(p2);
[_APP executeScriptNamed:[NSSWF @"%@/didCopyPos",[currentComponent name]] datasource:(PBWOEditor *)currentComponent parmDict:parmDict];
}
}
- (NSArray *)positionenFor:(PBEO *)k1 posEn:(NSString *)posEn;
{ return getEOsKnKv(posEn,@"masterkey",[k1 primaryKey]);
}
- (PBEO *)createEOforEN:(NSString *)entityName;
{ PBEO *eo;
NSArray *allAttr;
int i,j;
int dt;
PBDDTable *myTable = [myDD tableNamed:entityName];
PBDDAttribute *cdate = [myTable plainAttrNamed:@"cdate"];
// Felder initialisieren
if(!myTable){ return nil;
}
eo = [[PBEO alloc]initWithEntityName:entityName];
if(!eo)return nil;
// Statistikfelder, damit schon mal was drinsteht, wenn man nach "neu" auf das System-Tab geht
[[eo values] tvfk(CURRENTUSER,@"cuser")];
[[eo values] tvfk(CURRENTUSER,@"luser")];
if(cdate){ [[eo values] tvfk([_APP now],@"cdate")];
[[eo values] tvfk([_APP now],@"ldate")];
}
// alle int-Felder auf 0;///
// nicht nur Felder in DB damit insb. numerische parameter Felder initialsiert werden.
allAttr = [myTable plainAttributes];
for(i=0,j=[allAttr count];i<j;i++){ PBDDAttribute *pba = [allAttr oai:i];
NSString *initialValue = [pba initialValue];
NSString *dbName = [pba dbName];
// f. debug if([dbName iE:@"teilanzahl"])LOGS(([NSSWF @"%@ = %@",dbName,initialValue]));
if(FILLED(initialValue)){ if([initialValue iE:@"$today"])initialValue = [_APP today];
if([initialValue iE:@"$now"])initialValue = [_APP now];
if([initialValue iE:@"CURRENTUSER"])initialValue = CURRENTUSER;
[[eo values] tvfk(initialValue,dbName)];
// f. debug if([dbName iE:@"teilanzahl"])LOGS(([NSSWF @"%@ = %@ set",dbName,initialValue]));
continue;
}
// f. debug if([dbName iE:@"teilanzahl"])LOGS(([NSSWF @"%@ = %@ not set",dbName,initialValue]));
if(FILLED([pba expression]))continue;
if([pba targetTyp]!=ATTVCSELOBJ)continue;
dt = [pba dataTyp];
if([pba isNumeric]){ [[eo values] tvfk([NSString dbFromDouble:0.0 pba:pba],dbName)];
}
if([pba dataTyp] == DT_BOOL){ if([dbName iE:NAME_OF_AKTIV_FLAG]){ [[eo values] tvfk(SC_BOOL_TRUE,dbName)];
}else{ [[eo values] tvfk(SC_BOOL_FALSE,dbName)];
}
}
// hier koennte bei VLs noch der default-Entry gezogen werden; ist aber eigentlich durch den initialValue aus dem Modell schon abgebildet
}
return [eo autorelease];
}
- (BOOL)insertEO:(PBEO *)eo;
{ //raw: ohne Pruefungen u. ohne Cache
NSDictionary *eod;
NSString *en;
PBDDTable *myTable;
PBDDAttribute *cdate;
PBMySQLChannel *ac;
if([_APP orbDebug]){ LOGS(([NSSWF @"--> insertEO; %@.",[eo description]]));
}
if(!eo){ LOGS(@"kein EO uebergeben");
// PRINTCURRENTSTACK;
return NO;
}
en = [eo entityName];
myTable = [eo myTable];
if(!myTable){ LOGS(([NSSWF @"keine solche Table:%@",en]));
return NO;
}
if(![[myTable primaryKeyAttr]isSerialPK] && !FILLEDNUM([eo primaryKey])){ LOGS(([NSSWF @"INSERT %@ failed; no primaryKey",[eo description]]));
return NO;
}
[[eo values] tvfk(CURRENTUSER,@"cuser")];
[[eo values] tvfk(CURRENTUSER,@"luser")];
cdate = [myTable plainAttrNamed:@"cdate"];
if(cdate){ [[eo values] tvfk([_APP now],@"cdate")];
[[eo values] tvfk([_APP now],@"ldate")];
}
eod = [self dictFromEO:eo forKeys:nil]; //alle Werte
if(![eod count]){ LOGS(([NSSWF @"INSERT %@ failed; conversion to dictionary failed;",[eo description]]));
return NO;
}
if(!(ac = [self freshChannel])){ LOGS(([NSSWF @"INSERT %@ failed; no channel;",[eo description]]));
return NO;
}
if(![ac insertRow:eod forTable:myTable]){ LOGS(([NSSWF @"INSERT %@ failed; (s. vorherige Meldung)",[eo description]]));
return NO;
}
// wenn es ein serial ist, den vergebenen Wert holen
if([[myTable primaryKeyAttr]isSerialPK]){ if([[eo primaryKey]intValue] == 0)[eo setPrimaryKey:singleValueSQL(@"select LAST_INSERT_ID()")];
}
[eo setDescri:nil];
[eo setWasFetched:YES];
return YES;
}
- (BOOL)updateEO:(PBEO *)eo;
{ PBDDTable *myTable;
NSString *en,*pk;
NSDictionary *eod;
PBMySQLChannel *ac;
PBDDAttribute *ldate;
if([_APP orbDebug]){// LOGS(([NSSWF @"--> updateEO; %@.",[eo description]]));
}
if(!eo){ LOGS(@"kein EO uebergeben.");
// PRINTCURRENTSTACK;
return NO;
}
en = [eo entityName];
myTable = [eo myTable];
if(!myTable){ LOGS(([NSSWF @"UPDAT %@ failed; no table",[eo description]]));
return NO;
}
if(![[eo oldValues]count])return YES; //nix zu tun
//statistic felder erst hier versorgen, wenn feststeht, dass auch andere Felder geaendert
if(![[eo oldValues]ofk:@"luser"])[eo tvfk(CURRENTUSER,@"luser")]; //wenn nicht explizit geaendert...
ldate = [myTable plainAttrNamed:@"ldate"];
if(ldate){ [eo tvfk([_APP now],@"ldate")];
}
eod = [self dictFromEO:eo forKeys:[eo oldValues]];
if(![eod count])return YES; //nix zu tun
if(!(ac = [self freshChannel])){ LOGS(([NSSWF @"UPDAT %@ failed; no channel",[eo description]]));
return NO;
}
pk = [eo primaryKey];
if(![ac updateRow:eod forTable:myTable pk:[pk mysqlEscapedString]]){ LOGS(([NSSWF @"UPDAT %@ failed; (s. vorherige Meldung)",[eo description]]));
return NO;
}
[[eo changedValues]removeAllObjects];
[[eo changedValues]addEntriesFromDictionary:[eo oldValues]]; //damit man in didUpdate feststellen kann, was sich geaendert hat
[[eo oldValues]removeAllObjects];
[eo setDescri:nil];
return YES;
}
- (BOOL)deleteEO:(PBEO *)eo;
{ PBSQLQualifier *q;
NSString *en;
PBDDTable *myTable;
PBMySQLChannel *ac;
if([_APP orbDebug]){ LOGS(([NSSWF @"--> deleteEO; %@.",[eo description]]));
}
if(!eo){ LOGS(@"kein EO uebergeben.");
// PRINTCURRENTSTACK;
return NO;
}
en = [eo entityName];
myTable = [eo myTable];
if(!myTable){ LOGS(([NSSWF @"keine solche Entity:%@",en]));
return NO;
}
if(!(ac = [self freshChannel]))return NO;
q = [eo pkq];
if(![ac deleteRowsDescribedByQualifier:q forTable:myTable]){ LOGS(([NSSWF @"DELET %@ failed; (s. vorherige Meldung)",[eo description]]));
return NO;
}
return YES;
}
///////////////////////////////////////////////////////////////////////////////////////////
// channel handling
///////////////////////////////////////////////////////////////////////////////////////////
- (void)closeAllChannels;
{ int i,j;
PBMySQLChannel *ac;
for(i=0,j=[channelPool count];i<j;i++){ ac = [channelPool oai:i];
if([ac isOpen]){ if([ac isFetchInProgress])[ac cancelFetch];
[ac closeChannel];
}
}
[channelPool removeAllObjects];
}
- (PBMySQLChannel *)freshChannel;
{ //alle channelPool durchschauen; wenn einer geclosed ist, open u. verwenden;
// wenn einer !fetchin Progress, verwenden
//der channel muss danach sofoert verwendet werden, sonst wird er nochmal vergeben...
PBMySQLChannel *c;
int i,j;
// LOGS(([NSSWF @"channelpool count =%i",j]));
// in geschlossenen Channels einen wiederverwertbaren suchen
// rueckwaerts, damit der Index richtig bleibt
for(i=[channelPool count]-1;i>=0;i--){ c = [channelPool objectAtIndex:i];
if([c isOpen])continue;
if([c dbNr] != dbNr)continue;
if(![c openChannel]){ LOGS(@"konnte alten Adaptorchannel nicht oeffnen.");
[channelPool removeObjectAtIndex:i]; //mit Index;
continue;
}
// LOGS(([NSSWF @"returning reopened channel; channelpool count =%i",j]));
return c;
}
// in offenen channels einen wiederverwertbaren suchen
for(i=0,j=[channelPool count];i<j;i++){ c = [channelPool objectAtIndex:i];
if([c dbNr] != dbNr)continue;
if(![c isFetchInProgress]){// LOGS(([NSSWF @"reuseing open channel; channelpool count =%i",j]));
return c;
}
}
c = [[PBMySQLChannel alloc]init];
if(!c){ LOGS(@"keinen Adaptorchannel erhalten.");
LOGS(([NSSWF @"channelpool count =%i",j]));
return nil;
}
if(![c openChannel]){ LOGS(@"konnte neuen Adaptorchannel nicht oeffnen.");
LOGS(([NSSWF @"channelpool count =%i",j]));
return nil;
}
[channelPool addObject:c];
if([_APP orbDebug])LOGS(NSS([channelPool count]));
return c;
}
///////////////////////////////////////////////////////////////////////////////////////////
// SQL related
///////////////////////////////////////////////////////////////////////////////////////////
- (NSMutableString *)sqlValuesStringFromDict:(NSDictionary *)d forTable:(PBDDTable *)t;
{ //dict schon mit dictFromEO vorbereitet: nur noch db-Attribute, nur noch delta bei update, alle werte im db-Format
//hier nur noch quoten und escapen;
//pass f. insert und update
NSArray *a,*a1;
int i,j;
NSMutableString *ms = [NSMutableString stringWithCapacity:1024];
NSString *colName,*colValue;
if(!d || !t)return nil;
[ms setString:EON];
a = [d allKeys]; a1 = [d allValues];
for(i=0,j=[a count];i<j;i++){ colName = [a oai:i];
colValue = [a1 oai:i];
if(!FILLED(colValue)){ colValue=@"\"\""; //immer leer wg. uniq-Feldern;
}else{ colValue = [NSString stringWithFormat:@"\"%@\"",[colValue mysqlEscapedString]]; //immer quoten; zahlen eigentlich nicht
}
if(i)[ms appendString:@", "];
[ms appendFormat:@"%@=%@",colName,colValue];
}
return ms;
}
- (NSString *)orderbyClauseFromSoa:(NSArray *)soa;
{ NSMutableString *obyc;
int i,j=[soa count];
PBSortOrdering *pbso;
NSString *k,*ad;
SEL sel;
if(!j)return EON;
obyc = [NSMutableString stringWithCapacity:100];
for(i=0;i<j;i++){ pbso = [soa oai:i];
k = [pbso key];
if(!FILLED(k))continue;
if(!FILLED(obyc))[obyc setString:@"order by "];
sel = [pbso selector];
if(sel_eq(sel,EOCompareAscending) || sel_eq(sel,@selector(compareNumeric:)) || sel_eq(sel,@selector(compare:)) || sel_eq(sel,@selector(compareCaseInsensitive:))){ ad = @"ASC";
}else{ ad = @"DESC";
}
if(i)[obyc appendString:@", "];
[obyc appendFormat:@"%@ %@ ",k,ad];
}
return obyc;
}
- (NSString *)sqlFormatResetSerial:(PBDDTable *)t;
{// alternativ: alter table %@ AUTO_INCREMENT=1;
PBDDAttribute *pbat = [t primaryKeyAttr];
NSString *tn,*sn;
LMA;
if(![pbat isSerialPK])return @"";
tn = [t dbName];
sn = [pbat dbName];
[lma addObject:[NSSWF @"alter table %@ add auto_increment_bak INTEGER",tn]];
[lma addObject:[NSSWF @"update %@ set auto_increment_bak = %@",tn,sn]];
[lma addObject:[NSSWF @"alter table %@ drop %@",tn,sn]];
[lma addObject:[NSSWF @"alter table %@ add %@ INTEGER NOT NULL auto_increment PRIMARY KEY",tn,sn]];
[lma addObject:[NSSWF @"update %@ set %@ = auto_increment_bak",tn,sn]];
[lma addObject:[NSSWF @"alter table %@ drop auto_increment_bak",tn]];
return [lma componentsJoinedByString:@"\n"];
}
- (NSString *)sqlFormatCt:(PBDDTable *)t;
{ return [self sqlFormatCt:t tn:[t dbName] temp:NO];
}
- (NSString *)sqlFormatCt:(PBDDTable *)t tn:(NSString *)tn temp:(BOOL)temp;
{ static NSMutableString *s;
NSString *constraint,*temporary;
int i,j,rac=0;
NSArray *a;
PBDDAttribute *pba;
if(!s){ s = [[NSMutableString alloc]initWithCapacity:1000];
}
if(temp){ temporary = @"temporary";
}else{ temporary = EON;
}
// vorher muss im DD reorg gemacht worden sein;
[s setString:EON];
if([t isRealTable]){ a = [t attributesDB];
[s appendFormat:@"create %@ table %@ (\n",temporary,[tn lowercaseString]];
constraint = EON;
for(i=0,j=[a count];i<j;i++){ pba = [a oai:i];
if(rac)[s appendString:@",\n"];
[s appendString:[self sqlFormatCANew:pba]];
rac++;
}
[s appendString:@");\n"];
return s;
}else{ return EON;
}
}
- (NSString *)sqlFormatCANew:(PBDDAttribute *)pba;
{ NSString *atn,*dbTyp = @"CHAR(1)",*s;
atn = [[pba dbName]lowercaseString];
if([pba isSerialPK]){ return [NSSWF @"%@ INTEGER NOT NULL auto_increment PRIMARY KEY",atn];
}
switch([pba dataTyp]){ case DT_CHAR:
if([pba length]<4){ dbTyp = [NSSWF @"char(%i)",[pba length]];
}else if([pba length]<256){ dbTyp = [NSSWF @"varchar(%i)",[pba length]];
}else{ dbTyp = [NSSWF @"text"];
}
break;
case DT_DATE:
dbTyp = @"DATE";
break;
case DT_DATETIME:
dbTyp = @"DATETIME";
break;
case DT_MONEY:
dbTyp = @"DECIMAL(11,2)"; //platz f. vorzeichen
break;
case DT_FLOAT:
dbTyp = [NSSWF @"DECIMAL(%i,%i)",[pba length],[pba nak]]; //
break;
case DT_INT:
dbTyp = @"INTEGER";
break;
case DT_BOOL:
dbTyp = @"CHAR(1)";
break;
}
s = [NSSWF @" %@ %@",atn,dbTyp];
if([pba isPK]){ s = [s stringByAppendingString:@" NOT NULL PRIMARY KEY"];
}
return s;
}
- (void)readArialuni_cmap;
{// Char 0F50 -> Index 2334
NSString *s = [NSSWCOF [NSSWF @"%@/arialuni_cmap.txt",GLOBALCONFIGPATH]];
NSArray *a = [s componentsSeparatedByString:@"\n"];
int i,j;
for(i=0,j=65535;i<j;i++)arialuni_cmap[i]=0;
for(i=0,j=[a count];i<j;i++){ unsigned short uni;
s = [a oai:i];
uni = [[[s secureSubstringFromIndex:13]secureSubstringToIndex:4]hexValue];
arialuni_cmap[uni]=[[s secureSubstringFromIndex:27]intValue];
}
}
- (void)readArialuni_hmtx;
{// 17896. advWid: 2048, LSdBear: 113
// die hmtx sind nach cid organisiert und lueckenlos
NSString *s = [NSSWCOF [NSSWF @"%@/arialuni_hmtx.txt",GLOBALCONFIGPATH]];
NSArray *a = [s componentsSeparatedByString:@"\n"];
NSString *sep = @". advWid: ";
int i,j;
for(i=0,j=65535;i<j;i++)arialuni_hmtx[i]=1000;
for(i=0,j=[a count];i<j;i++){ NSArray *a1 = [[a oai:i]componentsSeparatedByString:sep];
if([a1 count]!=2)continue;
arialuni_hmtx[i]=(unsigned short)[[[[[a1 oai:1]stringWithoutSpace]componentsSeparatedByString:@","]firstObject]floatValue] / 2.023; //ist viel zu breit
}
}
- (NSString *)cidStringFrom:(NSString *)s;
{// die unicode characters in cid hex-zahlen umwandeln u. < > drumrum fuer PDF
int j = [s length];
int i=0;
NSMutableString *ms = [NSMutableString stringWithCapacity:(j * 4) + 3];
[ms setString:@"<"];
for(i=0,j=[s length];i<j;i++){ unsigned short cid=0;
unichar uni = [s characterAtIndex:i];
cid = arialuni_cmap[uni];
if(cid)[ms appendString:[NSSWF @"%04x",cid]]; //gibt sonst kaestchen
}
[ms appendString:@">"];
return ms;
}
- (unsigned short)cidForUnichar:(unichar)uni;
{ return arialuni_cmap[uni];
}
- (unsigned short)widthForCid:(unsigned short)cid;
{ return arialuni_hmtx[cid];
}
- (unsigned short)widthForUnichar:(unichar)uni;
{ return [self widthForCid:[self cidForUnichar:uni]];
}
@end
@implementation Application (CEOH)
// das hier wird auch noch aufgeloest und in Scripts verlagert;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// methoden fuer verschiedene Tabellen
- (NSArray *)helementv3_directChildrenOf:(PBEO *)eo;
{ return getEOsKnKv(@"helpdeskv3",@"parentelement",[eo primaryKey]);
}
- (void)helementv3_genPrimKey:(PBEO *)eo inParentEO:(PBEO *)peo;
{ if(!peo){ //root element return;
}else{ //innerhalb parent den naechsten schluessel NSArray *a = [[self helementv3_directChildrenOf:peo]valuesForKey:@"pid"];
int i,j,lk=0;
if(!a){ [eo tvfk(([NSSWF @"%@.0",[peo primaryKey]]),@"pid")]; //erstes element unter diesem parent
return;
}
for(i=0,j=[a count];i<j;i++){ //aeltestes Geschwister festsellen NSString *s = [a oai:i];
int lk1;
lk1 = [[[s componentsSeparatedByString:@"."]lastObject]intValue];
if(lk1 > lk)lk = lk1;
}
lk++;
[eo tvfk(([NSSWF @"%@.%i",[peo primaryKey],lk]),@"pid")];
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)flagsToGruppenstring:(PBEO *)eo;
{// beim Speichern
NSString *gs = @"";
int i;
for(i=0;i<ANZ_GRUPPEN;i++){ NSString *gn = [NSSWF @"gruppe%i",i];
if([[eo vfk:gn]iE:@"J"]){ gs = [gs stringByAppendingString:@"x"];
}else{ gs = [gs stringByAppendingString:@"-"];
}
}
[eo tvfk(gs,@"gruppenstring")];
}
- (void)gruppenstringToFlags:(PBEO *)eo;
{// beim Laden
NSString *gs = [eo vfk:@"gruppenstring"];
int i;
for(i=0;i<ANZ_GRUPPEN;i++){ NSString *gn = [NSSWF @"gruppe%i",i];
if([[[gs charAt:i]lowercaseString]iE:@"x"]){ [eo tvfk(@"J",gn)];
}else{ [eo tvfk(@"N",gn)];
}
}
}
@end
@implementation Application (Webpublishing)
// Webpublisher
- (void)unreferencedFiles;
{// holt alle Filenamen aus Images und dursucht
// alle \img und \dl Zeilen danach; nicht gefundene werden zum Löschen vorgeschlagen;
NSString *bp = [NSSWF @"%@/web_publish/%@",MANDANTPATH,[configDict ofk:@"web_publish_base"]]; // Directory relativ zu web_publish; ohne fuehrenden /; von hier wird der Input gelesen;
NSString *imgp = [NSSWF @"%@/Images",bp];
NSArray *a = [myFM directoryContentsAtPath:imgp];
int i,j;
NSString *dlAndImg = [[self dlAndImgIn:bp]componentsJoinedByString:@"\n"];
LMA;
NSString *allSource = [NSSWF @"%@\n%@\%@",dlAndImg,[NSSWCOF [NSSWF @"%@/web.css",bp]],[NSSWCOF [NSSWF @"%@/web_template.html",bp]]];
for(i=0,j=[a count];i<j;i++){ NSString *fn = [[a oai:i]stringWithForwardSlashes];
if(![allSource rangeOfString:fn].length)[lma addObject:[NSSWF @"rm %@/%@",imgp,fn]];
}
[[lma componentsJoinedByString:@"\n"] WTF:[NSSWF @"%@/unreferencedFiles.sh",bp]];
[allSource WTF:[NSSWF @"%@/allSource.txt",bp]];
}
- (NSString *)titleFromFn:(NSString *)fn;
{// liefert den vom Filenamen abgeleiteten Titel; wird die Ueberschrift und angezeigter Text des Links im Menu (Navigation);
NSRange r = [fn rangeOfString:@" "];
NSString *s;
NSString *product = [configDict ofk:@"product"];
if(!FILLED(product))product = @"Intars";
if(r.length == 0){ s = fn;
}else{ s = [fn substringFromIndex:r.location + r.length];
}
if([s hasSecureSuffix:@".txt"])s = [s stringWithoutSuffix:@".txt"];
return [s replace:@"IntarS 5.1" with:product];
}
- (NSString *)section:(int)i;
{ switch(i){ case 0: return @"chapter";
case 1: return @"section";
case 2: return @"subsection";
case 3: return @"subsubsection";
}
return @"subsubsection";
}
- (void)publishDirectory:(NSString *)dir;
{ NSArray *a = [[myFM directoryContentsAtPath:dir]sortedArray];
int i,j;
LMAN(latexma);
NSArray *a1;
int i1,j1;
NSString *product = [configDict ofk:@"product"];
BOOL mit_bild_fn = ([[[_APP configDict]ofk:@"mit_bild_fn"]iE:@"J"]);
if(!FILLED(product))product = @"Intars";
for(i=0,j=[a count];i<j;i++){ NSString *fn = [a oai:i];
NSString *completeFn = [dir stringByAppendingFormat:@"/%@",fn];
NSDictionary *fa = [myFM fileAttributesAtPath:completeFn traverseLink:NO];
if([[fa ofk:NSFileType]iE:NSFileTypeRegular] && [fn hasSecureSuffix:@".txt"] && ![fn hasSecurePrefix:@"_idee"]){ // BOOL addBR = NO;
BOOL inTT = NO;
BOOL inText = NO;
BOOL inOL = NO;
BOOL inUL = NO;
PBEO *eo = NEW_EO(@"webpublisher");
LMA;
[eo tvfk(NSS(nestinglevel),@"nestinglevel")];
[eo tvfk([self urlFromCompleteFn:[completeFn withoutPrefix:basePath]],@"url")];
[eo tvfk([self titleFromFn:fn],@"title")]; // Sortierung des Filenamens bis zum ersten Space abschneiden;
#include "renderHTML.h"
[eo tvfk(lma,@"lines")]; // als Array belassen f. 2. pass
[eo tvfk(@"J",@"isfinal")];
[h3eos addObject:eo];
[allLATeX appendString:[NSSWF @"\n\\%@{%@}\n%@",[self section:gliederungsTiefe],[[eo vfk:@"title"]latexEscapedString],[latexma componentsJoinedByString:@" "]]]; continue;
}
if([[fa ofk:NSFileType]iE:NSFileTypeDirectory] && ![fn iE:@"Images"] && ![fn iE:@".svn"]){ PBEO *eo = NEW_EO(@"webpublisher");
[eo tvfk(NSS(nestinglevel),@"nestinglevel")];
[eo tvfk([self urlFromCompleteFn:[completeFn withoutPrefix:basePath]],@"url")];
[eo tvfk([self titleFromFn:fn],@"title")];
[eo tvfk(EON,@"content")];
[h3eos addObject:eo];
[allLATeX appendString:[NSSWF @"\n\\%@{%@}",[self section:gliederungsTiefe],[[eo vfk:@"title"]latexEscapedString]]]; nestinglevel++;
gliederungsTiefe++; //wg. kompatib. zu renderHTML
[self publishDirectory:completeFn];
nestinglevel--;
gliederungsTiefe--;
}
}
}
- (NSArray *)dlAndImgIn:(NSString *)dir;
{ NSArray *a = [[myFM directoryContentsAtPath:dir]sortedArray];
int i,j;
LMA;
for(i=0,j=[a count];i<j;i++){ NSString *fn = [a oai:i];
NSString *completeFn = [dir stringByAppendingFormat:@"/%@",fn];
NSDictionary *fa = [myFM fileAttributesAtPath:completeFn traverseLink:NO];
if([[fa ofk:NSFileType]iE:NSFileTypeRegular] && [fn hasSecureSuffix:@".txt"] && ![fn hasSecurePrefix:@"_idee"]){ // NSString *file = [NSSWCOF completeFn];
NSArray *lines = [file componentsSeparatedByString:@"\n"];
int i1,j1;
for(i1=0,j1=[lines count];i1<j1;i1++){ NSString *line = [lines oai:i1];
if([line hasSecurePrefix:@"\\dl"] || [line hasSecurePrefix:@"\\img"])[lma addObject:line];
}
continue;
}
if([[fa ofk:NSFileType]iE:NSFileTypeDirectory] && ![fn iE:@"Images"] && ![fn iE:@".svn"]){ [lma addObjectsFromArray:[self dlAndImgIn:completeFn]];
}
}
return lma;
}
- (NSString *)urlFromCompleteFn:(NSString *)completeFn;
{// Sortierzahl vorne weg; .txt -> .html
// completeFn ist relativ zum basePath;
// url soll sein ohne fuehrenden / und ohne targetPath und ohne Suffix
// es wird daraus die URL und der Meta Title gebaut
NSArray *a = [[completeFn stringWithForwardSlashes]componentsSeparatedByString:@"/"];
int i,j;
LMA;
NSString *s;
NSString *product = [configDict ofk:@"product"];
if(!FILLED(product))product = @"Intars";
for(i=0,j=[a count];i<j;i++){ NSRange r;
s = [a oai:i];
r = [s rangeOfString:@" "];
if(r.length > 0){ s = [s substringFromIndex:r.location + r.length];
}
if([s hasSecureSuffix:@".txt"])s = [s stringWithoutSuffix:@".txt"];
[lma addObject:s];
}
if([[lma firstObject]iE:@""])[lma removeObjectAtIndex:0];
s = [lma componentsJoinedByString:@"/"];
return [s replace:@"IntarS 5.1" with:product];
}
- (NSString *)navLinesFor:(PBEO *)eo;
{ LMA;
int i,j;
NSString *url = [eo vfk:@"url"];
int nl = [[eo vfk:@"nestinglevel"]intValue];
int currentNL = 0;
BOOL increasing = YES;
for(i=0,j=[h3eos count];i<j;i++){ PBEO *eo1 = [h3eos oai:i];
NSString *url1 = [eo1 vfk:@"url"];
int nl1 = [[eo1 vfk:@"nestinglevel"]intValue];
BOOL wasAdded = NO;
if(nl1 == currentNL){ [lma addObject:[self navLinkFor:eo1 eo:eo]];
wasAdded = YES;
}
if(increasing){ if([url hasSecurePrefix:url1]){ if(!wasAdded)[lma addObject:[self navLinkFor:eo1 eo:eo]];
currentNL++;
if(currentNL > nl){ currentNL = nl;
increasing = NO;
}
}
}else{ if(nl1 < currentNL){ [lma addObject:[self navLinkFor:eo1 eo:eo]];
currentNL--;
}
}
}
return [lma componentsJoinedByString:@""];
}
- (NSString *)navLinkFor:(PBEO *)navEO eo:(PBEO *)eo;
{ NSString *navLinkDir = @"<tr><td nowrap>%@ <a class=\"navLinkDir\" href=\"/%@/%@.html\">» %@</a></td></tr>";
NSString *navLinkFile = @"<tr><td nowrap>%@ <a class=\"navLinkFile\" href=\"/%@/%@.html\">%@</a></td></tr>";
NSString *navLinkSelf = @"<tr><td nowrap>%@ <a class=\"navLinkSelf\" href=\"/%@/%@.html\">%@</a></td></tr>";
NSString *nestingImage=@"";
int nl = [[navEO vfk:@"nestinglevel"]intValue];
if(nl){ nestingImage = [NSSWF @"<img src=\"/%@/Images/1a.gif\" alt=\"\" width=%i height=1 border=0>",targetPath,nl*10];
}
if([[navEO vfk:@"url"]iE:[eo vfk:@"url"]]){ return [NSSWF navLinkSelf,nestingImage,targetPath,[[[navEO vfk:@"url"]urlEncodedString]umlautExpandedString],[navEO vfk:@"title"]];
}
if([[navEO vfk:@"isfinal"]iE:@"J"]){ return [NSSWF navLinkFile,nestingImage,targetPath,[[[navEO vfk:@"url"]urlEncodedString]umlautExpandedString],[navEO vfk:@"title"]];
}else{ return [NSSWF navLinkDir,nestingImage,targetPath,[[[navEO vfk:@"urlff"]urlEncodedString]umlautExpandedString],[navEO vfk:@"title"]];
}
}
- (void)publish;
{ NSString *web_template,*web_template_path;
int i,j;
BOOL first = YES;
LMD;
[self setBasePath:[NSSWF @"%@/web_publish/%@",MANDANTPATH,[configDict ofk:@"web_publish_base"]]]; // Directory relativ zu web_publish; ohne fuehrenden /; von hier wird der Input gelesen; parametrisierbar, um Buecher oder verschiedene Webseiten zu rendern
[self setTargetPath:[configDict ofk:@"web_publish_target"]]; // relativ zu htdocs; ohne fuehrenden /
// targetPath-Directory clearen und Images neu reinstellen
[myFM removeFileAtPath:[NSSWF @"%@/web/%@",RESOURCEPATH,targetPath] handler:nil];
[myFM createAllDirsAtPath:[NSSWF @"%@/web/%@/Images",RESOURCEPATH,targetPath]];
SYSTEM(([NSSWF @"cp -rf %@/Images/*.* %@/web/%@/Images",basePath,RESOURCEPATH,targetPath]));
SYSTEM(([NSSWF @"cp %@/web.css %@/web/%@/Images",basePath,RESOURCEPATH,targetPath]));
if(![myFM fileExistsAtPath:basePath]){ LOGI(([NSSWF TRANSLATION(@"basePath %@ nicht gefunden"),basePath]));
return;
}
[allLATeX setString:[NSSWF [NSSWCOF [NSSWF @"%@/publish_template.tex",basePath]],basePath]]; // graphicspath in tex rein
[h3eos removeAllObjects];
nestinglevel = 0;
gliederungsTiefe = 0;
[self publishDirectory:basePath];
[allLATeX appendString:@"\\end{document}"]; [allLATeX writeToFileLatin1:[NSSWF @"%@/web/%@/Publish.tex",RESOURCEPATH,targetPath]];
// dictionary aufbauen, URL f. ID
for(i=0,j=[h3eos count];i<j;i++){ PBEO *eo = [h3eos oai:i];
NSString *internal_id = [eo vfk:@"internal_id"];
if(FILLED(internal_id))[lmd setObject:eo forKey:internal_id];
}
// rendern
// den urlff first final ermitteln: erste angezeigte Seite
for(i=0,j=[h3eos count];i<j;i++){ PBEO *eo = [h3eos oai:i];
int i1;
if([[eo vfk:@"isfinal"]iE:@"J"])continue;
for(i1=i+1;i1<j;i1++){ PBEO *eo1 = [h3eos oai:i1];
if([[eo1 vfk:@"isfinal"]iE:@"J"]){ [eo tvfk([eo1 vfk:@"url"],@"urlff")]; // first final
break;
}
}
}
// template laden
web_template_path = [NSSWF @"%@/web_template.html",basePath];
web_template = [NSSWCOF web_template_path];
if(!FILLED(web_template)){ LOGS(([NSSWF @"web_template %@ nicht gefunden",web_template_path]));
return;
}
web_template = [web_template replace:@"${targetPath}" with:targetPath];
// alle final eos verarbeiten; pro eo wird ein .html file geschrieben; dazu die Nav-Leiste kunstvoll generieren; alle Directories auf dem Weg anlegen
for(i=0,j=[h3eos count];i<j;i++){ PBEO *eo = [h3eos oai:i];
NSString *htmlPath,*htmlFile;
NSString *navLines;
NSString *meta_title;
int i1,j1;
NSMutableArray *lines = [eo vfk:@"lines"];
if([[eo vfk:@"isfinal"]iE:@"N"])continue;
// internal links aufloesen
for(i1=0,j1=[lines count];i1<j1;i1++){ NSString *line = [lines oai:i1];
if([line hasSecurePrefix:@"\\ai "]){ NSArray *a2 = [line componentsSeparatedByString:@"{"]; NSString *internal_id,*arg2;
internal_id = [[a2 oai:1]stringWithoutLastChar]; // id
arg2 = [[a2 oai:2]stringWithoutLastChar]; // text
if(FILLED(internal_id)){ PBEO *eo_target = [lmd ofk:internal_id];
if(FILLED(eo_target)){ line = [NSSWF @"<a href=\"/%@/%@.html\">%@</a>",targetPath,[eo_target vfk:@"url"],arg2];
[lines insertObject:line atIndex:i1];
[lines removeObjectAtIndex:i1 + 1];
}
}
}
}
navLines = [self navLinesFor:eo];
meta_title = [eo vfk:@"meta_title"];
if(!FILLED(meta_title))meta_title = [NSSWF @"%@/%@",targetPath,[eo vfk:@"url"]];
htmlFile = [NSSWF web_template,meta_title,[[eo vfk:@"meta_description"] htmlEscapedString],[[eo vfk:@"meta_keywords"] htmlEscapedString],navLines,[[eo vfk:@"title"] htmlEscapedString],[lines componentsJoinedByString:@""]];
htmlPath = [[NSSWF @"%@/web/%@/%@.html",RESOURCEPATH,targetPath,[eo vfk:@"url"]]umlautExpandedString]; // url ist relativ zum /
[myFM createAllDirsAtPath:[htmlPath stringByDeletingLastPathComponent]];
[htmlFile WTF:htmlPath];
// erstes File als index.html wegschreiben
// URL /Aprica2/web
if(first){ [htmlFile WTF:[NSSWF @"%@/web/%@/index.html",RESOURCEPATH,targetPath]];
first = NO;
}
}
{// in htdocs installieren; dazu altes erstmal loeschen
NSString *htdocsPath = [NSSWF @"%@/%@",htdocs,[configDict ofk:@"web_publish_target"]];
[myFM removeFileAtPath:htdocsPath handler:nil];
[myFM copyPath:[[NSSWF @"%@/web/%@",RESOURCEPATH,targetPath]umlautExpandedString] toPath:htdocsPath handler:nil];
}
}
@end
@implementation Application (XML)
- (NSString *)encodeObjectXMLRPC:o methodName:(NSString *)methodName single:(BOOL)single;
{// o muss ein Dictionary oder Array sein
// methodName ist ein frei waehlbarer name
NSMutableString *ms = [NSMutableString stringWithCapacity:1000];
[ms setString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"];
/*
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
</params>
</methodCall>
*/
[ms appendString:@"<methodCall>\n"];
[ms appendString:@"<methodName>"];
[ms appendString:[methodName xmlEscapedString]];
[ms appendString:@"</methodName>\n"];
if(FILLED(o)){ [ms appendString:@"<params>\n"];
if([o isKindOfClass:[NSDictionary class]]){ [ms appendString:@"<param>\n"];
[self encodeDictionaryXMLRPC:o inXML:ms nestingLevel:0];
[ms appendString:@"</param>\n"];
}else if([o isKindOfClass:[NSArray class]]){ if(single){ int i,j;
for(i=0,j=[o count];i<j;i++){ [ms appendString:@"<param>\n"];
[ms appendString:@"<value>"];
[ms appendString:[[o oai:i] xmlEscapedString]];
[ms appendString:@"</value>\n"];
[ms appendString:@"</param>\n"];
}
}else{ [ms appendString:@"<param>\n"];
[self encodeArrayXMLRPC:o inXML:ms nestingLevel:0];
[ms appendString:@"</param>\n"];
}
}else{ [ms appendString:@"<param>\n"];
[ms appendString:@"<value>"];
[ms appendString:[o xmlEscapedString]];
[ms appendString:@"</value>\n"];
[ms appendString:@"</param>\n"];
}
[ms appendString:@"</params>\n"];
}
[ms appendString:@"</methodCall>\n"];
return ms;
}
- (void)encodeDictionaryXMLRPC:(NSDictionary *)d inXML:(NSMutableString *)ms nestingLevel:(int)nl;
{// interne Methode
/*
<value>
<struct>
<member>
<name>...</name>
<value>...</value>
</member>
</struct>
</value>
*/
NSArray *a1=[d allKeys];
NSArray *a2=[d allObjects];
// NSString *nesting = [NSString stringWith:nl timesString:@"\t"];
int i,j;
[ms appendString:@"<value>\n"];
[ms appendString:@"<struct>\n"];
for(i=0,j=[a1 count];i<j;i++){ NSString *k = [a1 oai:i];
id o;
[ms appendString:@"<member>\n"];
[ms appendString:@"<name>"];
[ms appendString:[k xmlEscapedString]];
[ms appendString:@"</name>\n"];
o=[a2 oai:i];
if([o isKindOfClass:[NSString class]]){ [ms appendString:@"<value>"];
[ms appendString:[o xmlEscapedString]];
[ms appendString:@"</value>\n"];
}else{ if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionaryXMLRPC:o inXML:ms nestingLevel:nl + 1];
}else if([o isKindOfClass:[NSArray class]]){ [self encodeArrayXMLRPC:o inXML:ms nestingLevel:nl + 1];
}
}
[ms appendString:@"</member>\n"];
}
[ms appendString:@"</struct>\n"];
[ms appendString:@"</value>\n"];
}
- (void)encodeArrayXMLRPC:(NSArray *)a inXML:(NSMutableString *)ms nestingLevel:(int)nl;
{// interne Methode
/*
<value>
<array>
<data>
<value>...</value>
</data>
</array>
</value>
*/
// NSString *nesting = [NSString stringWith:nl timesString:@"\t"];
int i,j;
[ms appendString:@"<value>\n"];
[ms appendString:@"<array>\n"];
[ms appendString:@"<data>\n"];
for(i=0,j=[a count];i<j;i++){ id o=[a oai:i];
if([o isKindOfClass:[NSString class]]){ [ms appendString:@"<value>"];
[ms appendString:[o xmlEscapedString]];
[ms appendString:@"</value>\n"];
}else{ if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionaryXMLRPC:o inXML:ms nestingLevel:nl + 1];
}else if([o isKindOfClass:[NSArray class]]){ [self encodeArrayXMLRPC:o inXML:ms nestingLevel:nl + 1];
}
}
}
[ms appendString:@"</data>\n"];
[ms appendString:@"</array>\n"];
[ms appendString:@"</value>\n"];
}
- (NSString *)encodeObject:o withDocType:(NSString *)docType;
{// o muss ein Dictionary oder Array sein
// docType ist ein frei waehlbarer name
NSMutableString *ms = [NSMutableString stringWithCapacity:1000];
[ms setString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"];
if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionary:o inXML:ms forName:docType nestingLevel:0];
}else if([o isKindOfClass:[NSArray class]]){ [self encodeArray:o inXML:ms forName:docType nestingLevel:0];
}else{ LOGS(@"falsche Klasse; muss Dictionary oder Array sein");
return @"";
}
return ms;
}
- (void)encodeDictionary:(NSDictionary *)d inXML:(NSMutableString *)ms forName:(NSString *)s nestingLevel:(int)nl;
{// interne Methode
NSArray *a1=[d allKeys];
NSArray *a2=[d allObjects];
NSString *dictName = [s xmlEscapedString];
NSString *nesting = [NSString stringWith:nl timesString:@"\t"];
int i,j;
[ms appendString:[NSSWF @"%@<%@>\n",nesting,dictName]];
for(i=0,j=[a1 count];i<j;i++){ NSString *k = [a1 oai:i];
id o=[a2 oai:i];
if([o isKindOfClass:[NSString class]]){ NSString *s1 = [k xmlEscapedString];
[ms appendString:[NSSWF @"%@\t<%@>%@</%@>\n",nesting,s1,[o xmlEscapedString],s1]];
}else{ if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionary:o inXML:ms forName:k nestingLevel:nl + 1];
}else if([o isKindOfClass:[NSArray class]]){ [self encodeArray:o inXML:ms forName:k nestingLevel:nl + 1];
}
}
}
[ms appendString:[NSSWF @"%@</%@>\n",nesting,dictName]];
}
- (void)encodeArray:(NSArray *)a inXML:(NSMutableString *)ms forName:(NSString *)s nestingLevel:(int)nl;
{// interne Methode
NSString *arrayName = [s xmlEscapedString];
NSString *nesting = [NSString stringWith:nl timesString:@"\t"];
int i,j;
[ms appendString:[NSSWF @"%@<%@>\n",nesting,arrayName]];
for(i=0,j=[a count];i<j;i++){ id o=[a oai:i];
if([o isKindOfClass:[NSString class]]){ [ms appendString:[NSSWF @"%@\t<NSArrayItem>%@</NSArrayItem>\n",nesting,[o xmlEscapedString]]];
}else{ if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionary:o inXML:ms forName:@"NSArrayItem" nestingLevel:nl + 1];
}else if([o isKindOfClass:[NSArray class]]){ [self encodeArray:o inXML:ms forName:@"NSArrayItem" nestingLevel:nl + 1];
}
}
}
[ms appendString:[NSSWF @"%@</%@>\n",nesting,arrayName]];
}
- (id)objectFromXML:(NSString *)xml;
{// erst den Baum aufbauen; danach analysieren und entscheiden, was Dictionaries und Arrays sind;
XMLObject *rootObject = [self objectTreeFromXML:xml];
if(!rootObject)return nil;
// jetzt den Baum analysieren
if([rootObject determineConreteContainer]){ if([rootObject ma])return [rootObject ma];
if([rootObject md])return [rootObject md];
}
return nil;
}
- (XMLObject *)objectTreeFromXML:(NSString *)xml;
{ XMLObject *rootObject = nil,*currentObject=nil;
NSString *xmlname;
NSRange r;
r = [xml rangeOfString:@"<?"];
if(r.length){ xml = [xml secureSubstringFromIndex:r.location + r.length];
r = [xml rangeOfString:@"?>"];
if(!(r.length)){ LOGS(([NSSWF @"unmatched <? %@",[xml abbreviated60String]]));
return nil;
}else{ xml = [xml secureSubstringFromIndex:r.location + r.length];
}
}
while(YES){// ist das naechste non-white-space Zeichen ein < kommt ein Objekt oder Kommentar oder endetag, sonst der Content des currentObject
xml = [xml stringWithoutLeadingWhiteSpaceCRLF];
if(!FILLED(xml))break; // fertig;
if([xml characterAtIndex:0] == '<'){ if([xml hasSecurePrefix:@"<!--"]){// ein Kommentar
xml = [xml substringFromIndex:4];
r = [xml rangeOfString:@"-->"];
if(!(r.length)){ LOGS(([NSSWF @"missing end of comment --> %@",[xml abbreviated60String]]));
return nil;
}else{ xml = [xml secureSubstringFromIndex:r.location + r.length];
}
}else if([xml hasSecurePrefix:@"</"]){// beendet currentObject;
// name im endetag muss mit name des currentObject uebereinstimmen
xml = [xml substringFromIndex:2];
r = [xml rangeOfString:@">"];
if(!(r.length)){ LOGS(([NSSWF @"missing > in endtag %@",[xml abbreviated60String]]));
return nil;
}else{ xmlname = [[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes];
if(!FILLED(xmlname)){ LOGS(([NSSWF @"empty Name in endtag %@ ",[xml abbreviated60String]]));
return nil;
}
if(![xmlname iE:[currentObject name]]){ LOGS(([NSSWF @"Name %@ doesn't match name of starttag %@",[xml abbreviated60String],[currentObject name]]));
return nil;
}
xml = [xml secureSubstringFromIndex:r.location + r.length];
// dieses Objekt ist fertig geparsed
currentObject = [currentObject parent];
}
}else{// hier beginnt vermutlich ein Name
xml = [xml substringFromIndex:1];
r = [xml rangeOfString:@">"];
if(!(r.length)){ LOGS(([NSSWF @"missing > %@",[xml abbreviated60String]]));
return nil;
}else{ NSRange r1;
XMLObject *o;
xmlname = [[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes];
r1 = [xmlname rangeOfString:@" "];
if(r1.length){ // Attribute des Namens vergessen wir jetzt mal
xmlname = [xmlname secureSubstringToIndex:r1.location];
}
if(!FILLED(xmlname)){ LOGS(([NSSWF @"empty Name %@",[xml abbreviated60String]]));
return nil;
}
o = [XMLObject xmlObjectWithName:xmlname];
[o setTyp:XMLObjectTyp_Container];
[[currentObject children]addObject:o];
[o setParent:currentObject];
currentObject = o;
if(!rootObject){ rootObject = currentObject;
}
xml = [xml secureSubstringFromIndex:r.location + r.length];
}
}
}else{ [currentObject setTyp:XMLObjectTyp_Element];
// content des element
r = [xml rangeOfString:@"</"];
if(!(r.length)){ LOGS(([NSSWF @"missing endtag of element </ %@",[xml abbreviated60String]]));
return nil;
}else{ [currentObject setContent:[[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes]];
xml = [xml secureSubstringFromIndex:r.location + r.length];
// name im endetag muss mit name des currentObject uebereinstimmen
r = [xml rangeOfString:@">"];
if(!(r.length)){ LOGS(([NSSWF @"missing > in endtag %@",[xml abbreviated60String]]));
return nil;
}else{ xmlname = [[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes];
if(!FILLED(xmlname)){ LOGS(([NSSWF @"empty Name in endtag %@",[xml abbreviated60String]]));
return nil;
}
if(![xmlname iE:[currentObject name]]){ LOGS(([NSSWF @"Name %@ doesn't match name of starttag %@",[xml abbreviated60String],[currentObject name]]));
return nil;
}
xml = [xml substringFromIndex:r.location + r.length];
// dieses Objekt ist fertig geparsed
currentObject = [currentObject parent];
}
}
}
}
if(!rootObject){ LOGS(@"no rootObject in xml");
return nil;
}
if([rootObject typ]==XMLObjectTyp_Element){ LOGS(@"rootObject ist kein Container-Objekt");
return nil;
}
return rootObject;
}
- (NSData *)httpGet:(NSString *)uri host:(NSString *)host;
{ NSMutableData *response = [NSMutableData dataWithCapacity:4096];
PBSocket *socket;
if(!FILLED(uri) || !FILLED(host)){LOGS(@"no host/uri"); return response;} if(!(socket = [PBSocket socket])){LOGS(@"no socket"); return response;} [socket connectToHostName:host port:80];
if(![socket connected]){LOGS(@"no connect"); return response;} [socket writeString:[NSSWF @"GET %@ HTTP/1.0\r\nHost: %@\r\n\r\n",uri,host]];
[socket readData:response];
return response;
}
- (NSData *)httpPost:(NSString *)uri host:(NSString *)host soa:(NSString *)soa parm:(NSDictionary *)parm docType:(NSString *)docType;
{// soa ist der optionale Name eines soa-Aufrufes; in Aprica ist dies ein Script-Name;
// parm ist ein Dictionary, das in XML umgewandelt zum host transportiert wird
// docType ist der optionale Name des XML-Dokuments; falls leer, wird ein default genommen;
NSMutableData *response = [NSMutableData dataWithCapacity:4096];
PBSocket *socket;
NSMutableString *ms = [NSMutableString stringWithCapacity:4096]; // hier wird der request zusammengebaut
if(!FILLED(uri) || !FILLED(host)){LOGS(@"no host/uri"); return response;} if(!(socket = [PBSocket socket])){LOGS(@"no socket"); return response;} [socket connectToHostName:host port:80];
if(![socket connected]){LOGS(@"no connect"); return response;} [ms setString:[NSSWF @"POST %@ HTTP/1.0\r\n",uri]];
[ms appendString:[NSSWF @"Host: %@\r\n",host]];
if(FILLED(soa)){ [ms appendString:[NSSWF @"soa: %@\r\n",soa]]; // ein zusaetzlicher Header nimmt das Kommando auf
}
if(parm){ NSString *xml;
if(!FILLED(docType))docType = @"pirmin";
xml = [self encodeObject:parm withDocType:docType];
[ms appendString:[NSSWF @"Content-Length: %i\r\n\r\n",[xml length]]];
[ms appendString:xml];
}else{ [ms appendString:@"Content-Length: 0\r\n\r\n"];
}
if(log_changes)LOG(ms);
[socket writeString:ms];
[socket readData:response];
return response;
}
- (NSData *)httpPostXMLRPC:(NSString *)uri host:(NSString *)host methodName:(NSString *)methodName params:params single:(BOOL)single;
{// nach http://www.xmlrpc.com/spec
/*
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>...</name>
<value>...</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
*/
NSMutableData *response = [NSMutableData dataWithCapacity:4096];
PBSocket *socket;
NSMutableString *ms = [NSMutableString stringWithCapacity:4096]; // hier wird der request zusammengebaut
NSString *xml;
if(!FILLED(uri) || !FILLED(host)){LOGS(@"no host/uri"); return response;} if(!(socket = [PBSocket socket])){LOGS(@"no socket"); return response;} [socket connectToHostName:host port:80];
if(![socket connected]){LOGS(@"no connect"); return response;} [ms setString:[NSSWF @"POST %@ HTTP/1.0\r\n",uri]];
[ms appendString:[NSSWF @"Host: %@\r\n",host]];
[ms appendString:@"Content-Type: text/xml;chartype=UTF-8\r\n"];
xml = [self encodeObjectXMLRPC:params methodName:methodName single:single];
[ms appendString:[NSSWF @"Content-Length: %i\r\n\r\n",[xml length]]];
[ms appendString:xml];
if(log_changes)LOG(ms);
[socket writeString:ms];
[socket readData:response];
return response;
}
@end