Annotation of Amaya/amaya/insertelem.c, revision 1.22
1.1 kia 1: /*
2: *
1.21 vatton 3: * COPYRIGHT INRIA and W3C, 1996-2008
1.1 kia 4: * Please first read the full copyright statement in file COPYRIGHT.
5: *
6: */
7:
8: /*
9: * Authors: Emilien Kia
10: *
11: */
12:
13: #define THOT_EXPORT extern
14: #include "amaya.h"
15: #include "document.h"
16:
17: #include "containers.h"
18: #include "Elemlist.h"
19:
20: #ifdef TEMPLATES
21: #include "Template.h"
22: #include "templates.h"
23: #include "templates_f.h"
24: #include "templateDeclarations.h"
25:
26: #include "templateLoad_f.h"
27: #include "templateDeclarations_f.h"
28: #include "templateInstantiate_f.h"
1.19 kia 29: #include "templateUtils_f.h"
1.1 kia 30: #include "appdialogue_wx.h"
31: #include "init_f.h"
32: #include "wxdialogapi_f.h"
33: #include "AHTURLTools_f.h"
34:
35: #endif /* TEMPLATES */
36:
37:
38: #include "fetchXMLname_f.h"
39: #include "MENUconf.h"
40: #include "parser.h"
41: #include "fetchXMLname_f.h"
42:
1.2 cvs 43: typedef struct _sInsertableElementList *InsertableElementList;
44: typedef struct _sInsertableElementList
1.1 kia 45: {
46: /** Current selected element.*/
47: Element elem;
48: /** Insertable element list.*/
49: DLList list;
1.2 cvs 50: } sInsertableElementList;
1.1 kia 51:
52:
53: static HashMap InsertableElementMap = NULL;
54:
55:
1.6 vatton 56: /*----------------------------------------------------------------------
57: ----------------------------------------------------------------------*/
1.1 kia 58: static InsertableElementList InsertableElementList_Create(Element elem, DLList list)
59: {
60: InsertableElementList lst = (InsertableElementList)TtaGetMemory(sizeof(sInsertableElementList));
61: lst->elem = elem;
62: lst->list = list;
63: return lst;
64: }
65:
66: static void InsertableElementList_Destroy(InsertableElementList list)
67: {
1.8 vatton 68: if (list->list)
1.1 kia 69: DLList_Destroy(list->list);
70: TtaFreeMemory(list);
71: }
72:
73: /*----------------------------------------------------------------------
74: InsertableElement_Init
75: Initialize the module.
76: ----------------------------------------------------------------------*/
77: void InsertableElement_Init()
78: {
1.8 vatton 79: if (!InsertableElementMap)
1.1 kia 80: InsertableElementMap = PointerHashMap_Create((Container_DestroyElementFunction)InsertableElementList_Destroy, 32);
81: }
82:
83: /*----------------------------------------------------------------------
84: InsertableElement_Final
85: Finalize the module.
86: ----------------------------------------------------------------------*/
87: void InsertableElement_Final()
88: {
1.8 vatton 89: if (InsertableElementMap)
1.1 kia 90: {
91: HashMap_Destroy(InsertableElementMap);
92: InsertableElementMap = NULL;
93: }
94: }
95:
96:
97: #ifdef TEMPLATES
98: /*----------------------------------------------------------------------
99: FillUnionResolvedPossibleElement
100: Fill an element list with all possible element, resolving them if union.
101: @param name Element name
102: @param elem Document element to attach
103: @param resolvedPath Path of different succesive union name.
104: @param list List to fill.
105: ----------------------------------------------------------------------*/
1.6 vatton 106: static void FillUnionResolvedPossibleElement(XTigerTemplate t, const char* name,
107: Element elem, const char* resolvedPath,
108: DLList list, int level)
1.1 kia 109: {
1.5 kia 110: Declaration dec = Template_GetDeclaration (t, name);
1.19 kia 111: Document doc = TtaGetDocument(elem);
1.8 vatton 112: if (dec == NULL)
113: return;
1.19 kia 114:
115: if (dec->nature==ComponentNat)
1.1 kia 116: {
1.6 vatton 117: DLList_Append(list, ElemListElement_CreateComponent(level, dec->name, (void*)dec,
118: resolvedPath, elem));
1.1 kia 119: }
1.8 vatton 120: else if (dec->nature==UnionNat)
1.1 kia 121: {
1.13 kia 122: DLList tempList = ElemList_Create();
123: ForwardIterator iter = HashMap_GetForwardIterator(dec->unionType.include);
124: HashMapNode mapnode;
125: DLListNode listnode;
126:
1.1 kia 127: int len1 = 0 , len2 = strlen(dec->name);
1.8 vatton 128: if (resolvedPath!=NULL)
1.1 kia 129: len1 = strlen(resolvedPath);
130: char* newPath = (char*)TtaGetMemory(len1+len2+2);
1.17 cvs 131: if (len1 > 0)
1.1 kia 132: {
133: strcpy(newPath, resolvedPath);
134: newPath[len1] = '/';
135: strcpy(newPath+len1+1, dec->name);
136: }
137: else
138: {
139: strcpy(newPath, dec->name);
140: }
141:
1.17 cvs 142: ITERATOR_FOREACH(iter, HashMapNode, mapnode)
1.13 kia 143: {
144: FillUnionResolvedPossibleElement(t, (char*)mapnode->key, elem, newPath, tempList, level);
145: }
146: TtaFreeMemory(iter);
147:
148: iter = DLList_GetForwardIterator(tempList);
149:
1.1 kia 150:
1.13 kia 151: listnode = (DLListNode) ForwardIterator_GetFirst(iter);
1.19 kia 152: ITERATOR_FOREACH(iter, DLListNode, listnode)
1.13 kia 153: DLList_Append(list, listnode->elem);
154: TtaFreeMemory(iter);
155:
1.1 kia 156: tempList->destroyElement = NULL;
157: DLList_Destroy(tempList);
158:
159: TtaFreeMemory(newPath);
160:
161: /** todo Remove excluded elements.*/
162: }
1.8 vatton 163: else if (dec->nature==SimpleTypeNat)
1.1 kia 164: {
1.12 vatton 165: DLList_Append(list, ElemListElement_CreateBaseType(level, dec->name, resolvedPath,
166: elem));
1.1 kia 167: /* Do nothing. */
168: }
169: else
170: {
171: /* Search in tgt std elements. */
172: int xmlType; /* See parser.h */
173: for(xmlType=XHTML_TYPE; xmlType<Template_TYPE; xmlType++)
174: {
175: ElementType elType = {0,0};
176: char* mappedName;
1.2 cvs 177: char content;
1.1 kia 178: ThotBool checkProfile;
1.6 vatton 179: MapXMLElementType(xmlType, dec->name, &elType, &mappedName, &content,
1.19 kia 180: &checkProfile, doc);
1.8 vatton 181: if (elType.ElTypeNum!=0)
1.1 kia 182: {
1.19 kia 183: if(TemplateCanInsertFirstChild(elType, elem, doc))
184: DLList_Append(list, ElemListElement_CreateLanguageElement(level, elType,
1.12 vatton 185: resolvedPath, elem));
1.1 kia 186: break;
187: }
188: }
189: }
190: }
191:
192: /*----------------------------------------------------------------------
193: FillInsertableElementFromElemAttribute
194: Fill an element list with all possible elements from an attribute list.
195: ----------------------------------------------------------------------*/
1.16 vatton 196: static void FillInsertableElementFromElemAttribute (XTigerTemplate t,
197: Element elem, Element refelem,
198: int attrib, DLList list, int level)
1.1 kia 199: {
1.21 vatton 200: ElementType elType = TtaGetElementType(elem);
201: AttributeType attributeType = {elType.ElSSchema, attrib};
1.1 kia 202: Attribute att = TtaGetAttribute (elem, attributeType);
203: int size = TtaGetTextAttributeLength (att);
204: char* types = (char *) TtaGetMemory (size+1);
1.6 vatton 205:
1.1 kia 206: TtaGiveTextAttributeValue (att, types, &size);
1.14 kia 207: HashMap basemap = KeywordHashMap_CreateFromList(NULL, -1, types);
208: HashMap map = Template_ExpandHashMapTypes(t, basemap);
209: ForwardIterator iter;
210: HashMapNode node;
211:
212: iter = HashMap_GetForwardIterator(map);
213: ITERATOR_FOREACH(iter, HashMapNode, node)
214: {
215: FillUnionResolvedPossibleElement(t, (const char*)node->key, refelem, NULL, list, level);
216: }
217: HashMap_Destroy (map);
218: HashMap_Destroy (basemap);
219:
1.6 vatton 220: TtaFreeMemory (types);
1.1 kia 221: }
222: #endif/* TEMPLATES */
223:
224: /*----------------------------------------------------------------------
1.19 kia 225: SortInsertableElemList
226: Sort a list of KeywordHashMap<Declaration> to be user friendly
227: First components and then XmlElements and sorted alphabeticaly.
228: ----------------------------------------------------------------------*/
229: static int SortInsertableElemList(ElemListElement elem1 ,ElemListElement elem2)
230: {
231: #ifdef TEMPLATES
232: if(elem1->typeClass==elem2->typeClass)
233: return strcmp(ElemListElement_GetName(elem1),ElemListElement_GetName(elem2));
234: else
235: return elem1->typeClass - elem2->typeClass;
236: #else /* TEMPLATES */
237: return 0;
238: #endif /* TEMPLATES */
239: }
240:
241:
242: /*----------------------------------------------------------------------
1.1 kia 243: FillInsertableElemList
244: Fill an element list with all insertable elements (base element or
245: XTiger comonent).
246: ----------------------------------------------------------------------*/
1.21 vatton 247: void FillInsertableElemList (Document doc, Element el, DLList list)
1.1 kia 248: {
1.4 cvs 249: #ifdef TEMPLATES
1.21 vatton 250: Element child, elem;
251: ElementType elType, childType;
1.6 vatton 252: XTigerTemplate t;
1.21 vatton 253: ThotBool haveAncestor = FALSE;
1.4 cvs 254: #endif/* TEMPLATES */
1.2 cvs 255: int level;
1.17 cvs 256: ThotBool cont = TRUE;
1.2 cvs 257:
1.22 ! vatton 258: if (el)
1.21 vatton 259: {
260: if (doc == 0)
1.22 ! vatton 261: doc = TtaGetDocument(el);
1.1 kia 262:
263: #ifdef TEMPLATES
1.13 kia 264: t = GetXTigerTemplate(DocumentMeta[doc]->template_url);
1.2 cvs 265: level = 0;
266: cont = TRUE;
1.21 vatton 267: elem = el;
1.15 kia 268: // Process for each ancestor.
1.21 vatton 269: while (elem && cont)
1.1 kia 270: {
1.21 vatton 271: elType = TtaGetElementType (elem);
272: switch (elType.ElTypeNum)
1.15 kia 273: {
1.1 kia 274: case Template_EL_repeat:
275: child = TtaGetFirstChild(elem);
276: childType = TtaGetElementType(child);
1.21 vatton 277: switch (childType.ElTypeNum)
1.1 kia 278: {
279: case Template_EL_useEl:
280: case Template_EL_useSimple:
281: case Template_EL_bag:
1.21 vatton 282: FillInsertableElementFromElemAttribute(t, el, elem,
1.6 vatton 283: Template_ATTR_types, list, level);
1.1 kia 284: break;
285: default:
286: break;
287: }
1.21 vatton 288: cont = FALSE;
1.1 kia 289: break;
290: case Template_EL_useEl:
291: // Fill for xt:use only if have no child.
1.8 vatton 292: if (TtaGetFirstChild(elem)==NULL){
1.21 vatton 293: FillInsertableElementFromElemAttribute(t, el, elem,
1.6 vatton 294: Template_ATTR_types, list, level);
1.21 vatton 295: cont = FALSE;
1.1 kia 296: }
297: break;
298: case Template_EL_bag:
1.6 vatton 299: FillInsertableElementFromElemAttribute(t, elem, elem,
300: Template_ATTR_types, list, level);
1.15 kia 301: cont = FALSE;
1.1 kia 302: break;
1.15 kia 303: }
1.21 vatton 304: elem = GetFirstTemplateParentElement (elem);
1.1 kia 305: level ++;
1.15 kia 306: }
307: #endif/* TEMPLATES */
1.21 vatton 308: }
1.19 kia 309: DLList_Sort(list, (Container_CompareFunction)SortInsertableElemList);
1.1 kia 310: }
311:
312: /*----------------------------------------------------------------------
313: InsertableElement_GetList
314: Get the insertable element list for a document.
315: @param doc Document
316: @return The insertable element list or NULL.
317: ----------------------------------------------------------------------*/
318: DLList InsertableElement_GetList(Document doc)
319: {
1.16 vatton 320: InsertableElementList list;
321:
322: list = (InsertableElementList) HashMap_Get(InsertableElementMap, (void*)doc);
1.6 vatton 323: if (list)
1.1 kia 324: return list->list;
325: else
326: return NULL;
327: }
328:
329: /*----------------------------------------------------------------------
330: InsertableElement_Update
331: Update the insertable element list for a document.
332: @param el Selected element, cant be NULL.
333: @param document Document, can be NULL.
334: @return List of insertable elements.
335: ----------------------------------------------------------------------*/
1.7 kia 336: DLList InsertableElement_Update(Document doc, Element el)
1.1 kia 337: {
1.2 cvs 338: InsertableElementList list;
1.16 vatton 339:
340: if (doc == 0)
341: doc= TtaGetDocument (el);
342: list = (InsertableElementList) HashMap_Get (InsertableElementMap, (void*)doc);
343: if (list == NULL)
1.1 kia 344: {
1.16 vatton 345: list = InsertableElementList_Create (0, DLList_Create());
346: HashMap_Set (InsertableElementMap, (void*)doc, list);
1.1 kia 347: }
1.7 kia 348:
1.16 vatton 349: DLList_Empty (list->list);
350: FillInsertableElemList (doc, el, list->list);
1.7 kia 351: list->elem = el;
1.19 kia 352: return list->list;
353: }
1.7 kia 354:
1.19 kia 355: /*----------------------------------------------------------------------
356: InsertableElement_ComputeList
357: Update a insertable element list for a document.
358: @param el Selected element, cant be NULL.
359: @param document Document, can be NULL.
360: @return List of insertable elements.
361: ----------------------------------------------------------------------*/
362: DLList InsertableElement_ComputeList(Document doc, Element el)
363: {
364: DLList list = DLList_Create();
365: FillInsertableElemList (doc, el, list);
366: return list;
1.1 kia 367: }
368:
1.19 kia 369:
1.3 kia 370: /*----------------------------------------------------------------------
371: InsertableElement_DoInsertElement
372: Insert the specified element.
373: @param el Element to insert (ElemListElement)
374: ----------------------------------------------------------------------*/
1.16 vatton 375: void InsertableElement_DoInsertElement (void* el)
1.3 kia 376: {
1.16 vatton 377: ElemListElement elem = (ElemListElement) el;
378: Element ref = elem->refElem;
379: ElementType refType = TtaGetElementType (ref);
380: Document doc = TtaGetDocument (ref);
381: Element newEl = NULL;
382: SSchema templateSSchema;
1.10 kia 383:
1.6 vatton 384: #ifdef AMAYA_DEBUG
1.12 vatton 385: printf("insert %s into %s\n", ElemListElement_GetName(elem),
1.16 vatton 386: TtaGetElementTypeName (refType));
1.6 vatton 387: #endif /* AMAYA_DEBUG */
1.11 kia 388:
389: #ifdef TEMPLATES
1.16 vatton 390: templateSSchema = TtaGetSSchema ("Template", doc);
391: if (templateSSchema && refType.ElSSchema == templateSSchema)
1.3 kia 392: {
1.11 kia 393: switch(refType.ElTypeNum)
394: {
395: case Template_EL_repeat:
396: if (elem->typeClass==DefinedComponent)
1.16 vatton 397: newEl = Template_InsertRepeatChild (doc, ref,
398: (Declaration)elem->elem.component.declaration,
399: -1);
1.11 kia 400: break;
401: case Template_EL_bag:
1.16 vatton 402: newEl = Template_InsertBagChild (doc, ref,
1.18 kia 403: (Declaration)elem->elem.component.declaration,
404: FALSE);
1.11 kia 405: break;
406: default:
407: break;
408: }
409: }
1.3 kia 410: #endif /* TEMPLATES */
1.11 kia 411:
1.12 vatton 412: if (newEl)
1.16 vatton 413: TtaSelectElement (doc, newEl);
1.3 kia 414: }
1.18 kia 415:
416: /*----------------------------------------------------------------------
417: GetFirstChildElementTo
418: Find and retrieve the first child of root element which is an ascendent
419: of the leaf element.
420: If leaf is a child of root, return leaf itself.
421: ----------------------------------------------------------------------*/
422: static Element GetFirstChildElementTo(Element root, Element leaf)
423: {
424: Element parent = TtaGetParent(leaf);
425: if(root==0 || leaf==0 || parent==0)
426: return 0;
427:
428: while(parent)
429: {
430: if(parent==root)
431: return leaf;
432: leaf = parent;
433: parent = TtaGetParent(parent);
434: }
435: return 0;
436: }
437:
438: /*----------------------------------------------------------------------
439: InsertableElement_InsertElement
440: Insert the specified element in the given document before or after the selection.
441: \param el Element to insert (ElemListElement)
442: \param before True if inserting before given element, false after.
443: ----------------------------------------------------------------------*/
1.19 kia 444: Element InsertableElement_InsertElement (ElemListElement elem, ThotBool before)
1.18 kia 445: {
446: #ifdef TEMPLATES
447: Element ref = elem->refElem;
448: ElementType refType = TtaGetElementType (ref);
449: Document doc = TtaGetDocument (ref);
450: Element newEl = NULL, sibling = NULL;
451: SSchema templateSSchema;
1.19 kia 452: Element sel;
453: int car1, car2;
454: XTigerTemplate t = NULL;
455: Declaration dec = NULL;
1.18 kia 456:
457: templateSSchema = TtaGetSSchema ("Template", doc);
458:
459: if (templateSSchema && refType.ElSSchema == templateSSchema)
460: {
461: switch(refType.ElTypeNum)
462: {
463: case Template_EL_repeat:
1.19 kia 464: if(elem->typeClass==DefinedComponent)
465: dec = (Declaration)elem->elem.component.declaration;
466: else if (elem->typeClass==LanguageElement)
467: {
468: t = GetXTigerDocTemplate(TtaGetDocument(elem->refElem));
469: if (t)
470: dec = Template_GetElementDeclaration(t, ElemListElement_GetName(elem));
471: }
472: if (dec)
1.18 kia 473: {
1.19 kia 474:
1.18 kia 475: TtaGiveFirstSelectedElement(doc, &sel, &car1, &car2);
476: sibling = GetFirstChildElementTo(ref, sel);
477: if(sibling)
478: {
479: if(before)
480: TtaPreviousSibling(&sibling);
1.19 kia 481: newEl = Template_InsertRepeatChildAfter (doc, ref, dec, sibling);
1.18 kia 482: }
483: }
484: break;
485: case Template_EL_bag:
1.19 kia 486: if(elem->typeClass==DefinedComponent)
487: dec = (Declaration)elem->elem.component.declaration;
488: else if (elem->typeClass==LanguageElement)
489: {
490: t = GetXTigerDocTemplate(TtaGetDocument(elem->refElem));
491: if (t)
492: dec = Template_GetElementDeclaration(t, ElemListElement_GetName(elem));
493: }
494: if (dec)
495: newEl = Template_InsertBagChild (doc, ref, dec, before);
1.18 kia 496: break;
497: default:
498: break;
499: }
500: }
1.19 kia 501: return newEl;
502: #else /* TEMPLATES */
503: return NULL;
1.18 kia 504: #endif /* TEMPLATES */
505: }
506:
507:
508: /*----------------------------------------------------------------------
509: InsertableElement_QueryInsertElement(void* el, ThotBool bAfter)
510: Do a InsertableElement_InsertElement with undo/redo management.
511: ----------------------------------------------------------------------*/
1.19 kia 512: void InsertableElement_QueryInsertElement(ElemListElement elem, ThotBool before)
1.18 kia 513: {
514: #ifdef TEMPLATES
1.19 kia 515: Element elSel, newEl, firstEl;
516: int firstSel, lastSel;
517: Document doc = TtaGetDocument(elem->refElem);
518:
519: ThotBool oldStructureChecking;
520: DisplayMode dispMode;
521:
522: // If document is readonly, dont do anything
523: if (!TtaGetDocumentAccessMode(doc))
524: return;
525:
526: TtaGiveFirstSelectedElement(doc, &elSel, &firstSel, &lastSel);
527:
528:
529: dispMode = TtaGetDisplayMode (doc);
530: if (dispMode == DisplayImmediately)
531: /* don't set NoComputedDisplay
532: -> it breaks down views formatting when Enter generates new elements */
533: TtaSetDisplayMode (doc, DeferredDisplay);
534:
535: /* Prepare insertion.*/
536: oldStructureChecking = TtaGetStructureChecking (doc);
537: TtaSetStructureChecking (FALSE, doc);
1.20 vatton 538: TtaOpenUndoSequence (doc, NULL, NULL, 0, 0);
1.19 kia 539:
540: /* Do the insertion */
541: newEl = InsertableElement_InsertElement (elem, before);
542:
543: /* Finish insertion.*/
544: TtaCloseUndoSequence (doc);
545: TtaSetDocumentModified (doc);
546: TtaSetStructureChecking (oldStructureChecking, doc);
547: // restore the display
548: TtaSetDisplayMode (doc, dispMode);
549:
1.20 vatton 550: if (newEl)
1.19 kia 551: {
1.20 vatton 552: firstEl = GetFirstEditableElement (newEl);
553: if (firstEl)
554: {
555: TtaSelectElement (doc, firstEl);
556: TtaSetStatusSelectedElement (doc, 1, firstEl);
557: }
558: else
559: {
560: TtaSelectElement (doc, newEl);
561: TtaSetStatusSelectedElement (doc, 1, newEl);
562: }
1.19 kia 563: }
1.18 kia 564: #endif /* TEMPLATES */
565: }
Webmaster