PageRenderTime 42ms CodeModel.GetById 11ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 1ms

/security/manager/pki/src/nsASN1Tree.cpp

http://github.com/zpao/v8monkey
C++ | 617 lines | 424 code | 93 blank | 100 comment | 51 complexity | fd99134799e7f69aa577191818e5bba8 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is the Netscape security libraries.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Netscape Communications Corporation.
 18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 19 * the Initial Developer. All Rights Reserved.
 20 *
 21 * Contributor(s):
 22 *   Javier Delgadillo <javi@netscape.com>
 23 *
 24 * Alternatively, the contents of this file may be used under the terms of
 25 * either the GNU General Public License Version 2 or later (the "GPL"), or
 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 27 * in which case the provisions of the GPL or the LGPL are applicable instead
 28 * of those above. If you wish to allow use of your version of this file only
 29 * under the terms of either the GPL or the LGPL, and not to allow others to
 30 * use your version of this file under the terms of the MPL, indicate your
 31 * decision by deleting the provisions above and replace them with the notice
 32 * and other provisions required by the GPL or the LGPL. If you do not delete
 33 * the provisions above, a recipient may use your version of this file under
 34 * the terms of any one of the MPL, the GPL or the LGPL.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37#include "nsASN1Tree.h"
 38#include "nsIComponentManager.h"
 39#include "nsString.h"
 40#include "nsCRT.h"
 41#include "nsIMutableArray.h"
 42#include "nsArrayUtils.h"
 43
 44NS_IMPL_THREADSAFE_ISUPPORTS2(nsNSSASN1Tree, nsIASN1Tree, 
 45                                                 nsITreeView)
 46
 47nsNSSASN1Tree::nsNSSASN1Tree() 
 48:mTopNode(nsnull)
 49{
 50}
 51
 52nsNSSASN1Tree::~nsNSSASN1Tree()
 53{
 54  ClearNodes();
 55}
 56
 57void nsNSSASN1Tree::ClearNodesRecursively(myNode *n)
 58{
 59  myNode *walk = n;
 60  while (walk) {
 61    myNode *kill = walk;
 62
 63    if (walk->child) {
 64      ClearNodesRecursively(walk->child);
 65    }
 66    
 67    walk = walk->next;
 68    delete kill;
 69  }
 70}
 71
 72void nsNSSASN1Tree::ClearNodes()
 73{
 74  ClearNodesRecursively(mTopNode);
 75  mTopNode = nsnull;
 76}
 77
 78void nsNSSASN1Tree::InitChildsRecursively(myNode *n)
 79{
 80  if (!n->obj)
 81    return;
 82
 83  n->seq = do_QueryInterface(n->obj);
 84  if (!n->seq)
 85    return;
 86
 87  // If the object is a sequence, there might still be a reason
 88  // why it should not be displayed as a container.
 89  // If we decide that it has all the properties to justify
 90  // displaying as a container, we will create a new child chain.
 91  // If we decide, it does not make sense to display as a container,
 92  // we forget that it is a sequence by erasing n->seq.
 93  // That way, n->seq and n->child will be either both set or both null.
 94
 95  bool isContainer;
 96  n->seq->GetIsValidContainer(&isContainer);
 97  if (!isContainer) {
 98    n->seq = nsnull;
 99    return;
100  }
101
102  nsCOMPtr<nsIMutableArray> asn1Objects;
103  n->seq->GetASN1Objects(getter_AddRefs(asn1Objects));
104  PRUint32 numObjects;
105  asn1Objects->GetLength(&numObjects);
106  
107  if (!numObjects) {
108    n->seq = nsnull;
109    return;
110  }
111  
112  myNode *walk = nsnull;
113  myNode *prev = nsnull;
114  
115  PRUint32 i;
116  nsCOMPtr<nsISupports> isupports;
117  for (i=0; i<numObjects; i++) {
118    if (0 == i) {
119      n->child = walk = new myNode;
120    }
121    else {
122      walk = new myNode;
123    }
124
125    walk->parent = n;
126    if (prev) {
127      prev->next = walk;
128    }
129  
130    walk->obj = do_QueryElementAt(asn1Objects, i);
131
132    InitChildsRecursively(walk);
133
134    prev = walk;
135  }
136}
137
138void nsNSSASN1Tree::InitNodes()
139{
140  ClearNodes();
141
142  mTopNode = new myNode;
143  mTopNode->obj = mASN1Object;
144
145  InitChildsRecursively(mTopNode);
146}
147
148/* void loadASN1Structure (in nsIASN1Object asn1Object); */
149NS_IMETHODIMP 
150nsNSSASN1Tree::LoadASN1Structure(nsIASN1Object *asn1Object)
151{
152  //
153  // The tree won't automatically re-draw if the contents
154  // have been changed.  So I do a quick test here to let
155  // me know if I should forced the tree to redraw itself
156  // by calling RowCountChanged on it.
157  //
158  bool redraw = (mASN1Object && mTree);
159  PRInt32 rowsToDelete = 0;
160
161  if (redraw) {
162    // This is the number of rows we will be deleting after
163    // the contents have changed.
164    rowsToDelete = 0-CountVisibleNodes(mTopNode);
165  }
166
167  mASN1Object = asn1Object;
168  InitNodes();
169
170  if (redraw) {
171    // The number of rows in the new content.
172    PRInt32 newRows = CountVisibleNodes(mTopNode);
173    mTree->BeginUpdateBatch();
174    // Erase all of the old rows.
175    mTree->RowCountChanged(0, rowsToDelete);
176    // Replace them with the new contents
177    mTree->RowCountChanged(0, newRows);
178    mTree->EndUpdateBatch();
179  }
180
181  return NS_OK;
182}
183
184/* readonly attribute long rowCount; */
185NS_IMETHODIMP 
186nsNSSASN1Tree::GetRowCount(PRInt32 *aRowCount)
187{
188  if (mASN1Object) {
189    *aRowCount = CountVisibleNodes(mTopNode);
190  } else {
191    *aRowCount = 0;
192  }
193  return NS_OK;
194}
195
196/* attribute nsITreeSelection selection; */
197NS_IMETHODIMP 
198nsNSSASN1Tree::GetSelection(nsITreeSelection * *aSelection)
199{
200  *aSelection = mSelection;
201  NS_IF_ADDREF(*aSelection);
202  return NS_OK;
203}
204
205NS_IMETHODIMP 
206nsNSSASN1Tree::SetSelection(nsITreeSelection * aSelection)
207{
208  mSelection = aSelection;
209  return NS_OK;
210}
211
212/* void getRowProperties (in long index, in nsISupportsArray properties); */
213NS_IMETHODIMP 
214nsNSSASN1Tree::GetRowProperties(PRInt32 index, nsISupportsArray *properties)
215{
216  return NS_OK;
217}
218
219/* void getCellProperties (in long row, in nsITreeColumn col,
220                           in nsISupportsArray properties); */
221NS_IMETHODIMP 
222nsNSSASN1Tree::GetCellProperties(PRInt32 row, nsITreeColumn* col, 
223                                 nsISupportsArray *properties)
224{
225  return NS_OK;
226}
227
228/* void getColumnProperties (in nsITreeColumn col,
229                             in nsISupportsArray properties); */
230NS_IMETHODIMP 
231nsNSSASN1Tree::GetColumnProperties(nsITreeColumn* col, 
232                                   nsISupportsArray *properties)
233{
234  return NS_OK;
235}
236
237/* boolean isContainer (in long index); */
238NS_IMETHODIMP 
239nsNSSASN1Tree::IsContainer(PRInt32 index, bool *_retval)
240{
241  myNode *n = FindNodeFromIndex(index);
242  if (!n)
243    return NS_ERROR_FAILURE;
244
245  *_retval = (n->seq != nsnull);
246  return NS_OK; 
247}
248
249/* boolean isContainerOpen (in long index); */
250NS_IMETHODIMP 
251nsNSSASN1Tree::IsContainerOpen(PRInt32 index, bool *_retval)
252{
253  myNode *n = FindNodeFromIndex(index);
254  if (!n || !n->seq)
255    return NS_ERROR_FAILURE;
256
257  n->seq->GetIsExpanded(_retval);
258  return NS_OK;
259}
260
261/* boolean isContainerEmpty (in long index); */
262NS_IMETHODIMP 
263nsNSSASN1Tree::IsContainerEmpty(PRInt32 index, bool *_retval)
264{
265  *_retval = false;
266  return NS_OK;
267}
268
269/* boolean isSeparator (in long index); */
270NS_IMETHODIMP 
271nsNSSASN1Tree::IsSeparator(PRInt32 index, bool *_retval)
272{
273  *_retval = false;
274  return NS_OK; 
275}
276
277/* long getLevel (in long index); */
278NS_IMETHODIMP 
279nsNSSASN1Tree::GetLevel(PRInt32 index, PRInt32 *_retval)
280{
281  PRInt32 parentIndex;
282  PRInt32 nodeLevel;
283
284  myNode *n = FindNodeFromIndex(index, &parentIndex, &nodeLevel);
285  if (!n)
286    return NS_ERROR_FAILURE;
287
288  *_retval = nodeLevel;
289  return NS_OK; 
290}
291
292/* Astring getImageSrc (in long row, in nsITreeColumn col); */
293NS_IMETHODIMP 
294nsNSSASN1Tree::GetImageSrc(PRInt32 row, nsITreeColumn* col, 
295                           nsAString& _retval)
296{
297  return NS_OK;
298}
299
300/* long getProgressMode (in long row, in nsITreeColumn col); */
301NS_IMETHODIMP 
302nsNSSASN1Tree::GetProgressMode(PRInt32 row, nsITreeColumn* col, PRInt32* _retval)
303{
304  return NS_OK;
305}
306
307/* Astring getCellValue (in long row, in nsITreeColumn col); */
308NS_IMETHODIMP 
309nsNSSASN1Tree::GetCellValue(PRInt32 row, nsITreeColumn* col, 
310                            nsAString& _retval)
311{
312  return NS_OK;
313}
314
315/* Astring getCellText (in long row, in nsITreeColumn col); */
316NS_IMETHODIMP 
317nsNSSASN1Tree::GetCellText(PRInt32 row, nsITreeColumn* col, 
318                           nsAString& _retval)
319{
320  _retval.Truncate();
321
322  myNode* n = FindNodeFromIndex(row);
323  if (!n)
324    return NS_ERROR_FAILURE;
325
326  // There's only one column for ASN1 dump.
327  return n->obj->GetDisplayName(_retval);
328}
329
330/* wstring getDisplayData (in unsigned long index); */
331NS_IMETHODIMP 
332nsNSSASN1Tree::GetDisplayData(PRUint32 index, nsAString &_retval)
333{
334  myNode *n = FindNodeFromIndex(index);
335  if (!n)
336    return NS_ERROR_FAILURE;
337
338  n->obj->GetDisplayValue(_retval);
339  return NS_OK;
340}
341
342/* void setTree (in nsITreeBoxObject tree); */
343NS_IMETHODIMP 
344nsNSSASN1Tree::SetTree(nsITreeBoxObject *tree)
345{
346  mTree = tree;
347  return NS_OK;
348}
349
350/* void toggleOpenState (in long index); */
351NS_IMETHODIMP 
352nsNSSASN1Tree::ToggleOpenState(PRInt32 index)
353{
354  myNode *n = FindNodeFromIndex(index);
355  if (!n)
356    return NS_ERROR_FAILURE;
357
358  if (!n->seq)
359    return NS_ERROR_FAILURE;
360
361  bool IsExpanded;
362  n->seq->GetIsExpanded(&IsExpanded);
363  PRInt32 rowCountChange;
364  if (IsExpanded) {
365    rowCountChange = -CountVisibleNodes(n->child);
366    n->seq->SetIsExpanded(false);
367  } else {
368    n->seq->SetIsExpanded(true);
369    rowCountChange = CountVisibleNodes(n->child);
370  }
371  if (mTree)
372    mTree->RowCountChanged(index, rowCountChange);
373  return NS_OK;
374}
375
376/* void cycleHeader (in nsITreeColumn col); */
377NS_IMETHODIMP 
378nsNSSASN1Tree::CycleHeader(nsITreeColumn* col)
379{
380  return NS_OK;
381}
382
383/* void selectionChanged (); */
384NS_IMETHODIMP 
385nsNSSASN1Tree::SelectionChanged()
386{
387  return NS_ERROR_NOT_IMPLEMENTED;
388}
389
390/* void cycleCell (in long row, in nsITreeColumn col); */
391NS_IMETHODIMP 
392nsNSSASN1Tree::CycleCell(PRInt32 row, nsITreeColumn* col)
393{
394  return NS_OK;
395}
396
397/* boolean isEditable (in long row, in nsITreeColumn col); */
398NS_IMETHODIMP 
399nsNSSASN1Tree::IsEditable(PRInt32 row, nsITreeColumn* col, 
400                          bool *_retval)
401{
402  *_retval = false;
403  return NS_OK;
404}
405
406/* boolean isSelectable (in long row, in nsITreeColumn col); */
407NS_IMETHODIMP 
408nsNSSASN1Tree::IsSelectable(PRInt32 row, nsITreeColumn* col, 
409                            bool *_retval)
410{
411  *_retval = false;
412  return NS_OK;
413}
414
415/* void setCellValue (in long row, in nsITreeColumn col, in AString value); */
416NS_IMETHODIMP 
417nsNSSASN1Tree::SetCellValue(PRInt32 row, nsITreeColumn* col, 
418                            const nsAString& value)
419{
420  return NS_OK;
421}
422
423/* void setCellText (in long row, in nsITreeColumn col, in AString value); */
424NS_IMETHODIMP 
425nsNSSASN1Tree::SetCellText(PRInt32 row, nsITreeColumn* col, 
426                           const nsAString& value)
427{
428  return NS_OK;
429}
430
431/* void performAction (in wstring action); */
432NS_IMETHODIMP 
433nsNSSASN1Tree::PerformAction(const PRUnichar *action)
434{
435  return NS_OK;
436}
437
438/* void performActionOnRow (in wstring action, in long row); */
439NS_IMETHODIMP 
440nsNSSASN1Tree::PerformActionOnRow(const PRUnichar *action, PRInt32 row)
441{
442  return NS_OK;
443}
444
445/* void performActionOnCell (in wstring action, in long row, in nsITreeColumn col); */
446NS_IMETHODIMP 
447nsNSSASN1Tree::PerformActionOnCell(const PRUnichar *action, PRInt32 row, 
448                                   nsITreeColumn* col)
449{
450  return NS_OK;
451}
452
453//
454// CanDrop
455//
456NS_IMETHODIMP nsNSSASN1Tree::CanDrop(PRInt32 index, PRInt32 orientation,
457                                     nsIDOMDataTransfer* aDataTransfer, bool *_retval)
458{
459  NS_ENSURE_ARG_POINTER(_retval);
460  *_retval = false;
461  
462  return NS_OK;
463}
464
465
466//
467// Drop
468//
469NS_IMETHODIMP nsNSSASN1Tree::Drop(PRInt32 row, PRInt32 orient, nsIDOMDataTransfer* aDataTransfer)
470{
471  return NS_OK;
472}
473
474
475//
476// IsSorted
477//
478// ...
479//
480NS_IMETHODIMP nsNSSASN1Tree::IsSorted(bool *_retval)
481{
482  *_retval = false;
483  return NS_OK;
484}
485
486
487/* long getParentIndex (in long rowIndex); */
488NS_IMETHODIMP 
489nsNSSASN1Tree::GetParentIndex(PRInt32 rowIndex, PRInt32 *_retval)
490{
491  PRInt32 parentIndex = -1;
492
493  myNode *n = FindNodeFromIndex(rowIndex, &parentIndex);
494  if (!n)
495    return NS_ERROR_FAILURE;
496
497  *_retval = parentIndex;
498  return NS_OK; 
499}
500
501/* boolean hasNextSibling (in long rowIndex, in long afterIndex); */
502NS_IMETHODIMP 
503nsNSSASN1Tree::HasNextSibling(PRInt32 rowIndex, PRInt32 afterIndex, 
504                              bool *_retval)
505{
506  myNode *n = FindNodeFromIndex(rowIndex);
507  if (!n)
508    return NS_ERROR_FAILURE;
509
510  if (!n->next) {
511    *_retval = false;
512  }
513  else {
514    PRInt32 nTotalSize = CountVisibleNodes(n);
515    PRInt32 nLastChildPos = rowIndex + nTotalSize -1;
516    PRInt32 nextSiblingPos = nLastChildPos +1;
517    *_retval = (nextSiblingPos > afterIndex);
518  }
519
520  return NS_OK; 
521}
522
523PRInt32 nsNSSASN1Tree::CountVisibleNodes(myNode *n)
524{
525  if (!n)
526    return 0;
527
528  myNode *walk = n;
529  PRInt32 count = 0;
530  
531  while (walk) {
532    ++count;
533
534    if (walk->seq) {
535      bool IsExpanded;
536      walk->seq->GetIsExpanded(&IsExpanded);
537      if (IsExpanded) {
538        count += CountVisibleNodes(walk->child);
539      }
540    }
541
542    walk = walk->next;
543  }
544
545  return count;
546}
547
548// Entry point for find
549nsNSSASN1Tree::myNode *
550nsNSSASN1Tree::FindNodeFromIndex(PRInt32 wantedIndex, 
551                                 PRInt32 *optionalOutParentIndex, PRInt32 *optionalOutLevel)
552{
553  if (0 == wantedIndex) {
554    if (optionalOutLevel) {
555      *optionalOutLevel = 0;
556    }
557    if (optionalOutParentIndex) {
558      *optionalOutParentIndex = -1;
559    }
560    return mTopNode;
561  }
562  else {
563    PRInt32 index = 0;
564    PRInt32 level = 0;
565    return FindNodeFromIndex(mTopNode, wantedIndex, index, level, 
566                             optionalOutParentIndex, optionalOutLevel);
567  }
568}
569
570// Internal recursive helper function
571nsNSSASN1Tree::myNode *
572nsNSSASN1Tree::FindNodeFromIndex(myNode *n, PRInt32 wantedIndex,
573                                 PRInt32 &index_counter, PRInt32 &level_counter,
574                                 PRInt32 *optionalOutParentIndex, PRInt32 *optionalOutLevel)
575{
576  if (!n)
577    return nsnull;
578
579  myNode *walk = n;
580  PRInt32 parentIndex = index_counter-1;
581  
582  while (walk) {
583    if (index_counter == wantedIndex) {
584      if (optionalOutLevel) {
585        *optionalOutLevel = level_counter;
586      }
587      if (optionalOutParentIndex) {
588        *optionalOutParentIndex = parentIndex;
589      }
590      return walk;
591    }
592
593    if (walk->seq) {
594      bool IsExpanded;
595      walk->seq->GetIsExpanded(&IsExpanded);
596      if (IsExpanded) {
597        ++index_counter; // set to walk->child
598
599        ++level_counter;
600        myNode *found = FindNodeFromIndex(walk->child, wantedIndex, index_counter, level_counter,
601                                          optionalOutParentIndex, optionalOutLevel);
602        --level_counter;
603
604        if (found)
605          return found;
606      }
607    }
608
609    walk = walk->next;
610    if (walk) {
611      ++index_counter;
612    }
613  }
614
615  return nsnull;
616}
617