1 #include <AEDataModel.h>
5 #define kComponentSignatureString "BBPy.LM"
9 #include <BBLMInterface.h>
10 #include <BBXTInterface.h>
11 //#include <BBLMTextIterator.h>
21 void debugf_(const char* func
,const char* fileName
,long line
, const char*fmt
,...)
26 vsnprintf(msg
,256 ,fmt
, arg
);
27 DebugAssert(COMPONENT_SIGNATURE
, DEBUG_NO_OPTIONS
, kComponentSignatureString
": " , msg
, nil
, fileName
, line
, 0 );
31 #define debugf(FMT,...) debugf_( __FUNCTION__,__FILE__, __LINE__,FMT,__VA_ARGS__);
33 #define debugf(FMT,...)
36 typedef const char *Str
;
40 kPyBBLMStringSubst
= kBBLMFirstUserRunKind
43 #define iswordchar(x) (isalnum(x)||x=='_')
53 char start(struct runloc
& r
,BBLMParamBlock
&pb
)
56 r
.last_start
= pb
.fCalcRunParams
.fStartOffset
;
57 r
.pos
= pb
.fCalcRunParams
.fStartOffset
;
58 r
.p
= ((unsigned char*)pb
.fText
) + pb
.fCalcRunParams
.fStartOffset
;
59 // Adjust for the gap if weÕre not already past it.
60 if ((!r
.past_gap
) && (r
.pos
>= pb
.fTextGapLocation
)){
61 r
.p
+= pb
.fTextGapLength
;
68 char nextchar(struct runloc
&r
,BBLMParamBlock
&pb
)
70 if ( r
.pos
< pb
.fTextLength
){
73 if ((!r
.past_gap
) && (r
.pos
>= pb
.fTextGapLocation
)){
74 r
.p
+= pb
.fTextGapLength
;
84 bool addRun(BBLMRunCode kind
, int start
,int len
, const BBLMCallbackBlock
& bblm_callbacks
)
86 if (len
> 0){ // Tie off the code run we were in, unless the length is zero.
87 debugf("Run %d %d:%d", kind
, start
, start
+len
-1 );
88 return bblmAddRun( &bblm_callbacks
, 'Pyth',
89 kind
, start
, len
, false);
97 bool addRunBefore (BBLMRunCode kind
,struct runloc
& r
, const BBLMCallbackBlock
& bblm_callbacks
)
99 bool more_runs
= addRun(kind
, r
.last_start
, r
.pos
- r
.last_start
, bblm_callbacks
);
100 r
.last_start
= r
.pos
;
104 bool addRunTo (BBLMRunCode kind
, struct runloc
& r
, const BBLMCallbackBlock
& bblm_callbacks
)
106 bool more_runs
= addRun(kind
, r
.last_start
, r
.pos
- r
.last_start
+1, bblm_callbacks
);
107 r
.last_start
= r
.pos
+1;
112 bool colorstr( char delim
,
115 const BBLMCallbackBlock
&bblm_callbacks
)
117 bool tripple
= false , pers
= false, lookup
= false, more_runs
= true;
118 char c
= nextchar(r
,pb
);
128 return addRunBefore(kBBLMRunIsSingleString
,r
,bblm_callbacks
);
131 while (c
&& more_runs
){
134 more_runs
= addRunTo(kPyBBLMStringSubst
,r
,bblm_callbacks
);
143 if ((c
= nextchar(r
,pb
))== delim
&& (c
= nextchar(r
,pb
)) == delim
){
144 break; // end of tripple-quote.
148 break; // end of single-quote.
155 else if (c
=='\r'||c
=='\n'){
161 more_runs
= addRunBefore(kBBLMRunIsSingleString
,r
,bblm_callbacks
);
164 else if (c
==')' && lookup
){
165 more_runs
= addRunTo(kPyBBLMStringSubst
,r
,bblm_callbacks
);
170 return more_runs
&& addRunTo(lookup
?kPyBBLMStringSubst
:kBBLMRunIsSingleString
,r
,bblm_callbacks
);
173 bool colorcomment(BBLMParamBlock
&pb
,
175 const BBLMCallbackBlock
&bblm_callbacks
)
177 while (char c
= nextchar(r
,pb
)){
178 if (c
=='\r'|| c
=='\n'){
182 return addRunTo(kBBLMRunIsLineComment
,r
,bblm_callbacks
);
185 void CalculateRuns(BBLMParamBlock
&pb
,
186 const BBLMCallbackBlock
&bblm_callbacks
)
189 const struct rundesc
*state
= NULL
;
194 char c
= start(r
,pb
);
196 while (c
&& more_runs
){
200 //If we're in the basic 'code' state, check for each interesting char (rundelims[i].start).
204 more_runs
= addRunBefore(kBBLMRunIsCode
,r
,bblm_callbacks
);
206 more_runs
= colorstr(c
,pb
,r
,bblm_callbacks
);
210 more_runs
= addRunBefore(kBBLMRunIsCode
,r
,bblm_callbacks
);
212 more_runs
= colorcomment(pb
,r
,bblm_callbacks
);
223 addRunBefore(kBBLMRunIsCode
,r
,bblm_callbacks
);
228 static void AdjustRange(BBLMParamBlock
¶ms
,
229 const BBLMCallbackBlock
&callbacks
)
235 UInt32 index
= params
.fAdjustRangeParams
.fStartIndex
;
238 bblmGetRun(&callbacks
, index
, language
, kind
, charPos
, length
) &&
239 (kind
==kPyBBLMStringSubst
||kind
==kBBLMRunIsSingleString
)){
242 params
.fAdjustRangeParams
.fStartIndex
= index
;
246 // The next couple funcs process the text of a file assumming it's in 1 piece in memory,
247 // so they may not be called from CalculateRuns.
249 bool matchword(BBLMParamBlock
&pb
, const char *pat
,unsigned long *pos
)
251 const char *asciText
= (const char *) (pb
.fTextIsUnicode
?NULL
:pb
.fText
);
254 for (i
=0; pat
[i
]; i
++){
255 if (*pos
+i
>=pb
.fTextLength
){
258 if (asciText
[*pos
+i
] != pat
[i
]){
262 if ((*pos
+i
<pb
.fTextLength
)&&iswordchar(asciText
[*pos
+i
])){
269 int matchindent(BBLMParamBlock
&pb
, UInt32
*pos
)
271 const char *asciText
= (const char *) (pb
.fTextIsUnicode
?NULL
:pb
.fText
);
274 while(*pos
<pb
.fTextLength
){
275 switch (/*(char)(pb.fTextIsUnicode?uniText[pos]:*/asciText
[*pos
]/*)*/){
295 void eat_line(BBLMParamBlock
&pb
, unsigned long* pos
)
297 const char *asciText
= (const char *) (pb
.fTextIsUnicode
?NULL
:pb
.fText
);
298 while (asciText
[*pos
]!='\r' && asciText
[*pos
]!='\n' && *pos
<pb
.fTextLength
) {++*pos
;}
299 while ((asciText
[*pos
]=='\r' || asciText
[*pos
]=='\n') && *pos
<pb
.fTextLength
) {++*pos
;}
303 void addItem(BBLMParamBlock
&pb
, UInt32 pos
, int nest
, BBLMFunctionKinds kind
,
304 const BBLMCallbackBlock
*bblm_callbacks
)
306 UInt32 funcstartpos
= pos
;
307 UInt32 funcnamelen
=0;
309 const char *asciText
= (const char *) pb
.fText
;
313 while (isspace(asciText
[pos
]) && pos
<pb
.fTextLength
) {++pos
;}
314 UInt32 fnamestart
= pos
;
315 while ((isalnum(asciText
[pos
])||asciText
[pos
]=='_') && pos
<pb
.fTextLength
) {pos
++; funcnamelen
++;}
317 err
= bblmAddTokenToBuffer( bblm_callbacks
,
318 pb
.fFcnParams
.fTokenBuffer
,
319 (void*)&asciText
[fnamestart
],
323 BBLMProcInfo procInfo
;
324 procInfo
.fFunctionStart
= fnamestart
; // char offset in file of first character of function
325 procInfo
.fFunctionEnd
= pos
; // char offset of last character of function
327 procInfo
.fSelStart
= fnamestart
; // first character to select when choosing function
328 procInfo
.fSelEnd
= pos
; // last character to select when choosing function
330 procInfo
.fFirstChar
= fnamestart
; // first character to make visible when choosing function
332 procInfo
.fKind
= kind
;
334 procInfo
.fIndentLevel
= nest
; // indentation level of token
335 procInfo
.fFlags
= 0; // token flags (see BBLMFunctionFlags)
336 procInfo
.fNameStart
= offset
; // char offset in token buffer of token name
337 procInfo
.fNameLength
= funcnamelen
; // length of token name
339 err
= bblmAddFunctionToList(bblm_callbacks
,
340 pb
.fFcnParams
.fFcnList
,
351 void ScanForFunctions(BBLMParamBlock
&pb
,
352 const BBLMCallbackBlock
&bblm_callbacks
)
355 const char *asciText
= (const char *) (pb
.fTextIsUnicode
?NULL
:pb
.fText
);
356 UniCharPtr uniText
= (UniCharPtr
) (pb
.fTextIsUnicode
?pb
.fText
:NULL
);
358 int indents
[maxnest
]= {0};
361 UInt32 pos
=0; // current character offset
364 while (pos
<pb
.fTextLength
){
366 int indent
= matchindent(pb
, &pos
);
369 for (int i
=0; i
<= nest
; i
++){
370 if (indent
<=indents
[i
]){
372 indents
[nest
]=indent
;
376 indents
[++nest
]=indent
;
379 if (matchword(pb
,"def",&pos
)){
380 addItem( pb
, pos
, nest
, kBBLMFunctionMark
, &bblm_callbacks
);
382 else if (matchword(pb
, "class", &pos
)){
383 addItem( pb
, pos
, nest
, kBBLMTypedef
, &bblm_callbacks
);
391 OSErr
main( BBLMParamBlock
¶ms
,
392 const BBLMCallbackBlock
&bblm_callbacks
,
393 const BBXTCallbackBlock
&bbxt_callbacks
)
397 if ((params
.fSignature
!= kBBLMParamBlockSignature
) ||
398 (params
.fLength
< sizeof(BBLMParamBlock
)))
403 switch (params
.fMessage
)
405 case kBBLMInitMessage
:
406 case kBBLMDisposeMessage
:
408 result
= noErr
; // nothing to do
412 case kBBLMCalculateRunsMessage
:
413 CalculateRuns(params
, bblm_callbacks
);
417 case kBBLMScanForFunctionsMessage
:
418 ScanForFunctions(params
, bblm_callbacks
);
422 case kBBLMAdjustRangeMessage
:
423 AdjustRange(params
, bblm_callbacks
);
427 case kBBLMMapRunKindToColorCodeMessage
:
428 switch (params
.fMapRunParams
.fRunKind
){
429 case kPyBBLMStringSubst
:
430 params
.fMapRunParams
.fColorCode
= kBBLMSGMLAttributeNameColor
;
431 params
.fMapRunParams
.fMapped
= true;
434 params
.fMapRunParams
.fMapped
= false;
439 case kBBLMEscapeStringMessage
:
440 case kBBLMAdjustEndMessage
:
441 case kBBLMMapColorCodeToColorMessage
:
442 case kBBLMSetCategoriesMessage
:
443 case kBBLMMatchKeywordMessage
:
445 result
= userCanceledErr
;