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