Attachment #623485: Patch part 1, v1 -- Clean up some nsHTMLEditRules methods for bug #590640

View | Details | Raw Unified | Return to bug 590640
Collapse All | Expand All

(-)a/editor/libeditor/html/nsHTMLEditRules.cpp (-248 / +237 lines)
Line     Link Here 
 Lines 2940-3264   nsHTMLEditRules::DidDeleteSelection(nsIS Link Here 
2940
    }
2940
    }
2941
  }
2941
  }
2942
  
2942
  
2943
  // call through to base class
2943
  // call through to base class
2944
  return nsTextEditRules::DidDeleteSelection(aSelection, aDir, aResult);
2944
  return nsTextEditRules::DidDeleteSelection(aSelection, aDir, aResult);
2945
}
2945
}
2946
2946
2947
nsresult
2947
nsresult
2948
nsHTMLEditRules::WillMakeList(nsISelection *aSelection, 
2948
nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
2949
                              const nsAString *aListType, 
2949
                              const nsAString* aListType,
2950
                              bool aEntireList,
2950
                              bool aEntireList,
2951
                              const nsAString *aBulletType,
2951
                              const nsAString* aBulletType,
2952
                              bool *aCancel,
2952
                              bool* aCancel,
2953
                              bool *aHandled,
2953
                              bool* aHandled,
2954
                              const nsAString *aItemType)
2954
                              const nsAString* aItemType)
2955
{
2955
{
2956
  if (!aSelection || !aListType || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
2956
  if (!aSelection || !aListType || !aCancel || !aHandled) {
2957
    return NS_ERROR_NULL_POINTER;
2958
  }
2959
  nsCOMPtr<nsIAtom> listTypeAtom = do_GetAtom(*aListType);
2957
2960
2958
  nsresult res = WillInsert(aSelection, aCancel);
2961
  nsresult res = WillInsert(aSelection, aCancel);
2959
  NS_ENSURE_SUCCESS(res, res);
2962
  NS_ENSURE_SUCCESS(res, res);
2960
2963
2961
  // initialize out param
2964
  // initialize out param
2962
  // we want to ignore result of WillInsert()
2965
  // we want to ignore result of WillInsert()
2963
  *aCancel = false;
2966
  *aCancel = false;
2964
  *aHandled = false;
2967
  *aHandled = false;
2965
2968
2966
  // deduce what tag to use for list items
2969
  // deduce what tag to use for list items
2967
  nsAutoString itemType;
2970
  nsAutoString itemType;
2968
  if (aItemType) 
2971
  if (aItemType) {
2969
    itemType = *aItemType;
2972
    itemType = *aItemType;
2970
  else if (aListType->LowerCaseEqualsLiteral("dl"))
2973
  } else if (aListType->LowerCaseEqualsLiteral("dl")) {
2971
    itemType.AssignLiteral("dd");
2974
    itemType.AssignLiteral("dd");
2972
  else
2975
  } else {
2973
    itemType.AssignLiteral("li");
2976
    itemType.AssignLiteral("li");
2974
    
2977
  }
2978
2975
  // convert the selection ranges into "promoted" selection ranges:
2979
  // convert the selection ranges into "promoted" selection ranges:
2976
  // this basically just expands the range to include the immediate
2980
  // this basically just expands the range to include the immediate
2977
  // block parent, and then further expands to include any ancestors
2981
  // block parent, and then further expands to include any ancestors
2978
  // whose children are all in the range
2982
  // whose children are all in the range
2979
  
2983
2980
  *aHandled = true;
2984
  *aHandled = true;
2981
2985
2982
  res = NormalizeSelection(aSelection);
2986
  res = NormalizeSelection(aSelection);
2983
  NS_ENSURE_SUCCESS(res, res);
2987
  NS_ENSURE_SUCCESS(res, res);
2984
  nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
2988
  nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
2985
  
2989
2986
  nsCOMArray<nsIDOMNode> arrayOfNodes;
2990
  nsCOMArray<nsIDOMNode> arrayOfNodes;
2987
  res = GetListActionNodes(arrayOfNodes, aEntireList);
2991
  res = GetListActionNodes(arrayOfNodes, aEntireList);
2988
  NS_ENSURE_SUCCESS(res, res);
2992
  NS_ENSURE_SUCCESS(res, res);
2989
  
2993
2990
  PRInt32 listCount = arrayOfNodes.Count();
2994
  PRInt32 listCount = arrayOfNodes.Count();
2991
  
2995
2992
  // check if all our nodes are <br>s, or empty inlines
2996
  // check if all our nodes are <br>s, or empty inlines
2993
  bool bOnlyBreaks = true;
2997
  bool bOnlyBreaks = true;
2994
  PRInt32 j;
2998
  for (PRInt32 j = 0; j < listCount; j++) {
2995
  for (j=0; j<listCount; j++)
2996
  {
2997
    nsIDOMNode* curNode = arrayOfNodes[j];
2999
    nsIDOMNode* curNode = arrayOfNodes[j];
2998
    // if curNode is not a Break or empty inline, we're done
3000
    // if curNode is not a Break or empty inline, we're done
2999
    if ( (!nsTextEditUtils::IsBreak(curNode)) && (!IsEmptyInline(curNode)) )
3001
    if (!nsTextEditUtils::IsBreak(curNode) && !IsEmptyInline(curNode)) {
3000
    {
3001
      bOnlyBreaks = false;
3002
      bOnlyBreaks = false;
3002
      break;
3003
      break;
3003
    }
3004
    }
3004
  }
3005
  }
3005
  
3006
3006
  // if no nodes, we make empty list.  Ditto if the user tried to make a list of some # of breaks.
3007
  // if no nodes, we make empty list.  Ditto if the user tried to make a list
3007
  if (!listCount || bOnlyBreaks) 
3008
  // of some # of breaks.
3008
  {
3009
  if (!listCount || bOnlyBreaks) {
3009
    nsCOMPtr<nsIDOMNode> parent, theList, theListItem;
3010
    nsCOMPtr<nsIDOMNode> parent, theList, theListItem;
3010
    PRInt32 offset;
3011
    PRInt32 offset;
3011
3012
3012
    // if only breaks, delete them
3013
    // if only breaks, delete them
3013
    if (bOnlyBreaks)
3014
    if (bOnlyBreaks) {
3014
    {
3015
      for (PRInt32 j = 0; j < (PRInt32)listCount; j++) {
3015
      for (j=0; j<(PRInt32)listCount; j++)
3016
      {
3017
        res = mHTMLEditor->DeleteNode(arrayOfNodes[j]);
3016
        res = mHTMLEditor->DeleteNode(arrayOfNodes[j]);
3018
        NS_ENSURE_SUCCESS(res, res);
3017
        NS_ENSURE_SUCCESS(res, res);
3019
      }
3018
      }
3020
    }
3019
    }
3021
    
3020
3022
    // get selection location
3021
    // get selection location
3023
    res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
3022
    res = mHTMLEditor->GetStartNodeAndOffset(aSelection,
3024
    NS_ENSURE_SUCCESS(res, res);
3023
                                             getter_AddRefs(parent), &offset);
3025
    
3024
    NS_ENSURE_SUCCESS(res, res);
3025
3026
    // make sure we can put a list here
3026
    // make sure we can put a list here
3027
    nsCOMPtr<nsIAtom> listTypeAtom = do_GetAtom(*aListType);
3028
    if (!mHTMLEditor->CanContainTag(parent, listTypeAtom)) {
3027
    if (!mHTMLEditor->CanContainTag(parent, listTypeAtom)) {
3029
      *aCancel = true;
3028
      *aCancel = true;
3030
      return NS_OK;
3029
      return NS_OK;
3031
    }
3030
    }
3032
    res = SplitAsNeeded(aListType, address_of(parent), &offset);
3031
    res = SplitAsNeeded(aListType, address_of(parent), &offset);
3033
    NS_ENSURE_SUCCESS(res, res);
3032
    NS_ENSURE_SUCCESS(res, res);
3034
    res = mHTMLEditor->CreateNode(*aListType, parent, offset, getter_AddRefs(theList));
3033
    res = mHTMLEditor->CreateNode(*aListType, parent, offset,
3035
    NS_ENSURE_SUCCESS(res, res);
3034
                                  getter_AddRefs(theList));
3036
    res = mHTMLEditor->CreateNode(itemType, theList, 0, getter_AddRefs(theListItem));
3035
    NS_ENSURE_SUCCESS(res, res);
3036
    res = mHTMLEditor->CreateNode(itemType, theList, 0,
3037
                                  getter_AddRefs(theListItem));
3037
    NS_ENSURE_SUCCESS(res, res);
3038
    NS_ENSURE_SUCCESS(res, res);
3038
    // remember our new block for postprocessing
3039
    // remember our new block for postprocessing
3039
    mNewBlock = theListItem;
3040
    mNewBlock = theListItem;
3040
    // put selection in new list item
3041
    // put selection in new list item
3041
    res = aSelection->Collapse(theListItem,0);
3042
    res = aSelection->Collapse(theListItem, 0);
3042
    selectionResetter.Abort();  // to prevent selection reseter from overriding us.
3043
    // to prevent selection resetter from overriding us
3044
    selectionResetter.Abort();
3043
    *aHandled = true;
3045
    *aHandled = true;
3044
    return res;
3046
    return res;
3045
  }
3047
  }
3046
3048
3047
  // if there is only one node in the array, and it is a list, div, or blockquote,
3049
  // if there is only one node in the array, and it is a list, div, or
3048
  // then look inside of it until we find inner list or content.
3050
  // blockquote, then look inside of it until we find inner list or content.
3049
3051
3050
  res = LookInsideDivBQandList(arrayOfNodes);
3052
  res = LookInsideDivBQandList(arrayOfNodes);
3051
  NS_ENSURE_SUCCESS(res, res);                                 
3053
  NS_ENSURE_SUCCESS(res, res);
3052
3054
3053
  // Ok, now go through all the nodes and put then in the list, 
3055
  // Ok, now go through all the nodes and put then in the list,
3054
  // or whatever is approriate.  Wohoo!
3056
  // or whatever is approriate.  Wohoo!
3055
3057
3056
  listCount = arrayOfNodes.Count();
3058
  listCount = arrayOfNodes.Count();
3057
  nsCOMPtr<nsIDOMNode> curParent;
3059
  nsCOMPtr<nsIDOMNode> curParent;
3058
  nsCOMPtr<nsIDOMNode> curList;
3060
  nsCOMPtr<nsIDOMNode> curList;
3059
  nsCOMPtr<nsIDOMNode> prevListItem;
3061
  nsCOMPtr<nsIDOMNode> prevListItem;
3060
  
3062
3061
  PRInt32 i;
3063
  for (PRInt32 i = 0; i < listCount; i++) {
3062
  for (i=0; i<listCount; i++)
3063
  {
3064
    // here's where we actually figure out what to do
3064
    // here's where we actually figure out what to do
3065
    nsCOMPtr<nsIDOMNode> newBlock;
3065
    nsCOMPtr<nsIDOMNode> newBlock;
3066
    nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
3066
    nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
3067
    PRInt32 offset;
3067
    PRInt32 offset;
3068
    res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
3068
    res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
3069
    NS_ENSURE_SUCCESS(res, res);
3069
    NS_ENSURE_SUCCESS(res, res);
3070
  
3070
3071
    // make sure we don't assemble content that is in different table cells into the same list.
3071
    // make sure we don't assemble content that is in different table cells
3072
    // respect table cell boundaries when listifying.
3072
    // into the same list.  respect table cell boundaries when listifying.
3073
    if (curList)
3073
    if (curList) {
3074
    {
3075
      bool bInDifTblElems;
3074
      bool bInDifTblElems;
3076
      res = InDifferentTableElements(curList, curNode, &bInDifTblElems);
3075
      res = InDifferentTableElements(curList, curNode, &bInDifTblElems);
3077
      NS_ENSURE_SUCCESS(res, res);
3076
      NS_ENSURE_SUCCESS(res, res);
3078
      if (bInDifTblElems)
3077
      if (bInDifTblElems) {
3079
        curList = nsnull;
3078
        curList = nsnull;
3080
    }
3079
      }
3081
    
3080
    }
3081
3082
    // if curNode is a Break, delete it, and quit remembering prev list item
3082
    // if curNode is a Break, delete it, and quit remembering prev list item
3083
    if (nsTextEditUtils::IsBreak(curNode)) 
3083
    if (nsTextEditUtils::IsBreak(curNode)) {
3084
    {
3085
      res = mHTMLEditor->DeleteNode(curNode);
3084
      res = mHTMLEditor->DeleteNode(curNode);
3086
      NS_ENSURE_SUCCESS(res, res);
3085
      NS_ENSURE_SUCCESS(res, res);
3087
      prevListItem = 0;
3086
      prevListItem = 0;
3088
      continue;
3087
      continue;
3089
    }
3088
    } else if (IsEmptyInline(curNode)) {
3090
    // if curNode is an empty inline container, delete it
3089
      // if curNode is an empty inline container, delete it
3091
    else if (IsEmptyInline(curNode)) 
3092
    {
3093
      res = mHTMLEditor->DeleteNode(curNode);
3090
      res = mHTMLEditor->DeleteNode(curNode);
3094
      NS_ENSURE_SUCCESS(res, res);
3091
      NS_ENSURE_SUCCESS(res, res);
3095
      continue;
3092
      continue;
3096
    }
3093
    }
3097
    
3094
3098
    if (nsHTMLEditUtils::IsList(curNode))
3095
    if (nsHTMLEditUtils::IsList(curNode)) {
3099
    {
3100
      nsAutoString existingListStr;
3101
      res = mHTMLEditor->GetTagString(curNode, existingListStr);
3102
      ToLowerCase(existingListStr);
3103
      // do we have a curList already?
3096
      // do we have a curList already?
3104
      if (curList && !nsEditorUtils::IsDescendantOf(curNode, curList))
3097
      if (curList && !nsEditorUtils::IsDescendantOf(curNode, curList)) {
3105
      {
3098
        // move all of our children into curList.  cheezy way to do it: move
3106
        // move all of our children into curList.
3099
        // whole list and then RemoveContainer() on the list.  ConvertListType
3107
        // cheezy way to do it: move whole list and then
3100
        // first: that routine handles converting the list item types, if
3108
        // RemoveContainer() on the list.
3101
        // needed
3109
        // ConvertListType first: that routine
3110
        // handles converting the list item types, if needed
3111
        res = mHTMLEditor->MoveNode(curNode, curList, -1);
3102
        res = mHTMLEditor->MoveNode(curNode, curList, -1);
3112
        NS_ENSURE_SUCCESS(res, res);
3103
        NS_ENSURE_SUCCESS(res, res);
3113
        res = ConvertListType(curNode, address_of(newBlock), *aListType, itemType);
3104
        res = ConvertListType(curNode, address_of(newBlock),
3105
                              *aListType, itemType);
3114
        NS_ENSURE_SUCCESS(res, res);
3106
        NS_ENSURE_SUCCESS(res, res);
3115
        res = mHTMLEditor->RemoveBlockContainer(newBlock);
3107
        res = mHTMLEditor->RemoveBlockContainer(newBlock);
3116
        NS_ENSURE_SUCCESS(res, res);
3108
        NS_ENSURE_SUCCESS(res, res);
3117
      }
3109
      } else {
3118
      else
3119
      {
3120
        // replace list with new list type
3110
        // replace list with new list type
3121
        res = ConvertListType(curNode, address_of(newBlock), *aListType, itemType);
3111
        res = ConvertListType(curNode, address_of(newBlock),
3112
                              *aListType, itemType);
3122
        NS_ENSURE_SUCCESS(res, res);
3113
        NS_ENSURE_SUCCESS(res, res);
3123
        curList = newBlock;
3114
        curList = newBlock;
3124
      }
3115
      }
3125
      prevListItem = 0;
3116
      prevListItem = 0;
3126
      continue;
3117
      continue;
3127
    }
3118
    }
3128
3119
3129
    if (nsHTMLEditUtils::IsListItem(curNode))
3120
    if (nsHTMLEditUtils::IsListItem(curNode)) {
3130
    {
3121
      if (mHTMLEditor->GetTag(curParent) != listTypeAtom) {
3131
      nsAutoString existingListStr;
3122
        // list item is in wrong type of list. if we don't have a curList,
3132
      res = mHTMLEditor->GetTagString(curParent, existingListStr);
3123
        // split the old list and make a new list of correct type.
3133
      ToLowerCase(existingListStr);
3124
        if (!curList || nsEditorUtils::IsDescendantOf(curNode, curList)) {
3134
      if ( existingListStr != *aListType )
3125
          res = mHTMLEditor->SplitNode(curParent, offset,
3135
      {
3126
                                       getter_AddRefs(newBlock));
3136
        // list item is in wrong type of list.  
3137
        // if we don't have a curList, split the old list
3138
        // and make a new list of correct type.
3139
        if (!curList || nsEditorUtils::IsDescendantOf(curNode, curList))
3140
        {
3141
          res = mHTMLEditor->SplitNode(curParent, offset, getter_AddRefs(newBlock));
3142
          NS_ENSURE_SUCCESS(res, res);
3127
          NS_ENSURE_SUCCESS(res, res);
3143
          nsCOMPtr<nsIDOMNode> p;
3128
          nsCOMPtr<nsIDOMNode> parent;
3144
          PRInt32 o;
3129
          PRInt32 offset;
3145
          res = nsEditor::GetNodeLocation(curParent, address_of(p), &o);
3130
          res = nsEditor::GetNodeLocation(curParent, address_of(parent),
3131
                                          &offset);
3146
          NS_ENSURE_SUCCESS(res, res);
3132
          NS_ENSURE_SUCCESS(res, res);
3147
          res = mHTMLEditor->CreateNode(*aListType, p, o, getter_AddRefs(curList));
3133
          res = mHTMLEditor->CreateNode(*aListType, parent, offset,
3134
                                        getter_AddRefs(curList));
3148
          NS_ENSURE_SUCCESS(res, res);
3135
          NS_ENSURE_SUCCESS(res, res);
3149
        }
3136
        }
3150
        // move list item to new list
3137
        // move list item to new list
3151
        res = mHTMLEditor->MoveNode(curNode, curList, -1);
3138
        res = mHTMLEditor->MoveNode(curNode, curList, -1);
3152
        NS_ENSURE_SUCCESS(res, res);
3139
        NS_ENSURE_SUCCESS(res, res);
3153
        // convert list item type if needed
3140
        // convert list item type if needed
3154
        if (!mHTMLEditor->NodeIsTypeString(curNode,itemType))
3141
        if (!mHTMLEditor->NodeIsTypeString(curNode, itemType)) {
3155
        {
3142
          res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock),
3156
          res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), itemType);
3143
                                              itemType);
3157
          NS_ENSURE_SUCCESS(res, res);
3144
          NS_ENSURE_SUCCESS(res, res);
3158
        }
3145
        }
3159
      }
3146
      } else {
3160
      else
3161
      {
3162
        // item is in right type of list.  But we might still have to move it.
3147
        // item is in right type of list.  But we might still have to move it.
3163
        // and we might need to convert list item types.
3148
        // and we might need to convert list item types.
3164
        if (!curList)
3149
        if (!curList) {
3165
          curList = curParent;
3150
          curList = curParent;
3166
        else
3151
        } else {
3167
        {
3152
          if (curParent != curList) {
3168
          if (curParent != curList)
3169
          {
3170
            // move list item to new list
3153
            // move list item to new list
3171
            res = mHTMLEditor->MoveNode(curNode, curList, -1);
3154
            res = mHTMLEditor->MoveNode(curNode, curList, -1);
3172
            NS_ENSURE_SUCCESS(res, res);
3155
            NS_ENSURE_SUCCESS(res, res);
3173
          }
3156
          }
3174
        }
3157
        }
3175
        if (!mHTMLEditor->NodeIsTypeString(curNode,itemType))
3158
        if (!mHTMLEditor->NodeIsTypeString(curNode, itemType)) {
3176
        {
3159
          res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock),
3177
          res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), itemType);
3160
                                              itemType);
3178
          NS_ENSURE_SUCCESS(res, res);
3161
          NS_ENSURE_SUCCESS(res, res);
3179
        }
3162
        }
3180
      }
3163
      }
3181
      nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode);
3164
      nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode);
3182
      NS_NAMED_LITERAL_STRING(typestr, "type");
3165
      NS_NAMED_LITERAL_STRING(typestr, "type");
3183
      if (aBulletType && !aBulletType->IsEmpty()) {
3166
      if (aBulletType && !aBulletType->IsEmpty()) {
3184
        res = mHTMLEditor->SetAttribute(curElement, typestr, *aBulletType);
3167
        res = mHTMLEditor->SetAttribute(curElement, typestr, *aBulletType);
3185
      }
3168
      } else {
3186
      else {
3187
        res = mHTMLEditor->RemoveAttribute(curElement, typestr);
3169
        res = mHTMLEditor->RemoveAttribute(curElement, typestr);
3188
      }
3170
      }
3189
      NS_ENSURE_SUCCESS(res, res);
3171
      NS_ENSURE_SUCCESS(res, res);
3190
      continue;
3172
      continue;
3191
    }
3173
    }
3192
    
3174
3193
    // if we hit a div clear our prevListItem, insert divs contents
3175
    // if we hit a div clear our prevListItem, insert divs contents
3194
    // into our node array, and remove the div
3176
    // into our node array, and remove the div
3195
    if (nsHTMLEditUtils::IsDiv(curNode))
3177
    if (nsHTMLEditUtils::IsDiv(curNode)) {
3196
    {
3197
      prevListItem = nsnull;
3178
      prevListItem = nsnull;
3198
      PRInt32 j=i+1;
3179
      PRInt32 j = i + 1;
3199
      res = GetInnerContent(curNode, arrayOfNodes, &j);
3180
      res = GetInnerContent(curNode, arrayOfNodes, &j);
3200
      NS_ENSURE_SUCCESS(res, res);
3181
      NS_ENSURE_SUCCESS(res, res);
3201
      res = mHTMLEditor->RemoveContainer(curNode);
3182
      res = mHTMLEditor->RemoveContainer(curNode);
3202
      NS_ENSURE_SUCCESS(res, res);
3183
      NS_ENSURE_SUCCESS(res, res);
3203
      listCount = arrayOfNodes.Count();
3184
      listCount = arrayOfNodes.Count();
3204
      continue;
3185
      continue;
3205
    }
3186
    }
3206
      
3187
3207
    // need to make a list to put things in if we haven't already,
3188
    // need to make a list to put things in if we haven't already,
3208
    if (!curList)
3189
    if (!curList) {
3209
    {
3210
      res = SplitAsNeeded(aListType, address_of(curParent), &offset);
3190
      res = SplitAsNeeded(aListType, address_of(curParent), &offset);
3211
      NS_ENSURE_SUCCESS(res, res);
3191
      NS_ENSURE_SUCCESS(res, res);
3212
      res = mHTMLEditor->CreateNode(*aListType, curParent, offset, getter_AddRefs(curList));
3192
      res = mHTMLEditor->CreateNode(*aListType, curParent, offset,
3193
                                    getter_AddRefs(curList));
3213
      NS_ENSURE_SUCCESS(res, res);
3194
      NS_ENSURE_SUCCESS(res, res);
3214
      // remember our new block for postprocessing
3195
      // remember our new block for postprocessing
3215
      mNewBlock = curList;
3196
      mNewBlock = curList;
3216
      // curList is now the correct thing to put curNode in
3197
      // curList is now the correct thing to put curNode in
3217
      prevListItem = 0;
3198
      prevListItem = 0;
3218
    }
3199
    }
3219
  
3200
3220
    // if curNode isn't a list item, we must wrap it in one
3201
    // if curNode isn't a list item, we must wrap it in one
3221
    nsCOMPtr<nsIDOMNode> listItem;
3202
    nsCOMPtr<nsIDOMNode> listItem;
3222
    if (!nsHTMLEditUtils::IsListItem(curNode))
3203
    if (!nsHTMLEditUtils::IsListItem(curNode)) {
3223
    {
3204
      if (IsInlineNode(curNode) && prevListItem) {
3224
      if (IsInlineNode(curNode) && prevListItem)
3225
      {
3226
        // this is a continuation of some inline nodes that belong together in
3205
        // this is a continuation of some inline nodes that belong together in
3227
        // the same list item.  use prevListItem
3206
        // the same list item.  use prevListItem
3228
        res = mHTMLEditor->MoveNode(curNode, prevListItem, -1);
3207
        res = mHTMLEditor->MoveNode(curNode, prevListItem, -1);
3229
        NS_ENSURE_SUCCESS(res, res);
3208
        NS_ENSURE_SUCCESS(res, res);
3230
      }
3209
      } else {
3231
      else
3232
      {
3233
        // don't wrap li around a paragraph.  instead replace paragraph with li
3210
        // don't wrap li around a paragraph.  instead replace paragraph with li
3234
        if (nsHTMLEditUtils::IsParagraph(curNode))
3211
        if (nsHTMLEditUtils::IsParagraph(curNode)) {
3235
        {
3212
          res = mHTMLEditor->ReplaceContainer(curNode, address_of(listItem),
3236
          res = mHTMLEditor->ReplaceContainer(curNode, address_of(listItem), itemType);
3213
                                              itemType);
3237
        }
3214
        } else {
3238
        else
3215
          res = mHTMLEditor->InsertContainerAbove(curNode,
3239
        {
3216
                                                  address_of(listItem),
3240
          res = mHTMLEditor->InsertContainerAbove(curNode, address_of(listItem), itemType);
3217
                                                  itemType);
3241
        }
3218
        }
3242
        NS_ENSURE_SUCCESS(res, res);
3219
        NS_ENSURE_SUCCESS(res, res);
3243
        if (IsInlineNode(curNode)) 
3220
        if (IsInlineNode(curNode)) {
3244
          prevListItem = listItem;
3221
          prevListItem = listItem;
3245
        else
3222
        } else {
3246
          prevListItem = nsnull;
3223
          prevListItem = nsnull;
3247
      }
3224
        }
3248
    }
3225
      }
3249
    else
3226
    } else {
3250
    {
3251
      listItem = curNode;
3227
      listItem = curNode;
3252
    }
3228
    }
3253
  
3229
3254
    if (listItem)  // if we made a new list item, deal with it
3230
    if (listItem) {
3255
    {
3231
      // if we made a new list item, deal with it: tuck the listItem into the
3256
      // tuck the listItem into the end of the active list
3232
      // end of the active list
3257
      res = mHTMLEditor->MoveNode(listItem, curList, -1);
3233
      res = mHTMLEditor->MoveNode(listItem, curList, -1);
3258
      NS_ENSURE_SUCCESS(res, res);
3234
      NS_ENSURE_SUCCESS(res, res);
3259
    }
3235
    }
3260
  }
3236
  }
3261
3237
3262
  return res;
3238
  return res;
3263
}
3239
}
3264
3240
 Lines 4359-4558   nsHTMLEditRules::ConvertListType(nsIDOMN Link Here 
4359
  }
4335
  }
4360
  return res;
4336
  return res;
4361
}
4337
}
4362
4338
4363
4339
4364
///////////////////////////////////////////////////////////////////////////
4340
///////////////////////////////////////////////////////////////////////////
4365
// CreateStyleForInsertText:  take care of clearing and setting appropriate
4341
// CreateStyleForInsertText:  take care of clearing and setting appropriate
4366
//                            style nodes for text insertion.
4342
//                            style nodes for text insertion.
4367
//                
4343
//
4368
//                  
4344
//
4369
nsresult 
4345
nsresult
4370
nsHTMLEditRules::CreateStyleForInsertText(nsISelection *aSelection, nsIDOMDocument *aDoc) 
4346
nsHTMLEditRules::CreateStyleForInsertText(nsISelection *aSelection,
4371
{
4347
                                          nsIDOMDocument *aDoc)
4372
  NS_ENSURE_TRUE(aSelection && aDoc, NS_ERROR_NULL_POINTER);
4348
{
4373
  NS_ENSURE_TRUE(mHTMLEditor->mTypeInState, NS_ERROR_NULL_POINTER);
4349
  MOZ_ASSERT(aSelection && aDoc && mHTMLEditor->mTypeInState);
4374
  
4350
4375
  bool weDidSometing = false;
4351
  bool weDidSomething = false;
4376
  nsCOMPtr<nsIDOMNode> node, tmp;
4352
  nsCOMPtr<nsIDOMNode> node, tmp;
4377
  PRInt32 offset;
4353
  PRInt32 offset;
4378
  nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(node), &offset);
4354
  nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection,
4379
  NS_ENSURE_SUCCESS(res, res);
4355
                                                    getter_AddRefs(node),
4380
  
4356
                                                    &offset);
4357
  NS_ENSURE_SUCCESS(res, res);
4358
4381
  // if we deleted selection then also for cached styles
4359
  // if we deleted selection then also for cached styles
4382
  if (mDidDeleteSelection && 
4360
  if (mDidDeleteSelection &&
4383
      ((mTheAction == nsEditor::kOpInsertText ) ||
4361
      (mTheAction == nsEditor::kOpInsertText ||
4384
       (mTheAction == nsEditor::kOpInsertIMEText) ||
4362
       mTheAction == nsEditor::kOpInsertIMEText ||
4385
       (mTheAction == nsEditor::kOpInsertBreak) ||
4363
       mTheAction == nsEditor::kOpInsertBreak ||
4386
       (mTheAction == nsEditor::kOpDeleteSelection)))
4364
       mTheAction == nsEditor::kOpDeleteSelection)) {
4387
  {
4388
    res = ReapplyCachedStyles();
4365
    res = ReapplyCachedStyles();
4389
    NS_ENSURE_SUCCESS(res, res);
4366
    NS_ENSURE_SUCCESS(res, res);
4390
  }
4367
  }
4391
  // either way we clear the cached styles array
4368
  // either way we clear the cached styles array
4392
  res = ClearCachedStyles();  
4369
  res = ClearCachedStyles();
4393
  NS_ENSURE_SUCCESS(res, res);
4370
  NS_ENSURE_SUCCESS(res, res);
4394
4371
4395
  // next examine our present style and make sure default styles are either present or
4372
  // next examine our present style and make sure default styles are either
4396
  // explicitly overridden.  If neither, add the default style to the TypeInState
4373
  // present or explicitly overridden.  If neither, add the default style to
4397
  PRInt32 j, defcon = mHTMLEditor->mDefaultStyles.Length();
4374
  // the TypeInState
4398
  for (j=0; j<defcon; j++)
4375
  PRInt32 length = mHTMLEditor->mDefaultStyles.Length();
4399
  {
4376
  for (PRInt32 j = 0; j < length; j++) {
4400
    PropItem *propItem = mHTMLEditor->mDefaultStyles[j];
4377
    PropItem* propItem = mHTMLEditor->mDefaultStyles[j];
4401
    NS_ENSURE_TRUE(propItem, NS_ERROR_NULL_POINTER);
4378
    MOZ_ASSERT(propItem);
4402
    bool bFirst, bAny, bAll;
4379
    bool bFirst, bAny, bAll;
4403
4380
4404
    // GetInlineProperty also examine TypeInState.  The only gotcha here is that a cleared
4381
    // GetInlineProperty also examine TypeInState.  The only gotcha here is
4405
    // property looks like an unset property.  For now I'm assuming that's not a problem:
4382
    // that a cleared property looks like an unset property.  For now I'm
4406
    // that default styles will always be multivalue styles (like font face or size) where
4383
    // assuming that's not a problem: that default styles will always be
4407
    // clearing the style means we want to go back to the default.  If we ever wanted a 
4384
    // multivalue styles (like font face or size) where clearing the style
4408
    // "toggle" style like bold for a default, though, I'll have to add code to detect the
4385
    // means we want to go back to the default.  If we ever wanted a "toggle"
4409
    // difference between unset and explicitly cleared, else user would never be able to
4386
    // style like bold for a default, though, I'll have to add code to detect
4410
    // unbold, for instance.
4387
    // the difference between unset and explicitly cleared, else user would
4388
    // never be able to unbold, for instance.
4411
    nsAutoString curValue;
4389
    nsAutoString curValue;
4412
    res = mHTMLEditor->GetInlinePropertyBase(propItem->tag, &(propItem->attr), nsnull, 
4390
    res = mHTMLEditor->GetInlinePropertyBase(propItem->tag, &propItem->attr,
4413
                                             &bFirst, &bAny, &bAll, &curValue, false);
4391
                                             nsnull, &bFirst, &bAny, &bAll,
4414
    NS_ENSURE_SUCCESS(res, res);
4392
                                             &curValue, false);
4415
    
4393
    NS_ENSURE_SUCCESS(res, res);
4416
    if (!bAny)  // no style set for this prop/attr
4394
4417
    {
4395
    if (!bAny) {
4418
      mHTMLEditor->mTypeInState->SetProp(propItem->tag, propItem->attr, propItem->value);
4396
      // no style set for this prop/attr
4419
    }
4397
      mHTMLEditor->mTypeInState->SetProp(propItem->tag, propItem->attr,
4420
  }
4398
                                         propItem->value);
4421
  
4399
    }
4400
  }
4401
4422
  nsCOMPtr<nsIDOMElement> rootElement;
4402
  nsCOMPtr<nsIDOMElement> rootElement;
4423
  res = aDoc->GetDocumentElement(getter_AddRefs(rootElement));
4403
  res = aDoc->GetDocumentElement(getter_AddRefs(rootElement));
4424
  NS_ENSURE_SUCCESS(res, res);
4404
  NS_ENSURE_SUCCESS(res, res);
4425
4405
4426
  // process clearing any styles first
4406
  // process clearing any styles first
4427
  nsAutoPtr<PropItem> item(mHTMLEditor->mTypeInState->TakeClearProperty());
4407
  nsAutoPtr<PropItem> item(mHTMLEditor->mTypeInState->TakeClearProperty());
4428
  while (item && node != rootElement)
4408
  while (item && node != rootElement) {
4429
  {
4409
    nsCOMPtr<nsIDOMNode> leftNode, rightNode;
4430
    nsCOMPtr<nsIDOMNode> leftNode, rightNode, secondSplitParent, newSelParent, savedBR;
4410
    res = mHTMLEditor->SplitStyleAbovePoint(address_of(node), &offset,
4431
    res = mHTMLEditor->SplitStyleAbovePoint(address_of(node), &offset, item->tag, &item->attr, address_of(leftNode), address_of(rightNode));
4411
                                            item->tag, &item->attr,
4412
                                            address_of(leftNode),
4413
                                            address_of(rightNode));
4432
    NS_ENSURE_SUCCESS(res, res);
4414
    NS_ENSURE_SUCCESS(res, res);
4433
    bool bIsEmptyNode;
4415
    bool bIsEmptyNode;
4434
    if (leftNode)
4416
    if (leftNode) {
4435
    {
4436
      mHTMLEditor->IsEmptyNode(leftNode, &bIsEmptyNode, false, true);
4417
      mHTMLEditor->IsEmptyNode(leftNode, &bIsEmptyNode, false, true);
4437
      if (bIsEmptyNode)
4418
      if (bIsEmptyNode) {
4438
      {
4439
        // delete leftNode if it became empty
4419
        // delete leftNode if it became empty
4440
        res = mEditor->DeleteNode(leftNode);
4420
        res = mEditor->DeleteNode(leftNode);
4441
        NS_ENSURE_SUCCESS(res, res);
4421
        NS_ENSURE_SUCCESS(res, res);
4442
      }
4422
      }
4443
    }
4423
    }
4444
    if (rightNode)
4424
    if (rightNode) {
4445
    {
4425
      nsCOMPtr<nsIDOMNode> secondSplitParent =
4446
      secondSplitParent = mHTMLEditor->GetLeftmostChild(rightNode);
4426
        mHTMLEditor->GetLeftmostChild(rightNode);
4447
      // don't try to split non-containers (br's, images, hr's, etc)
4427
      // don't try to split non-containers (br's, images, hr's, etc)
4448
      if (!secondSplitParent) secondSplitParent = rightNode;
4428
      if (!secondSplitParent) {
4449
      if (!mHTMLEditor->IsContainer(secondSplitParent))
4429
        secondSplitParent = rightNode;
4450
      {
4430
      }
4451
        if (nsTextEditUtils::IsBreak(secondSplitParent))
4431
      nsCOMPtr<nsIDOMNode> savedBR;
4432
      if (!mHTMLEditor->IsContainer(secondSplitParent)) {
4433
        if (nsTextEditUtils::IsBreak(secondSplitParent)) {
4452
          savedBR = secondSplitParent;
4434
          savedBR = secondSplitParent;
4435
        }
4453
4436
4454
        secondSplitParent->GetParentNode(getter_AddRefs(tmp));
4437
        secondSplitParent->GetParentNode(getter_AddRefs(tmp));
4455
        secondSplitParent = tmp;
4438
        secondSplitParent = tmp;
4456
      }
4439
      }
4457
      offset = 0;
4440
      offset = 0;
4458
      res = mHTMLEditor->SplitStyleAbovePoint(address_of(secondSplitParent), &offset, item->tag, &(item->attr), address_of(leftNode), address_of(rightNode));
4441
      res = mHTMLEditor->SplitStyleAbovePoint(address_of(secondSplitParent),
4442
                                              &offset, item->tag,
4443
                                              &item->attr,
4444
                                              address_of(leftNode),
4445
                                              address_of(rightNode));
4459
      NS_ENSURE_SUCCESS(res, res);
4446
      NS_ENSURE_SUCCESS(res, res);
4460
      // should be impossible to not get a new leftnode here
4447
      // should be impossible to not get a new leftnode here
4461
      NS_ENSURE_TRUE(leftNode, NS_ERROR_FAILURE);
4448
      NS_ENSURE_TRUE(leftNode, NS_ERROR_FAILURE);
4462
      newSelParent = mHTMLEditor->GetLeftmostChild(leftNode);
4449
      nsCOMPtr<nsIDOMNode> newSelParent =
4463
      if (!newSelParent) newSelParent = leftNode;
4450
        mHTMLEditor->GetLeftmostChild(leftNode);
4464
      // if rightNode starts with a br, suck it out of right node and into leftNode.
4451
      if (!newSelParent) {
4465
      // This is so we you don't revert back to the previous style if you happen to click at the end of a line.
4452
        newSelParent = leftNode;
4466
      if (savedBR)
4453
      }
4467
      {
4454
      // If rightNode starts with a br, suck it out of right node and into
4455
      // leftNode.  This is so we you don't revert back to the previous style
4456
      // if you happen to click at the end of a line.
4457
      if (savedBR) {
4468
        res = mEditor->MoveNode(savedBR, newSelParent, 0);
4458
        res = mEditor->MoveNode(savedBR, newSelParent, 0);
4469
        NS_ENSURE_SUCCESS(res, res);
4459
        NS_ENSURE_SUCCESS(res, res);
4470
      }
4460
      }
4471
      mHTMLEditor->IsEmptyNode(rightNode, &bIsEmptyNode, false, true);
4461
      mHTMLEditor->IsEmptyNode(rightNode, &bIsEmptyNode, false, true);
4472
      if (bIsEmptyNode)
4462
      if (bIsEmptyNode) {
4473
      {
4474
        // delete rightNode if it became empty
4463
        // delete rightNode if it became empty
4475
        res = mEditor->DeleteNode(rightNode);
4464
        res = mEditor->DeleteNode(rightNode);
4476
        NS_ENSURE_SUCCESS(res, res);
4465
        NS_ENSURE_SUCCESS(res, res);
4477
      }
4466
      }
4478
      // remove the style on this new hierarchy
4467
      // remove the style on this new hierarchy
4479
      PRInt32 newSelOffset = 0;
4468
      PRInt32 newSelOffset = 0;
4480
      {
4469
      {
4481
        // track the point at the new hierarchy.
4470
        // Track the point at the new hierarchy.  This is so we can know where
4482
        // This is so we can know where to put the selection after we call
4471
        // to put the selection after we call RemoveStyleInside().
4483
        // RemoveStyleInside().  RemoveStyleInside() could remove any and all of those nodes,
4472
        // RemoveStyleInside() could remove any and all of those nodes, so I
4484
        // so I have to use the range tracking system to find the right spot to put selection.
4473
        // have to use the range tracking system to find the right spot to put
4485
        nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(newSelParent), &newSelOffset);
4474
        // selection.
4486
        res = mHTMLEditor->RemoveStyleInside(leftNode, item->tag, &(item->attr));
4475
        nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
4476
                                    address_of(newSelParent), &newSelOffset);
4477
        res = mHTMLEditor->RemoveStyleInside(leftNode, item->tag,
4478
                                             &(item->attr));
4487
        NS_ENSURE_SUCCESS(res, res);
4479
        NS_ENSURE_SUCCESS(res, res);
4488
      }
4480
      }
4489
      // reset our node offset values to the resulting new sel point
4481
      // reset our node offset values to the resulting new sel point
4490
      node = newSelParent;
4482
      node = newSelParent;
4491
      offset = newSelOffset;
4483
      offset = newSelOffset;
4492
    }
4484
    }
4493
    item = mHTMLEditor->mTypeInState->TakeClearProperty();
4485
    item = mHTMLEditor->mTypeInState->TakeClearProperty();
4494
    weDidSometing = true;
4486
    weDidSomething = true;
4495
  }
4487
  }
4496
  
4488
4497
  // then process setting any styles
4489
  // then process setting any styles
4498
  PRInt32 relFontSize = mHTMLEditor->mTypeInState->TakeRelativeFontSize();
4490
  PRInt32 relFontSize = mHTMLEditor->mTypeInState->TakeRelativeFontSize();
4499
  item = mHTMLEditor->mTypeInState->TakeSetProperty();
4491
  item = mHTMLEditor->mTypeInState->TakeSetProperty();
4500
  
4492
4501
  if (item || relFontSize) // we have at least one style to add; make a
4493
  if (item || relFontSize) {
4502
  {                        // new text node to insert style nodes above.
4494
    // we have at least one style to add; make a new text node to insert style
4503
    if (mHTMLEditor->IsTextNode(node))
4495
    // nodes above.
4504
    {
4496
    if (mHTMLEditor->IsTextNode(node)) {
4505
      // if we are in a text node, split it
4497
      // if we are in a text node, split it
4506
      res = mHTMLEditor->SplitNodeDeep(node, node, offset, &offset);
4498
      res = mHTMLEditor->SplitNodeDeep(node, node, offset, &offset);
4507
      NS_ENSURE_SUCCESS(res, res);
4499
      NS_ENSURE_SUCCESS(res, res);
4508
      node->GetParentNode(getter_AddRefs(tmp));
4500
      node->GetParentNode(getter_AddRefs(tmp));
4509
      node = tmp;
4501
      node = tmp;
4510
    }
4502
    }
4511
    if (!mHTMLEditor->IsContainer(node))
4503
    if (!mHTMLEditor->IsContainer(node)) {
4512
    {
4513
      return NS_OK;
4504
      return NS_OK;
4514
    }
4505
    }
4515
    nsCOMPtr<nsIDOMNode> newNode;
4506
    nsCOMPtr<nsIDOMNode> newNode;
4516
    nsCOMPtr<nsIDOMText> nodeAsText;
4507
    nsCOMPtr<nsIDOMText> nodeAsText;
4517
    res = aDoc->CreateTextNode(EmptyString(), getter_AddRefs(nodeAsText));
4508
    res = aDoc->CreateTextNode(EmptyString(), getter_AddRefs(nodeAsText));
4518
    NS_ENSURE_SUCCESS(res, res);
4509
    NS_ENSURE_SUCCESS(res, res);
4519
    NS_ENSURE_TRUE(nodeAsText, NS_ERROR_NULL_POINTER);
4510
    NS_ENSURE_TRUE(nodeAsText, NS_ERROR_NULL_POINTER);
4520
    newNode = do_QueryInterface(nodeAsText);
4511
    newNode = do_QueryInterface(nodeAsText);
4521
    res = mHTMLEditor->InsertNode(newNode, node, offset);
4512
    res = mHTMLEditor->InsertNode(newNode, node, offset);
4522
    NS_ENSURE_SUCCESS(res, res);
4513
    NS_ENSURE_SUCCESS(res, res);
4523
    node = newNode;
4514
    node = newNode;
4524
    offset = 0;
4515
    offset = 0;
4525
    weDidSometing = true;
4516
    weDidSomething = true;
4526
4517
4527
    if (relFontSize)
4518
    if (relFontSize) {
4528
    {
4529
      PRInt32 j, dir;
4530
      // dir indicated bigger versus smaller.  1 = bigger, -1 = smaller
4519
      // dir indicated bigger versus smaller.  1 = bigger, -1 = smaller
4531
      if (relFontSize > 0) dir=1;
4520
      PRInt32 dir = relFontSize > 0 ? 1 : -1;
4532
      else dir = -1;
4521
      for (PRInt32 j = 0; j < abs(relFontSize); j++) {
4533
      for (j=0; j<abs(relFontSize); j++)
4522
        res = mHTMLEditor->RelativeFontChangeOnTextNode(dir, nodeAsText,
4534
      {
4523
                                                        0, -1);
4535
        res = mHTMLEditor->RelativeFontChangeOnTextNode(dir, nodeAsText, 0, -1);
4536
        NS_ENSURE_SUCCESS(res, res);
4524
        NS_ENSURE_SUCCESS(res, res);
4537
      }
4525
      }
4538
    }
4526
    }
4539
    
4527
4540
    while (item)
4528
    while (item) {
4541
    {
4529
      res = mHTMLEditor->SetInlinePropertyOnNode(node, item->tag, &item->attr,
4542
      res = mHTMLEditor->SetInlinePropertyOnNode(node, item->tag, &item->attr, &item->value);
4530
                                                 &item->value);
4543
      NS_ENSURE_SUCCESS(res, res);
4531
      NS_ENSURE_SUCCESS(res, res);
4544
      item = mHTMLEditor->mTypeInState->TakeSetProperty();
4532
      item = mHTMLEditor->mTypeInState->TakeSetProperty();
4545
    }
4533
    }
4546
  }
4534
  }
4547
  if (weDidSometing)
4535
  if (weDidSomething) {
4548
    return aSelection->Collapse(node, offset);
4536
    return aSelection->Collapse(node, offset);
4549
    
4537
  }
4550
  return res;
4538
4539
  return NS_OK;
4551
}
4540
}
4552
4541
4553
4542
4554
///////////////////////////////////////////////////////////////////////////
4543
///////////////////////////////////////////////////////////////////////////
4555
// IsEmptyBlock: figure out if aNode is (or is inside) an empty block.
4544
// IsEmptyBlock: figure out if aNode is (or is inside) an empty block.
4556
//               A block can have children and still be considered empty,
4545
//               A block can have children and still be considered empty,
4557
//               if the children are empty or non-editable.
4546
//               if the children are empty or non-editable.
4558
//                  
4547
//                  

Return to bug 590640