home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmisc / bkmutils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  23.0 KB  |  889 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "xp_mcom.h"
  20. #include "client.h"
  21. #include "hotlist.h"
  22.  
  23. static int32 hot_measure_Separator(HotlistStruct * item, int bLongFormat, int nIndent);
  24.  
  25.  
  26. #define TEXT_INDENT 3
  27. #define SEPATATOR_COUNT 20
  28. /*
  29.  * Measure a boring URL hotlist entry and return the length in bytes
  30.  *
  31.  * Short format:
  32.  *  "     item->address\n"
  33.  *    where there are nIndent number of spaces before the item
  34.  *
  35.  * Long format:
  36.  *  int16 type
  37.  *  item->name\n
  38.  *  item->address\n
  39.  *  int32 addition_date
  40.  *  int32 last_visit_date
  41.  *  item->description\0
  42.  *
  43.  * The item->description field is *NOT* \n terminated since it might
  44.  *  be a multi-line string and is therefore \0 terminated
  45.  */
  46. PRIVATE int32
  47. hot_measure_URL(HotlistStruct * item, int bLongFormat, int nIndent)
  48. {
  49.  
  50.     int32 iSpace = 0;
  51.  
  52.     if(!item)
  53.         return(0);
  54.  
  55.     if(bLongFormat) {
  56.  
  57.         /* type, addition_date, last_visit_date + 2 \n's + 1 \0 */
  58.         iSpace += 2 + 4 + 4 + 2 + 1;
  59.  
  60.         if(item->name)
  61.             iSpace += XP_STRLEN(item->name);
  62.         if(item->description)
  63.             iSpace += XP_STRLEN(item->description);
  64.  
  65.     } else {
  66.  
  67.         /* space indentation and '\n' terminator */
  68.         iSpace = 1 + nIndent;
  69.  
  70.     }
  71.  
  72.     /* the address appears in both formats */
  73.     if(item->address)
  74.         iSpace += XP_STRLEN(item->address);
  75.  
  76.     return(iSpace);
  77.  
  78. }
  79.  
  80. /*
  81.  * Measure a header entry and all its children
  82.  *
  83.  * Short format:
  84.  *  "     item->name\n"
  85.  *  "        child1->address\n"
  86.  *  "        child2->address\n"
  87.  *    where there are nIndent number of spaces before the item and
  88.  *    TEXT_INDENT spaces between levels
  89.  *
  90.  * Long format:
  91.  *  int16 type
  92.  *  item->name\n
  93.  *  int32 addition_date
  94.  *  int32 number of children
  95.  *  item->description\0
  96.  *
  97.  * The item->description field is *NOT* \n terminated since it might
  98.  *  be a multi-line string and is therefore \0 terminated.  Note that
  99.  *  the address field is *NOT* written for headers since its it meaningless
  100.  */
  101. PRIVATE int32
  102. hot_measure_Header(HotlistStruct * item, int bLongFormat, int nIndent)
  103. {
  104.  
  105.     XP_List * list;
  106.     int32 iSpace = 0;
  107.  
  108.     if(!item)
  109.         return(0);
  110.  
  111.     if(bLongFormat) {
  112.  
  113.         /* type, addition_date, last_visit_date + # children + 2 \n's + 1 \0 */
  114.         iSpace += 2 + 4 + 4 + 2 + 1;
  115.  
  116.         if(item->description)
  117.             iSpace += XP_STRLEN(item->description);
  118.  
  119.     } else {
  120.  
  121.         /* space indentation and '\n' terminator */
  122.         iSpace = 1 + nIndent;
  123.  
  124.     }
  125.  
  126.     /* the name appears in both formats */
  127.     if(item->name)
  128.         iSpace += XP_STRLEN(item->name);
  129.  
  130.  
  131.     /* if no children just return */
  132.     if(!item->children)
  133.         return(iSpace);
  134.  
  135.     /* measure the amount of space taken up by this item's children */
  136.     for(list = item->children->next; list; list = list->next) {
  137.         HotlistStruct * child = (HotlistStruct *) list->object;
  138.  
  139.         if(!child)
  140.             continue;
  141.  
  142.         switch(child->type) {
  143.         case HOT_URLType:
  144.             iSpace += hot_measure_URL(child, bLongFormat, nIndent + TEXT_INDENT);
  145.             break;
  146.         case HOT_HeaderType:
  147.             iSpace += hot_measure_Header(child, bLongFormat, nIndent + TEXT_INDENT); 
  148.             break;
  149.         case HOT_SeparatorType:
  150.             iSpace += hot_measure_Separator(child, bLongFormat, nIndent + TEXT_INDENT); 
  151.             break;
  152.         default:
  153.             break;
  154.         }
  155.  
  156.     }
  157.  
  158.     return(iSpace);
  159.  
  160. }
  161.  
  162.  
  163. /*
  164.  * Measure a separator entry and return the length in bytes
  165.  *
  166.  * Short format:
  167.  *  "     ---------------------\n"
  168.  *    where there are nIndent number of spaces before the item
  169.  *    and 20 dashes
  170.  *
  171.  * Long format:
  172.  *  int16 type
  173.  */
  174. PRIVATE int32
  175. hot_measure_Separator(HotlistStruct * item, int bLongFormat, int nIndent)
  176. {
  177.  
  178.     int32 iSpace = 0;
  179.  
  180.     if(!item)
  181.         return(0);
  182.  
  183.     if(bLongFormat) {
  184.  
  185.         /* type */
  186.         iSpace = 2;
  187.  
  188.     } else {
  189.  
  190.         /* space indentation and '\n' terminator */
  191.         iSpace = 1 + nIndent + 20;
  192.  
  193.     }
  194.  
  195.     return(iSpace);
  196.  
  197. }
  198.  
  199.  
  200. /*
  201.  * Write out a boring URL hotlist entry.  See comment at the top of
  202.  *   hot_measure_URL for the format used.  Assume we start writing at
  203.  *   the start of the buffer passed in.  Return a pointer to where the
  204.  *   buffer ends when we get done.
  205.  */
  206. PRIVATE char *
  207. hot_write_URL(char * buffer, HotlistStruct * item, int bLongFormat, int nIndent)
  208. {
  209.  
  210.     int iLen;
  211.     int32 lVal;
  212.     int32 sVal;
  213.  
  214.     if(!item || !buffer)
  215.         return(buffer);    
  216.  
  217.     if(bLongFormat) {                 
  218.  
  219.         /* copy the type */
  220.         sVal = (int16) item->type;
  221.         iLen = 2;
  222.         XP_MEMCPY(buffer, &sVal, iLen);
  223.         buffer += iLen;
  224.  
  225.         /* copy the name */
  226.         if(item->name) {
  227.             iLen = XP_STRLEN(item->name);
  228.             XP_MEMCPY(buffer, item->name, iLen);
  229.             buffer += iLen;
  230.         }
  231.  
  232.         /* put the \n terminator on */
  233.         *buffer++ = '\n';
  234.  
  235.         /* copy the address */
  236.         if(item->address) {
  237.             iLen = XP_STRLEN(item->address);
  238.             XP_MEMCPY(buffer, item->address, iLen);
  239.             buffer += iLen;
  240.         }
  241.  
  242.         /* put the \n terminator on */
  243.         *buffer++ = '\n';
  244.  
  245.         /* addition date */
  246.         lVal = (int32) item->addition_date;
  247.         iLen = 4;
  248.         XP_MEMCPY(buffer, &lVal, iLen);
  249.         buffer += iLen;
  250.  
  251.         /* last visit date */            
  252.         lVal = (int32) item->last_visit;
  253.         iLen = 4;
  254.         XP_MEMCPY(buffer, &lVal, iLen);
  255.         buffer += iLen;
  256.  
  257.         /* copy the description */
  258.         if(item->description) {
  259.             iLen = XP_STRLEN(item->description);
  260.             XP_MEMCPY(buffer, item->description, iLen);
  261.             buffer += iLen;
  262.         }
  263.  
  264.         /* put the \n terminator on */
  265.         *buffer++ = '\0';
  266.  
  267.     } else {
  268.  
  269.         XP_MEMSET(buffer, ' ', nIndent);
  270.         buffer += nIndent;
  271.  
  272.         if(item->address) {
  273.             XP_STRCPY(buffer, item->address);
  274.             buffer += XP_STRLEN(item->address);
  275.         }
  276.  
  277.         *buffer++ = '\n';
  278.  
  279.     }
  280.  
  281.     return(buffer);
  282.  
  283. }
  284.  
  285. /*
  286.  * Write out a separator entry.  See comment at the top of
  287.  *   hot_measure_Separator for the format used.  Assume we start writing at
  288.  *   the start of the buffer passed in.  Return a pointer to where the
  289.  *   buffer ends when we get done.
  290.  */
  291. PRIVATE char *
  292. hot_write_Separator(char * buffer, HotlistStruct * item, int bLongFormat, int nIndent)
  293. {
  294.  
  295.     int iLen;
  296. #if 0
  297.     int32 lVal;
  298. #endif
  299.     int32 sVal;
  300.  
  301.     if(!item || !buffer)
  302.         return(buffer);    
  303.  
  304.     if(bLongFormat) {                 
  305.  
  306.         /* copy the type */
  307.         sVal = (int16) item->type;
  308.         iLen = 2;
  309.         XP_MEMCPY(buffer, &sVal, iLen);
  310.         buffer += iLen;
  311.  
  312.     } else {
  313.  
  314.         XP_MEMSET(buffer, ' ', nIndent);
  315.         buffer += nIndent;
  316.  
  317.         XP_MEMSET(buffer, '-', SEPATATOR_COUNT);
  318.         buffer += SEPATATOR_COUNT;
  319.  
  320.         *buffer++ = '\n';
  321.  
  322.     }
  323.  
  324.     return(buffer);
  325.  
  326. }
  327.  
  328.  
  329. /*
  330.  * Write out a hotlist header entry.  See comment at the top of
  331.  *   hot_measure_Header for the format used.  Assume we start writing at
  332.  *   the start of the buffer passed in.  Return a pointer to where the
  333.  *   buffer ends when we get done.
  334.  */
  335. PRIVATE char *
  336. hot_write_Header(char * buffer, HotlistStruct * item, int bLongFormat, int nIndent)
  337. {
  338.  
  339.     XP_List * list;
  340.     int iLen;
  341.     int32 lVal;
  342.     int32 sVal;
  343.  
  344.     if(!item || !buffer)
  345.         return(buffer);    
  346.  
  347.     if(bLongFormat) {                 
  348.  
  349.         /* copy the type */
  350.         sVal = (int16) item->type;
  351.         iLen = 2;
  352.         XP_MEMCPY(buffer, &sVal, iLen);
  353.         buffer += iLen;
  354.  
  355.         /* copy the name */
  356.         if(item->name) {
  357.             iLen = XP_STRLEN(item->name);
  358.             XP_MEMCPY(buffer, item->name, iLen);
  359.             buffer += iLen;
  360.         }
  361.  
  362.         /* put the \n terminator on */
  363.         *buffer++ = '\n';
  364.  
  365.         /* addition date */
  366.         lVal = (int32) item->addition_date;
  367.         iLen = 4;
  368.         XP_MEMCPY(buffer, &lVal, iLen);
  369.         buffer += iLen;
  370.  
  371.         /* number of children */            
  372.         lVal = XP_ListCount(item->children);
  373.         iLen = 4;
  374.         XP_MEMCPY(buffer, &lVal, iLen);
  375.         buffer += iLen;
  376.  
  377.         /* copy the description */
  378.         if(item->description) {
  379.             iLen = XP_STRLEN(item->description);
  380.             XP_MEMCPY(buffer, item->description, iLen);
  381.             buffer += iLen;
  382.         }
  383.  
  384.         /* put the \n terminator on */
  385.         *buffer++ = '\0';
  386.  
  387.     } else {
  388.  
  389.         XP_MEMSET(buffer, ' ', nIndent);
  390.         buffer += nIndent;
  391.  
  392.         if(item->name) {
  393.             XP_STRCPY(buffer, item->name);
  394.             buffer += XP_STRLEN(item->name);
  395.         }
  396.  
  397.         *buffer++ = '\n';
  398.  
  399.     }
  400.  
  401.     /* if no children just get out now */
  402.     if(!item->children)
  403.         return(buffer);
  404.  
  405.     /* write out the children */
  406.     for(list = item->children->next; list; list = list->next) {
  407.         HotlistStruct * child = (HotlistStruct *) list->object;
  408.  
  409.         if(!child)
  410.             continue;
  411.  
  412.         switch(child->type) {
  413.         case HOT_URLType:
  414.             buffer = hot_write_URL(buffer, child, bLongFormat, nIndent + TEXT_INDENT);
  415.             break;
  416.         case HOT_HeaderType:
  417.             buffer = hot_write_Header(buffer, child, bLongFormat, nIndent + TEXT_INDENT); 
  418.             break;
  419.         case HOT_SeparatorType:
  420.             buffer = hot_write_Separator(buffer, child, bLongFormat, nIndent + TEXT_INDENT); 
  421.             break;
  422.         default:
  423.             break;
  424.         }
  425.  
  426.     }
  427.  
  428.     return(buffer);
  429.  
  430. }
  431.  
  432.  
  433. /*
  434.  * Take a URL packed in a block the way hot_write_URL packs it.
  435.  * Return the new item if we created one
  436.  */
  437. PRIVATE HotlistStruct *
  438. hot_read_URL(char * buffer, HotlistStruct * pListParent, HotlistStruct * item, int bLongFormat, int32 * lBytesEaten)
  439. {
  440.  
  441.     HotlistStruct * new_item = NULL;
  442.  
  443.     if(!buffer)
  444.         return(NULL);
  445.                               
  446.     if(bLongFormat) {                 
  447.  
  448.         int32 addition, visit;
  449.  
  450.         /* get the name */
  451.         char * name = buffer;
  452.         char * address = strchr(name, '\n');
  453.         char * description = NULL;
  454.         char * ptr;
  455.         if(!address)
  456.             return(NULL);
  457.  
  458.         *address++ = '\0';
  459.  
  460.         /* get the address */
  461.         ptr = strchr(address, '\n');
  462.         if(!ptr)
  463.             return(NULL);
  464.  
  465.         *ptr++ = '\0';
  466.  
  467.         /* addition date */
  468.         XP_MEMCPY(&addition, ptr, 4);
  469.         ptr += 4;
  470.  
  471.         /* visiting date */
  472.         XP_MEMCPY(&visit, ptr, 4);
  473.         ptr += 4;
  474.  
  475.         /* get the description (it should be NULL terminated) */
  476.         description = ptr;
  477.  
  478.         /* we should really strip leading whitespace */
  479.         new_item = HOT_CreateEntry(HOT_URLType, name, address, 0, visit);
  480.         new_item->addition_date = addition;
  481.         new_item->description = XP_STRDUP(description);
  482.         *lBytesEaten = XP_STRLEN(description) + (description - buffer) + 1;
  483.  
  484.     } else {
  485.  
  486.         char * end = strchr(buffer, '\n');
  487.  
  488.         /* if there was a return NULL terminate the current string */
  489.         if(end)
  490.             *end++ = '\0';
  491.  
  492.         /* we should really strip leading whitespace */
  493.         new_item = HOT_CreateEntry(HOT_URLType, buffer, buffer, 0, 0);
  494.         new_item->addition_date = time ((time_t *) NULL);
  495.         *lBytesEaten = XP_STRLEN(buffer) + 1;
  496.  
  497.     }
  498.  
  499.     if(item)
  500.         HOT_InsertItemAfter(item, new_item);
  501.     else
  502.         HOT_InsertItemInHeaderOrAfterItem(pListParent, new_item);
  503.         
  504.     return(new_item);
  505.                
  506. }
  507.  
  508.  
  509. /*
  510.  * Take a separator and insert it
  511.  */
  512. PRIVATE HotlistStruct *
  513. hot_read_Separator(char * buffer, HotlistStruct * pListParent, HotlistStruct * item, int bLongFormat, int32 * lBytesEaten)
  514. {
  515. #if 0
  516.     int32 kids = 0;
  517.     int16 sVal;
  518. #endif
  519.     HotlistStruct * new_item = NULL;
  520.  
  521.     if(!buffer)
  522.         return(NULL);
  523.  
  524.     /* can only read long format headers */
  525.     if(bLongFormat) {                 
  526.  
  527.         new_item = HOT_CreateEntry(HOT_SeparatorType, NULL, NULL, 0, 0);
  528.         *lBytesEaten = 0;
  529.  
  530.         if(item)
  531.             HOT_InsertItemAfter(item, new_item);
  532.         else
  533.             HOT_InsertItemInHeaderOrAfterItem(pListParent, new_item);
  534.  
  535.         return(new_item);
  536.  
  537.     }
  538.  
  539.     return(NULL);
  540.                
  541. }
  542.  
  543.  
  544.  
  545. /*
  546.  * Take a header and children packed in a block the way hot_write_Header 
  547.  * packs it.  Return the new header item if we created one
  548.  */
  549. PRIVATE HotlistStruct *
  550. hot_read_Header(char * buffer, HotlistStruct * pListParent, HotlistStruct * item, int bLongFormat, int32 * lBytesEaten)
  551. {
  552.  
  553.     int32 kids = 0;
  554.     int16 sVal;
  555.     HotlistStruct * new_item = NULL;
  556.  
  557.     if(!buffer)
  558.         return(NULL);
  559.  
  560.     /* can only read long format headers */
  561.     if(bLongFormat) {                 
  562.  
  563.         int32 addition;
  564.  
  565.         /* get the name */
  566.         char * name = buffer;
  567.         char * ptr = strchr(name, '\n');
  568.         char * description = NULL;
  569.         if(!ptr)
  570.             return(NULL);
  571.  
  572.         /* skip over the \n but change it to a \0 so strcpy() will work */
  573.         *ptr++ = '\0';
  574.  
  575.         /* addition date */
  576.         XP_MEMCPY(&addition, ptr, 4);
  577.         ptr += 4;
  578.  
  579.         /* number of children to read */
  580.         XP_MEMCPY(&kids, ptr, 4);
  581.         ptr += 4;
  582.  
  583.         /* get the description (it should be NULL terminated) */
  584.         description = ptr;
  585.  
  586.         /* we should really strip leading whitespace */
  587.         new_item = HOT_CreateEntry(HOT_HeaderType, name, NULL, 0, 0);
  588.         new_item->addition_date = addition;
  589.         new_item->description = XP_STRDUP(description);
  590.         *lBytesEaten = XP_STRLEN(description) + (description - buffer) + 1;
  591.  
  592.         /* handle all of the kids now */
  593.         if(kids) {
  594.  
  595.             int i;
  596.             HotlistStruct * kid = NULL;
  597.  
  598.             new_item->children = XP_ListNew();
  599.             buffer += *lBytesEaten;
  600.  
  601.             for(i = 0; i < kids; i++) {
  602.  
  603.                 int32 lEat;
  604.  
  605.                 /* determine the type of the next entry */
  606.                 sVal = 0;
  607.                 XP_MEMCPY(&sVal, buffer, 2);
  608.                 buffer += 2;
  609.                 *lBytesEaten += 2;
  610.  
  611.                 switch(sVal) {
  612.                 case HOT_URLType:
  613.                     kid = hot_read_URL(buffer, new_item, kid, bLongFormat, &lEat);
  614.                     *lBytesEaten += lEat;
  615.                     buffer += lEat;
  616.                     break;
  617.                 case HOT_HeaderType:
  618.                     kid = hot_read_Header(buffer, new_item, kid, bLongFormat, &lEat);
  619.                     *lBytesEaten += lEat;
  620.                     buffer += lEat;
  621.                     break;
  622.                 case HOT_SeparatorType:
  623.                     kid = hot_read_Separator(buffer, new_item, kid, bLongFormat, &lEat);
  624.                     *lBytesEaten += lEat;
  625.                     buffer += lEat;
  626.                     break;
  627.                 default:
  628.                     /* bogus type.  Who knows whats going on.  Just quit and get out */
  629.                     break;
  630.                 }
  631.             
  632.             }        
  633.  
  634.         } else {
  635.  
  636.             /* no kids */
  637.             new_item->children = NULL;
  638.  
  639.         }
  640.  
  641.     }
  642.  
  643.     if(item)
  644.         HOT_InsertItemAfter(item, new_item);
  645.     else
  646.         HOT_InsertItemInHeaderOrAfterItem(pListParent, new_item);
  647.         
  648.     return(new_item);
  649.                
  650. }
  651.  
  652.  
  653.  
  654. /*
  655.  * Allocate and return a string that contains the text representation of
  656.  *   a list of hotlist entries (including headers and their contents).
  657.  * The caller is responsible for freeing the string
  658.  */
  659. PUBLIC char *
  660. HOT_ConvertSelectionsToBlock(HotlistStruct ** list, int iCount, int bLongFormat, int32 * lTotalLen)
  661. {
  662.  
  663.     int i, j;
  664.     int bSkip;
  665.     int16 marker;
  666.     int32 iSpace = 0;
  667.     HotlistStruct * item;
  668.     HotlistStruct * pParent;
  669.     char * pString;
  670.     char * pOriginal;
  671.  
  672.     for(i = 0; i < iCount; i++) {
  673.  
  674.         /* don't skip yet */
  675.         bSkip = FALSE;
  676.  
  677.         /* make sure we have a valid item */
  678.         item = list[i];
  679.         if(!item)
  680.             continue;
  681.  
  682.         /* 
  683.          * if our parent is in the list don't add ourselves, we will have
  684.          *   been added when our parent got added.  Ugh.  This is going to be
  685.          *   n^2 over the number of selected items
  686.          */
  687.         for(pParent = item->parent; pParent && !bSkip; pParent = pParent->parent) {
  688.             for(j = 0; (j < iCount) && (!bSkip) ; j++)
  689.                 if(list[j] == pParent)
  690.                     bSkip = TRUE;
  691.         }
  692.  
  693.         if(bSkip)
  694.             continue;
  695.  
  696.         /* decide how much space we need */
  697.         switch(item->type) {
  698.         case HOT_URLType:
  699.             iSpace += hot_measure_URL(item, bLongFormat, 0);
  700.             break;
  701.         case HOT_HeaderType:
  702.             iSpace += hot_measure_Header(item, bLongFormat, 0);
  703.             break;
  704.         case HOT_SeparatorType:
  705.             iSpace += hot_measure_Separator(item, bLongFormat, 0);
  706.             break;
  707.         default:
  708.             break;
  709.         }
  710.  
  711.     }
  712.  
  713.     /* leave room for end of list marker */
  714.     if(bLongFormat)
  715.         iSpace += 2;
  716.  
  717.     /* leave room for the termination character */
  718.     iSpace++;
  719.  
  720. #ifdef XP_WIN16
  721.     if(iSpace > 32000)
  722.         return(NULL);
  723. #endif
  724.  
  725.     /* allocate the string */
  726.     pOriginal = pString = (char *) XP_ALLOC(iSpace * sizeof(char));
  727.     if(!pString)
  728.         return(NULL);
  729.  
  730.     /* Make a big string */
  731.     for(i = 0; i < iCount; i++) {
  732.  
  733.         bSkip = FALSE;
  734.  
  735.         /* make sure we have a valid item */
  736.         item = list[i];
  737.         if(!item)
  738.             continue;
  739.  
  740.         /* 
  741.          * if our parent is in the list don't add ourselves, we will have
  742.          *   been added when our parent got added.  Ugh.  This is going to be
  743.          *   n^2 over the number of selected items
  744.          */
  745.         for(pParent = item->parent; pParent && !bSkip; pParent = pParent->parent) {
  746.             for(j = 0; (j < iCount) && (!bSkip) ; j++)
  747.                 if(list[j] == pParent)
  748.                     bSkip = TRUE;
  749.         }
  750.  
  751.         if(bSkip)
  752.             continue;
  753.  
  754.         /* write out the item */
  755.         switch(item->type) {
  756.         case HOT_URLType:
  757.             pString = hot_write_URL(pString, item, bLongFormat, 0);
  758.             break;
  759.         case HOT_HeaderType:
  760.             pString = hot_write_Header(pString, item, bLongFormat, 0);
  761.             break;
  762.         case HOT_SeparatorType:
  763.             pString = hot_write_Separator(pString, item, bLongFormat, 0);
  764.             break;
  765.         default:
  766.             break;
  767.         }
  768.  
  769.     }
  770.  
  771.     /* stick the end of list marker on so that when we are decoding this */
  772.     /* block we know when we are done                                    */
  773.     if(bLongFormat) {
  774.         marker = 12345;
  775.         XP_MEMCPY(pString, &marker, 2);
  776.         pString +=2;
  777.     }
  778.  
  779.     /* end the string and return the total length to our caller */
  780.     *pString++ = '\0';
  781.     *lTotalLen = (pString - pOriginal);
  782.     return(pOriginal);
  783.  
  784. }
  785.  
  786.  
  787.  
  788. /*
  789.  * Take a block of memory formatted by HOT_ConvertSelectionsToBlock and insert
  790.  *   the items it represents into the hotlist following 'item'.  If item is 
  791.  *   NULL insert at the beginning of the hotlist.
  792.  */
  793. PUBLIC void
  794. HOT_InsertBlockAt(char * pOriginalBlock, HotlistStruct * item, int bLongFormat, int32 lTotalLen)
  795. {
  796.  
  797.     int16 sVal;              /* 16-bit scratch variable */
  798.     int32 lBytesEaten = 0;   /* total number of bytes eaten */
  799.     int32 lEat;              /* number of bytes eaten on this item */
  800.     char * pCurrentPos;
  801.     char * pBlock;
  802.     HotlistStruct * pParent = HOT_GetHotlist();
  803.  
  804.     if(!pOriginalBlock)
  805.         return;
  806.  
  807.     /* make a copy of the string we can write into */    
  808.     pCurrentPos = pBlock = (char *) XP_ALLOC(lTotalLen + 1);
  809.     if(!pBlock)
  810.         return;    
  811.  
  812.     /* copy the data over and make sure we are NULL terminated to make life easier */    
  813.     XP_MEMCPY(pBlock, pOriginalBlock, lTotalLen);
  814.     pBlock[lTotalLen] = '\0';
  815.  
  816.     /* 
  817.      * if our very first element is a header then we really want to insert
  818.      *   everything into the header and not after it --- I think.
  819.      */
  820.     if(item && item->type == HOT_HeaderType) {
  821.         pParent = item;
  822.         item = NULL;
  823.  
  824.         /* 
  825.          * gack! if we are inserting under a header make sure its set up
  826.          *  to accept children
  827.          */
  828.         if(!pParent->children)
  829.             pParent->children = XP_ListNew();
  830.     }
  831.  
  832.     /* long format can have all kinds of different types of things in it */
  833.     if(bLongFormat) {    
  834.  
  835.         while(lBytesEaten < lTotalLen) {
  836.  
  837.             /* determine the type of the next entry */
  838.             sVal = 0;
  839.             XP_MEMCPY(&sVal, pCurrentPos, 2);
  840.             pCurrentPos += 2;
  841.             lBytesEaten += 2;
  842.  
  843.             switch(sVal) {
  844.             case HOT_URLType:
  845.                 item = hot_read_URL(pCurrentPos, pParent, item, bLongFormat, &lEat);
  846.                 lBytesEaten += lEat;
  847.                 pCurrentPos += lEat;
  848.                 break;
  849.             case HOT_HeaderType:
  850.                 item = hot_read_Header(pCurrentPos, pParent, item, bLongFormat, &lEat);
  851.                 lBytesEaten += lEat;
  852.                 pCurrentPos += lEat;
  853.                 break;
  854.             case HOT_SeparatorType:
  855.                 item = hot_read_Separator(pCurrentPos, pParent, item, bLongFormat, &lEat);
  856.                 lBytesEaten += lEat;
  857.                 pCurrentPos += lEat;
  858.                 break;
  859.             default:
  860.                 /* bogus type.  Who knows whats going on.  Just quit and get out */
  861.                 return;
  862.                 break;
  863.             }        
  864.  
  865.         }
  866.  
  867.     } else {
  868.  
  869.         /* short format is just a list of URLs separated by \n's */
  870.         while(lBytesEaten < lTotalLen) {
  871.  
  872.             item = hot_read_URL(pCurrentPos, pParent, item, bLongFormat, &lEat);
  873.             lBytesEaten += lEat;
  874.             pCurrentPos += lEat;
  875.  
  876.             /* if we just walked over a \0 we are done */
  877.             if(pOriginalBlock[lBytesEaten - 1] == '\0')
  878.                 lBytesEaten = lTotalLen;
  879.  
  880.         }
  881.  
  882.     }
  883.  
  884.     /* mark the bookmark list as changed and clean up */
  885.     HOT_SetModified();
  886.     XP_FREE(pBlock);
  887.  
  888. }
  889.