Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / js / jsd / jsd_text.c
blob16def17f3771e973a42ff58f2063d389ed30a673
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * JavaScript Debugging support - Source Text functions
42 #include <ctype.h>
43 #include "jsd.h"
45 #ifdef DEBUG
46 void JSD_ASSERT_VALID_SOURCE_TEXT(JSDSourceText* jsdsrc)
48 JS_ASSERT(jsdsrc);
49 JS_ASSERT(jsdsrc->url);
51 #endif
53 /***************************************************************************/
54 /* XXX add notification */
56 static void
57 _clearText(JSDContext* jsdc, JSDSourceText* jsdsrc)
59 if( jsdsrc->text )
60 free(jsdsrc->text);
61 jsdsrc->text = NULL;
62 jsdsrc->textLength = 0;
63 jsdsrc->textSpace = 0;
64 jsdsrc->status = JSD_SOURCE_CLEARED;
65 jsdsrc->dirty = JS_TRUE;
66 jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
67 jsdsrc->doingEval = JS_FALSE;
70 static JSBool
71 _appendText(JSDContext* jsdc, JSDSourceText* jsdsrc,
72 const char* text, size_t length)
74 #define MEMBUF_GROW 1000
76 uintN neededSize = jsdsrc->textLength + length;
78 if( neededSize > jsdsrc->textSpace )
80 char* newBuf;
81 uintN iNewSize;
83 /* if this is the first alloc, the req might be all that's needed*/
84 if( ! jsdsrc->textSpace )
85 iNewSize = length;
86 else
87 iNewSize = (neededSize * 5 / 4) + MEMBUF_GROW;
89 newBuf = (char*) realloc(jsdsrc->text, iNewSize);
90 if( ! newBuf )
92 /* try again with the minimal size really asked for */
93 iNewSize = neededSize;
94 newBuf = (char*) realloc(jsdsrc->text, iNewSize);
95 if( ! newBuf )
97 /* out of memory */
98 _clearText( jsdc, jsdsrc );
99 jsdsrc->status = JSD_SOURCE_FAILED;
100 return JS_FALSE;
104 jsdsrc->text = newBuf;
105 jsdsrc->textSpace = iNewSize;
108 memcpy(jsdsrc->text + jsdsrc->textLength, text, length);
109 jsdsrc->textLength += length;
110 return JS_TRUE;
113 static JSDSourceText*
114 _newSource(JSDContext* jsdc, const char* url)
116 JSDSourceText* jsdsrc = (JSDSourceText*)calloc(1,sizeof(JSDSourceText));
117 if( ! jsdsrc )
118 return NULL;
120 jsdsrc->url = (char*) url; /* already a copy */
121 jsdsrc->status = JSD_SOURCE_INITED;
122 jsdsrc->dirty = JS_TRUE;
123 jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
125 return jsdsrc;
128 static void
129 _destroySource(JSDContext* jsdc, JSDSourceText* jsdsrc)
131 JS_ASSERT(NULL == jsdsrc->text); /* must _clearText() first */
132 free(jsdsrc->url);
133 free(jsdsrc);
136 static void
137 _removeSource(JSDContext* jsdc, JSDSourceText* jsdsrc)
139 JS_REMOVE_LINK(&jsdsrc->links);
140 _clearText(jsdc, jsdsrc);
141 _destroySource(jsdc, jsdsrc);
144 static JSDSourceText*
145 _addSource(JSDContext* jsdc, const char* url)
147 JSDSourceText* jsdsrc = _newSource(jsdc, url);
148 if( ! jsdsrc )
149 return NULL;
150 JS_INSERT_LINK(&jsdsrc->links, &jsdc->sources);
151 return jsdsrc;
154 static void
155 _moveSourceToFront(JSDContext* jsdc, JSDSourceText* jsdsrc)
157 JS_REMOVE_LINK(&jsdsrc->links);
158 JS_INSERT_LINK(&jsdsrc->links, &jsdc->sources);
161 static void
162 _moveSourceToRemovedList(JSDContext* jsdc, JSDSourceText* jsdsrc)
164 _clearText(jsdc, jsdsrc);
165 JS_REMOVE_LINK(&jsdsrc->links);
166 JS_INSERT_LINK(&jsdsrc->links, &jsdc->removedSources);
169 static void
170 _removeSourceFromRemovedList( JSDContext* jsdc, JSDSourceText* jsdsrc )
172 JS_REMOVE_LINK(&jsdsrc->links);
173 _destroySource( jsdc, jsdsrc );
176 static JSBool
177 _isSourceInSourceList(JSDContext* jsdc, JSDSourceText* jsdsrcToFind)
179 JSDSourceText *jsdsrc;
181 for( jsdsrc = (JSDSourceText*)jsdc->sources.next;
182 jsdsrc != (JSDSourceText*)&jsdc->sources;
183 jsdsrc = (JSDSourceText*)jsdsrc->links.next )
185 if( jsdsrc == jsdsrcToFind )
186 return JS_TRUE;
188 return JS_FALSE;
191 /* compare strings in a case insensitive manner with a length limit
194 static int
195 strncasecomp (const char* one, const char * two, int n)
197 const char *pA;
198 const char *pB;
200 for(pA=one, pB=two;; pA++, pB++)
202 int tmp;
203 if (pA == one+n)
204 return 0;
205 if (!(*pA && *pB))
206 return *pA - *pB;
207 tmp = tolower(*pA) - tolower(*pB);
208 if (tmp)
209 return tmp;
213 static char file_url_prefix[] = "file:";
214 #define FILE_URL_PREFIX_LEN (sizeof file_url_prefix - 1)
216 const char*
217 jsd_BuildNormalizedURL( const char* url_string )
219 char *new_url_string;
221 if( ! url_string )
222 return NULL;
224 if (!strncasecomp(url_string, file_url_prefix, FILE_URL_PREFIX_LEN) &&
225 url_string[FILE_URL_PREFIX_LEN + 0] == '/' &&
226 url_string[FILE_URL_PREFIX_LEN + 1] == '/') {
227 new_url_string = JS_smprintf("%s%s",
228 file_url_prefix,
229 url_string + FILE_URL_PREFIX_LEN + 2);
230 } else {
231 new_url_string = strdup(url_string);
233 return new_url_string;
236 /***************************************************************************/
238 void
239 jsd_DestroyAllSources( JSDContext* jsdc )
241 JSDSourceText *jsdsrc;
242 JSDSourceText *next;
244 for( jsdsrc = (JSDSourceText*)jsdc->sources.next;
245 jsdsrc != (JSDSourceText*)&jsdc->sources;
246 jsdsrc = next )
248 next = (JSDSourceText*)jsdsrc->links.next;
249 _removeSource( jsdc, jsdsrc );
252 for( jsdsrc = (JSDSourceText*)jsdc->removedSources.next;
253 jsdsrc != (JSDSourceText*)&jsdc->removedSources;
254 jsdsrc = next )
256 next = (JSDSourceText*)jsdsrc->links.next;
257 _removeSourceFromRemovedList( jsdc, jsdsrc );
262 JSDSourceText*
263 jsd_IterateSources(JSDContext* jsdc, JSDSourceText **iterp)
265 JSDSourceText *jsdsrc = *iterp;
267 if( !jsdsrc )
268 jsdsrc = (JSDSourceText *)jsdc->sources.next;
269 if( jsdsrc == (JSDSourceText *)&jsdc->sources )
270 return NULL;
271 *iterp = (JSDSourceText *)jsdsrc->links.next;
272 return jsdsrc;
275 JSDSourceText*
276 jsd_FindSourceForURL(JSDContext* jsdc, const char* url)
278 JSDSourceText *jsdsrc;
280 for( jsdsrc = (JSDSourceText *)jsdc->sources.next;
281 jsdsrc != (JSDSourceText *)&jsdc->sources;
282 jsdsrc = (JSDSourceText *)jsdsrc->links.next )
284 if( 0 == strcmp(jsdsrc->url, url) )
285 return jsdsrc;
287 return NULL;
290 const char*
291 jsd_GetSourceURL(JSDContext* jsdc, JSDSourceText* jsdsrc)
293 return jsdsrc->url;
296 JSBool
297 jsd_GetSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc,
298 const char** ppBuf, intN* pLen )
300 *ppBuf = jsdsrc->text;
301 *pLen = jsdsrc->textLength;
302 return JS_TRUE;
305 void
306 jsd_ClearSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc)
308 if( JSD_SOURCE_INITED != jsdsrc->status &&
309 JSD_SOURCE_PARTIAL != jsdsrc->status )
311 _clearText(jsdc, jsdsrc);
315 JSDSourceStatus
316 jsd_GetSourceStatus(JSDContext* jsdc, JSDSourceText* jsdsrc)
318 return jsdsrc->status;
321 JSBool
322 jsd_IsSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc)
324 return jsdsrc->dirty;
327 void
328 jsd_SetSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc, JSBool dirty)
330 jsdsrc->dirty = dirty;
333 uintN
334 jsd_GetSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
336 return jsdsrc->alterCount;
339 uintN
340 jsd_IncrementSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
342 return jsdsrc->alterCount = jsdc->sourceAlterCount++;
345 /***************************************************************************/
347 #if defined(DEBUG) && 0
348 void DEBUG_ITERATE_SOURCES( JSDContext* jsdc )
350 JSDSourceText* iterp = NULL;
351 JSDSourceText* jsdsrc = NULL;
352 int dummy;
354 while( NULL != (jsdsrc = jsd_IterateSources(jsdc, &iterp)) )
356 const char* url;
357 const char* text;
358 int len;
359 JSBool dirty;
360 JSDStreamStatus status;
361 JSBool gotSrc;
363 url = JSD_GetSourceURL(jsdc, jsdsrc);
364 dirty = JSD_IsSourceDirty(jsdc, jsdsrc);
365 status = JSD_GetSourceStatus(jsdc, jsdsrc);
366 gotSrc = JSD_GetSourceText(jsdc, jsdsrc, &text, &len );
368 dummy = 0; /* gives us a line to set breakpoint... */
371 #else
372 #define DEBUG_ITERATE_SOURCES(x) ((void)x)
373 #endif
375 /***************************************************************************/
377 JSDSourceText*
378 jsd_NewSourceText(JSDContext* jsdc, const char* url)
380 JSDSourceText* jsdsrc;
381 const char* new_url_string;
383 JSD_LOCK_SOURCE_TEXT(jsdc);
385 #ifdef LIVEWIRE
386 new_url_string = url; /* we take ownership of alloc'd string */
387 #else
388 new_url_string = jsd_BuildNormalizedURL(url);
389 #endif
390 if( ! new_url_string )
391 return NULL;
393 jsdsrc = jsd_FindSourceForURL(jsdc, new_url_string);
395 if( jsdsrc )
397 if( jsdsrc->doingEval )
399 #ifdef LIVEWIRE
400 free((char*)new_url_string);
401 #endif
402 JSD_UNLOCK_SOURCE_TEXT(jsdc);
403 return NULL;
405 else
406 _moveSourceToRemovedList(jsdc, jsdsrc);
409 jsdsrc = _addSource( jsdc, new_url_string );
411 JSD_UNLOCK_SOURCE_TEXT(jsdc);
413 return jsdsrc;
416 JSDSourceText*
417 jsd_AppendSourceText(JSDContext* jsdc,
418 JSDSourceText* jsdsrc,
419 const char* text, /* *not* zero terminated */
420 size_t length,
421 JSDSourceStatus status)
423 JSD_LOCK_SOURCE_TEXT(jsdc);
425 if( jsdsrc->doingEval )
427 JSD_UNLOCK_SOURCE_TEXT(jsdc);
428 return NULL;
431 if( ! _isSourceInSourceList( jsdc, jsdsrc ) )
433 _removeSourceFromRemovedList( jsdc, jsdsrc );
434 JSD_UNLOCK_SOURCE_TEXT(jsdc);
435 return NULL;
438 if( text && length && ! _appendText( jsdc, jsdsrc, text, length ) )
440 jsdsrc->dirty = JS_TRUE;
441 jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
442 jsdsrc->status = JSD_SOURCE_FAILED;
443 _moveSourceToRemovedList(jsdc, jsdsrc);
444 JSD_UNLOCK_SOURCE_TEXT(jsdc);
445 return NULL;
448 jsdsrc->dirty = JS_TRUE;
449 jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
450 jsdsrc->status = status;
451 DEBUG_ITERATE_SOURCES(jsdc);
452 JSD_UNLOCK_SOURCE_TEXT(jsdc);
453 return jsdsrc;
456 JSDSourceText*
457 jsd_AppendUCSourceText(JSDContext* jsdc,
458 JSDSourceText* jsdsrc,
459 const jschar* text, /* *not* zero terminated */
460 size_t length,
461 JSDSourceStatus status)
463 #define UNICODE_TRUNCATE_BUF_SIZE 1024
464 static char* buf = NULL;
465 int remaining = length;
467 if(!text || !length)
468 return jsd_AppendSourceText(jsdc, jsdsrc, NULL, 0, status);
470 JSD_LOCK_SOURCE_TEXT(jsdc);
471 if(!buf)
473 buf = malloc(UNICODE_TRUNCATE_BUF_SIZE);
474 if(!buf)
476 JSD_UNLOCK_SOURCE_TEXT(jsdc);
477 return NULL;
480 while(remaining && jsdsrc) {
481 int bytes = JS_MIN(remaining, UNICODE_TRUNCATE_BUF_SIZE);
482 int i;
483 for(i = 0; i < bytes; i++)
484 buf[i] = (const char) *(text++);
485 jsdsrc = jsd_AppendSourceText(jsdc,jsdsrc,
486 buf, bytes,
487 JSD_SOURCE_PARTIAL);
488 remaining -= bytes;
490 if(jsdsrc && status != JSD_SOURCE_PARTIAL)
491 jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc, NULL, 0, status);
493 JSD_UNLOCK_SOURCE_TEXT(jsdc);
494 return jsdsrc;
497 /* convienence function for adding complete source of url in one call */
498 JSBool
499 jsd_AddFullSourceText(JSDContext* jsdc,
500 const char* text, /* *not* zero terminated */
501 size_t length,
502 const char* url)
504 JSDSourceText* jsdsrc;
506 JSD_LOCK_SOURCE_TEXT(jsdc);
508 jsdsrc = jsd_NewSourceText(jsdc, url);
509 if( jsdsrc )
510 jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc,
511 text, length, JSD_SOURCE_PARTIAL );
512 if( jsdsrc )
513 jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc,
514 NULL, 0, JSD_SOURCE_COMPLETED );
516 JSD_UNLOCK_SOURCE_TEXT(jsdc);
518 return jsdsrc ? JS_TRUE : JS_FALSE;
521 /***************************************************************************/
523 void
524 jsd_StartingEvalUsingFilename(JSDContext* jsdc, const char* url)
526 JSDSourceText* jsdsrc;
528 /* NOTE: We leave it locked! */
529 JSD_LOCK_SOURCE_TEXT(jsdc);
531 jsdsrc = jsd_FindSourceForURL(jsdc, url);
532 if(jsdsrc)
534 #if 0
535 #ifndef JSD_LOWLEVEL_SOURCE
536 JS_ASSERT(! jsdsrc->doingEval);
537 #endif
538 #endif
539 jsdsrc->doingEval = JS_TRUE;
543 void
544 jsd_FinishedEvalUsingFilename(JSDContext* jsdc, const char* url)
546 JSDSourceText* jsdsrc;
548 /* NOTE: We ASSUME it is locked! */
550 jsdsrc = jsd_FindSourceForURL(jsdc, url);
551 if(jsdsrc)
553 #if 0
554 #ifndef JSD_LOWLEVEL_SOURCE
556 * when using this low level source addition, this jsdsrc might
557 * not have existed before the eval, but does exist now (without
558 * this flag set!)
560 JS_ASSERT(jsdsrc->doingEval);
561 #endif
562 #endif
563 jsdsrc->doingEval = JS_FALSE;
566 JSD_UNLOCK_SOURCE_TEXT(jsdc);