Return to insertelem.c CVS log | Up to [Public] / Amaya / amaya |
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.25 ! kia 106: static void FillUnionResolvedPossibleElement(XTigerTemplate t, Declaration dec, 1.6 vatton 107: Element elem, const char* resolvedPath, 108: DLList list, int level) 1.1 kia 109: { 1.25 ! kia 110: Document doc; ! 111: if(t && dec && elem) 1.1 kia 112: { 1.25 ! kia 113: doc = TtaGetDocument(elem); ! 114: if (dec->nature==ComponentNat) ! 115: DLList_Append(list, ElemListElement_CreateComponent(level, dec->name, (void*)dec, ! 116: resolvedPath, elem)); ! 117: else if (dec->nature==UnionNat) ! 118: { ! 119: DLList tempList = ElemList_Create(); ! 120: ForwardIterator iter = SearchSet_GetForwardIterator(dec->unionType.include); ! 121: SearchSetNode mapnode; ! 122: DLListNode listnode; ! 123: ! 124: int len1 = 0 , len2 = strlen(dec->name); ! 125: if (resolvedPath!=NULL) ! 126: len1 = strlen(resolvedPath); ! 127: char* newPath = (char*)TtaGetMemory(len1+len2+2); ! 128: if (len1 > 0) ! 129: { ! 130: strcpy(newPath, resolvedPath); ! 131: newPath[len1] = '/'; ! 132: strcpy(newPath+len1+1, dec->name); ! 133: } ! 134: else ! 135: strcpy(newPath, dec->name); ! 136: ! 137: ITERATOR_FOREACH(iter, SearchSetNode, mapnode) ! 138: { ! 139: FillUnionResolvedPossibleElement(t, (Declaration)mapnode->elem, elem, newPath, tempList, level); ! 140: } ! 141: TtaFreeMemory(iter); ! 142: ! 143: iter = DLList_GetForwardIterator(tempList); ! 144: ! 145: ! 146: listnode = (DLListNode) ForwardIterator_GetFirst(iter); ! 147: ITERATOR_FOREACH(iter, DLListNode, listnode) ! 148: DLList_Append(list, listnode->elem); ! 149: TtaFreeMemory(iter); ! 150: ! 151: tempList->destroyElement = NULL; ! 152: DLList_Destroy(tempList); ! 153: ! 154: TtaFreeMemory(newPath); ! 155: ! 156: /** todo Remove excluded elements.*/ ! 157: } ! 158: else if (dec->nature==SimpleTypeNat) ! 159: DLList_Append(list, ElemListElement_CreateBaseType(level, dec->name, resolvedPath, ! 160: elem)); ! 161: /* Do nothing. */ ! 162: else ! 163: { ! 164: /* Search in tgt std elements. */ ! 165: int xmlType; /* See parser.h */ ! 166: for(xmlType=XHTML_TYPE; xmlType<Template_TYPE; xmlType++) ! 167: { ! 168: ElementType elType = {0,0}; ! 169: char* mappedName; ! 170: char content; ! 171: ThotBool checkProfile; ! 172: MapXMLElementType(xmlType, dec->name, &elType, &mappedName, &content, ! 173: &checkProfile, doc); ! 174: if (elType.ElTypeNum!=0) ! 175: { ! 176: if(TemplateCanInsertFirstChild(elType, elem, doc)) ! 177: DLList_Append(list, ElemListElement_CreateLanguageElement(level, elType, ! 178: resolvedPath, elem)); ! 179: break; ! 180: } ! 181: } ! 182: } 1.1 kia 183: } 184: } 185: 186: /*---------------------------------------------------------------------- 187: FillInsertableElementFromElemAttribute 188: Fill an element list with all possible elements from an attribute list. 189: ----------------------------------------------------------------------*/ 1.16 vatton 190: static void FillInsertableElementFromElemAttribute (XTigerTemplate t, 191: Element elem, Element refelem, 192: int attrib, DLList list, int level) 1.1 kia 193: { 1.25 ! kia 194: ElementType elType = TtaGetElementType(elem); 1.21 vatton 195: AttributeType attributeType = {elType.ElSSchema, attrib}; 1.25 ! kia 196: Attribute att = TtaGetAttribute (elem, attributeType); ! 197: int size = TtaGetTextAttributeLength (att); ! 198: char* types = (char *) TtaGetMemory (size+1); 1.6 vatton 199: 1.1 kia 200: TtaGiveTextAttributeValue (att, types, &size); 1.25 ! kia 201: SearchSet set = Template_GetDeclarationSetFromNames(t, types, true); 1.14 kia 202: ForwardIterator iter; 1.25 ! kia 203: SearchSetNode node; 1.14 kia 204: 1.25 ! kia 205: iter = SearchSet_GetForwardIterator(set); ! 206: ITERATOR_FOREACH(iter, SearchSetNode, node) 1.14 kia 207: { 1.25 ! kia 208: FillUnionResolvedPossibleElement(t, (Declaration)node->elem, refelem, NULL, list, level); 1.14 kia 209: } 1.25 ! kia 210: SearchSet_Destroy (set); 1.6 vatton 211: TtaFreeMemory (types); 1.1 kia 212: } 213: #endif/* TEMPLATES */ 214: 215: /*---------------------------------------------------------------------- 1.19 kia 216: SortInsertableElemList 217: Sort a list of KeywordHashMap<Declaration> to be user friendly 218: First components and then XmlElements and sorted alphabeticaly. 219: ----------------------------------------------------------------------*/ 220: static int SortInsertableElemList(ElemListElement elem1 ,ElemListElement elem2) 221: { 222: #ifdef TEMPLATES 223: if(elem1->typeClass==elem2->typeClass) 224: return strcmp(ElemListElement_GetName(elem1),ElemListElement_GetName(elem2)); 225: else 226: return elem1->typeClass - elem2->typeClass; 227: #else /* TEMPLATES */ 228: return 0; 229: #endif /* TEMPLATES */ 230: } 231: 232: 233: /*---------------------------------------------------------------------- 1.1 kia 234: FillInsertableElemList 235: Fill an element list with all insertable elements (base element or 236: XTiger comonent). 237: ----------------------------------------------------------------------*/ 1.21 vatton 238: void FillInsertableElemList (Document doc, Element el, DLList list) 1.1 kia 239: { 1.4 cvs 240: #ifdef TEMPLATES 1.21 vatton 241: Element child, elem; 242: ElementType elType, childType; 1.6 vatton 243: XTigerTemplate t; 1.4 cvs 244: #endif/* TEMPLATES */ 1.2 cvs 245: int level; 1.17 cvs 246: ThotBool cont = TRUE; 1.2 cvs 247: 1.22 vatton 248: if (el) 1.21 vatton 249: { 250: if (doc == 0) 1.22 vatton 251: doc = TtaGetDocument(el); 1.1 kia 252: 253: #ifdef TEMPLATES 1.24 kia 254: t = GetXTigerDocTemplate(doc); 1.2 cvs 255: level = 0; 256: cont = TRUE; 1.21 vatton 257: elem = el; 1.15 kia 258: // Process for each ancestor. 1.21 vatton 259: while (elem && cont) 1.1 kia 260: { 1.21 vatton 261: elType = TtaGetElementType (elem); 262: switch (elType.ElTypeNum) 1.15 kia 263: { 1.1 kia 264: case Template_EL_repeat: 265: child = TtaGetFirstChild(elem); 266: childType = TtaGetElementType(child); 1.21 vatton 267: switch (childType.ElTypeNum) 1.1 kia 268: { 269: case Template_EL_useEl: 270: case Template_EL_useSimple: 271: case Template_EL_bag: 1.21 vatton 272: FillInsertableElementFromElemAttribute(t, el, elem, 1.6 vatton 273: Template_ATTR_types, list, level); 1.1 kia 274: break; 275: default: 276: break; 277: } 1.21 vatton 278: cont = FALSE; 1.1 kia 279: break; 280: case Template_EL_useEl: 281: // Fill for xt:use only if have no child. 1.8 vatton 282: if (TtaGetFirstChild(elem)==NULL){ 1.21 vatton 283: FillInsertableElementFromElemAttribute(t, el, elem, 1.6 vatton 284: Template_ATTR_types, list, level); 1.21 vatton 285: cont = FALSE; 1.1 kia 286: } 287: break; 288: case Template_EL_bag: 1.6 vatton 289: FillInsertableElementFromElemAttribute(t, elem, elem, 290: Template_ATTR_types, list, level); 1.15 kia 291: cont = FALSE; 1.1 kia 292: break; 1.15 kia 293: } 1.21 vatton 294: elem = GetFirstTemplateParentElement (elem); 1.1 kia 295: level ++; 1.15 kia 296: } 297: #endif/* TEMPLATES */ 1.21 vatton 298: } 1.19 kia 299: DLList_Sort(list, (Container_CompareFunction)SortInsertableElemList); 1.1 kia 300: } 301: 302: /*---------------------------------------------------------------------- 303: InsertableElement_GetList 304: Get the insertable element list for a document. 305: @param doc Document 306: @return The insertable element list or NULL. 307: ----------------------------------------------------------------------*/ 308: DLList InsertableElement_GetList(Document doc) 309: { 1.16 vatton 310: InsertableElementList list; 311: 312: list = (InsertableElementList) HashMap_Get(InsertableElementMap, (void*)doc); 1.6 vatton 313: if (list) 1.1 kia 314: return list->list; 315: else 316: return NULL; 317: } 318: 319: /*---------------------------------------------------------------------- 320: InsertableElement_Update 321: Update the insertable element list for a document. 322: @param el Selected element, cant be NULL. 323: @param document Document, can be NULL. 324: @return List of insertable elements. 325: ----------------------------------------------------------------------*/ 1.7 kia 326: DLList InsertableElement_Update(Document doc, Element el) 1.1 kia 327: { 1.2 cvs 328: InsertableElementList list; 1.16 vatton 329: 330: if (doc == 0) 331: doc= TtaGetDocument (el); 332: list = (InsertableElementList) HashMap_Get (InsertableElementMap, (void*)doc); 333: if (list == NULL) 1.1 kia 334: { 1.16 vatton 335: list = InsertableElementList_Create (0, DLList_Create()); 336: HashMap_Set (InsertableElementMap, (void*)doc, list); 1.1 kia 337: } 1.7 kia 338: 1.16 vatton 339: DLList_Empty (list->list); 340: FillInsertableElemList (doc, el, list->list); 1.7 kia 341: list->elem = el; 1.19 kia 342: return list->list; 343: } 1.7 kia 344: 1.19 kia 345: /*---------------------------------------------------------------------- 346: InsertableElement_ComputeList 347: Update a insertable element list for a document. 348: @param el Selected element, cant be NULL. 349: @param document Document, can be NULL. 350: @return List of insertable elements. 351: ----------------------------------------------------------------------*/ 352: DLList InsertableElement_ComputeList(Document doc, Element el) 353: { 354: DLList list = DLList_Create(); 355: FillInsertableElemList (doc, el, list); 356: return list; 1.1 kia 357: } 358: 1.19 kia 359: 1.3 kia 360: /*---------------------------------------------------------------------- 361: InsertableElement_DoInsertElement 362: Insert the specified element. 363: @param el Element to insert (ElemListElement) 364: ----------------------------------------------------------------------*/ 1.16 vatton 365: void InsertableElement_DoInsertElement (void* el) 1.3 kia 366: { 1.16 vatton 367: ElemListElement elem = (ElemListElement) el; 368: Element ref = elem->refElem; 369: ElementType refType = TtaGetElementType (ref); 370: Document doc = TtaGetDocument (ref); 371: Element newEl = NULL; 372: SSchema templateSSchema; 1.10 kia 373: 1.6 vatton 374: #ifdef AMAYA_DEBUG 1.12 vatton 375: printf("insert %s into %s\n", ElemListElement_GetName(elem), 1.16 vatton 376: TtaGetElementTypeName (refType)); 1.6 vatton 377: #endif /* AMAYA_DEBUG */ 1.11 kia 378: 379: #ifdef TEMPLATES 1.16 vatton 380: templateSSchema = TtaGetSSchema ("Template", doc); 381: if (templateSSchema && refType.ElSSchema == templateSSchema) 1.3 kia 382: { 1.11 kia 383: switch(refType.ElTypeNum) 384: { 385: case Template_EL_repeat: 386: if (elem->typeClass==DefinedComponent) 1.16 vatton 387: newEl = Template_InsertRepeatChild (doc, ref, 388: (Declaration)elem->elem.component.declaration, 389: -1); 1.11 kia 390: break; 391: case Template_EL_bag: 1.16 vatton 392: newEl = Template_InsertBagChild (doc, ref, 1.18 kia 393: (Declaration)elem->elem.component.declaration, 394: FALSE); 1.11 kia 395: break; 396: default: 397: break; 398: } 399: } 1.3 kia 400: #endif /* TEMPLATES */ 1.11 kia 401: 1.12 vatton 402: if (newEl) 1.16 vatton 403: TtaSelectElement (doc, newEl); 1.3 kia 404: } 1.18 kia 405: 406: /*---------------------------------------------------------------------- 407: GetFirstChildElementTo 408: Find and retrieve the first child of root element which is an ascendent 409: of the leaf element. 410: If leaf is a child of root, return leaf itself. 411: ----------------------------------------------------------------------*/ 412: static Element GetFirstChildElementTo(Element root, Element leaf) 413: { 414: Element parent = TtaGetParent(leaf); 415: if(root==0 || leaf==0 || parent==0) 416: return 0; 417: 418: while(parent) 419: { 420: if(parent==root) 421: return leaf; 422: leaf = parent; 423: parent = TtaGetParent(parent); 424: } 425: return 0; 426: } 427: 428: /*---------------------------------------------------------------------- 429: InsertableElement_InsertElement 430: Insert the specified element in the given document before or after the selection. 431: \param el Element to insert (ElemListElement) 432: \param before True if inserting before given element, false after. 433: ----------------------------------------------------------------------*/ 1.19 kia 434: Element InsertableElement_InsertElement (ElemListElement elem, ThotBool before) 1.18 kia 435: { 436: #ifdef TEMPLATES 437: Element ref = elem->refElem; 438: ElementType refType = TtaGetElementType (ref); 439: Document doc = TtaGetDocument (ref); 440: Element newEl = NULL, sibling = NULL; 441: SSchema templateSSchema; 1.19 kia 442: Element sel; 443: int car1, car2; 444: XTigerTemplate t = NULL; 445: Declaration dec = NULL; 1.18 kia 446: 447: templateSSchema = TtaGetSSchema ("Template", doc); 448: 449: if (templateSSchema && refType.ElSSchema == templateSSchema) 450: { 451: switch(refType.ElTypeNum) 452: { 453: case Template_EL_repeat: 1.19 kia 454: if(elem->typeClass==DefinedComponent) 455: dec = (Declaration)elem->elem.component.declaration; 456: else if (elem->typeClass==LanguageElement) 457: { 458: t = GetXTigerDocTemplate(TtaGetDocument(elem->refElem)); 459: if (t) 460: dec = Template_GetElementDeclaration(t, ElemListElement_GetName(elem)); 461: } 462: if (dec) 1.18 kia 463: { 1.19 kia 464: 1.18 kia 465: TtaGiveFirstSelectedElement(doc, &sel, &car1, &car2); 466: sibling = GetFirstChildElementTo(ref, sel); 467: if(sibling) 468: { 469: if(before) 470: TtaPreviousSibling(&sibling); 1.19 kia 471: newEl = Template_InsertRepeatChildAfter (doc, ref, dec, sibling); 1.18 kia 472: } 473: } 474: break; 475: case Template_EL_bag: 1.19 kia 476: if(elem->typeClass==DefinedComponent) 477: dec = (Declaration)elem->elem.component.declaration; 478: else if (elem->typeClass==LanguageElement) 479: { 480: t = GetXTigerDocTemplate(TtaGetDocument(elem->refElem)); 481: if (t) 482: dec = Template_GetElementDeclaration(t, ElemListElement_GetName(elem)); 483: } 484: if (dec) 485: newEl = Template_InsertBagChild (doc, ref, dec, before); 1.18 kia 486: break; 487: default: 488: break; 489: } 490: } 1.19 kia 491: return newEl; 492: #else /* TEMPLATES */ 493: return NULL; 1.18 kia 494: #endif /* TEMPLATES */ 495: } 496: 497: 498: /*---------------------------------------------------------------------- 499: InsertableElement_QueryInsertElement(void* el, ThotBool bAfter) 500: Do a InsertableElement_InsertElement with undo/redo management. 501: ----------------------------------------------------------------------*/ 1.19 kia 502: void InsertableElement_QueryInsertElement(ElemListElement elem, ThotBool before) 1.18 kia 503: { 504: #ifdef TEMPLATES 1.19 kia 505: Element elSel, newEl, firstEl; 506: int firstSel, lastSel; 507: Document doc = TtaGetDocument(elem->refElem); 508: 509: ThotBool oldStructureChecking; 510: DisplayMode dispMode; 511: 512: // If document is readonly, dont do anything 513: if (!TtaGetDocumentAccessMode(doc)) 514: return; 515: 516: TtaGiveFirstSelectedElement(doc, &elSel, &firstSel, &lastSel); 517: 518: 519: dispMode = TtaGetDisplayMode (doc); 520: if (dispMode == DisplayImmediately) 521: /* don't set NoComputedDisplay 522: -> it breaks down views formatting when Enter generates new elements */ 523: TtaSetDisplayMode (doc, DeferredDisplay); 524: 525: /* Prepare insertion.*/ 526: oldStructureChecking = TtaGetStructureChecking (doc); 527: TtaSetStructureChecking (FALSE, doc); 1.20 vatton 528: TtaOpenUndoSequence (doc, NULL, NULL, 0, 0); 1.19 kia 529: 530: /* Do the insertion */ 531: newEl = InsertableElement_InsertElement (elem, before); 532: 533: /* Finish insertion.*/ 534: TtaCloseUndoSequence (doc); 535: TtaSetDocumentModified (doc); 536: TtaSetStructureChecking (oldStructureChecking, doc); 537: // restore the display 538: TtaSetDisplayMode (doc, dispMode); 539: 1.20 vatton 540: if (newEl) 1.19 kia 541: { 1.20 vatton 542: firstEl = GetFirstEditableElement (newEl); 543: if (firstEl) 544: { 545: TtaSelectElement (doc, firstEl); 546: TtaSetStatusSelectedElement (doc, 1, firstEl); 547: } 548: else 549: { 550: TtaSelectElement (doc, newEl); 551: TtaSetStatusSelectedElement (doc, 1, newEl); 552: } 1.19 kia 553: } 1.18 kia 554: #endif /* TEMPLATES */ 555: }