home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX503 / STEPART.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  45.8 KB  |  1,802 lines

  1. /*
  2.  * Partition editing and picking.
  3.  *
  4.  * 09-Dec-87    ml.    Added pheader() to take care of placing partition
  5.  *            headers at good sectors.
  6.  * 14-Jan-88    ml.    Added chkpart() to make sure partition scheme does
  7.  *            not map pass end of device.
  8.  * 02-Dec-88     jye. Change and add codes so that can be used for MS-DOS
  9.  *
  10.  * 12-Dec-89    jye. Fixed a bug in stuffamt() so that correctly show three
  11.  *                digits or more in the partitioning deialog box.
  12.  */
  13.  
  14. #include "obdefs.h"
  15. #include "gemdefs.h"
  16. #include "osbind.h"
  17. #include "mydefs.h"
  18. #include "part.h"
  19. #include "bsl.h"
  20. #include "hdx.h"
  21. #include "addr.h"
  22. #include "myerror.h"
  23. #include "ipart.h"
  24.  
  25. #define ROLL1 1            /* move the bar one step */
  26. #define ROLL4 4            /* move the bar four steps */
  27. #define NULL 0L            /* the nill pointer */
  28.  
  29. extern int wdesk;
  30. extern int hdesk;
  31. extern long gbslsiz();
  32. extern long bslsiz;
  33. extern SECTOR badbuf[];        /* bad sectors buffer */
  34. extern long sptrk;                /* sector per track */
  35. extern long disksiz;            /* size of disk in blocks */
  36. extern int yesscan;            /* the flag for the func. IBMGPART use */
  37. extern int npart;            /* number of partitions */
  38. extern int ext;            /* the index that point to the extended partition */
  39. extern int extend;        /* the index that point to the end of extended */
  40. extern char ttscsi;        /* 1: SCSI bus drive */
  41.  
  42.  
  43. /*
  44.  * Global variables these routines communicate with
  45.  *
  46.  */
  47. static PART *pinfo;        /* -> partition block */
  48. static int totcyl;        /* total # of cylinder */
  49. static long sizleft;    /* size of unused disk in blocks */
  50. static long extleft;    /* size of unused extended partition in blocks */
  51. static int formw, formh;
  52. static int lx, ly, sx, sy;
  53. static int ok2draw;        /* 0: don't draw PARTPNL boxes */
  54. static char partnames[NAMSIZ];    /* partition name buffer */
  55. static int menuflg;        /* negative: never called partmenu */
  56. static int pnlflg;        /* 1: partition scheme comes from panel */
  57. static int along;        /* 1: will not redraw and clean the box */
  58. static int first;        /* flag for add bad and good sectors only one time */
  59. long sumsiz;            /* the sum of bytes of root sectors */
  60. int tolpart;            /* the total of number partitions */
  61. int epty;                /* the y-coordinate of the moving bar */
  62. int uplim;                /* index of dialog box */
  63. int lowlim;                /* index of dialog box */
  64. int restept;            /* 1: rest the moving bar to initial place */
  65. DPART *headptr;            /* the head pointer of structure */
  66. long ratio, bps;
  67. long nill = (long)NULL;
  68. int prevnpart;            /* former number of partitions */
  69.  
  70.  
  71. /*
  72.  * Figure out partition information;
  73.  *    return OK if xpinfo[] is filled-in,
  74.  *         ERROR on [CANCEL] or something.
  75.  */
  76. sfigpart(bs, dev, rpinfo)
  77.  
  78. char *bs;
  79. int dev;
  80. PART **rpinfo;
  81.  
  82. {
  83.     int ret;
  84.  
  85.     lowlim = 0;
  86.     uplim = 4;
  87.     first = 0;
  88.     along = 0;        /* will redraw and clean the box */
  89.     restept = 0;
  90.  
  91.     /*  Get partition information from disk's root block. */
  92.     if ((ret = getroot(dev, bs, (SECTOR)0)) != 0) {
  93.         if (tsterr(ret) != OK)
  94.             err(rootread);
  95.         return ERROR;
  96.     }
  97.     yesscan = 0;
  98.     
  99.     /* get bad sectors list size */
  100.     if ((bslsiz = gbslsiz(dev)) == 0L) {    /* no bsl */
  101.         return err(oldfmt);
  102.     } else if (bslsiz < 0L) {            /* error occurred */
  103.         if (bslsiz == ERROR)            /* read error */
  104.             err(rootread);
  105.         return ERROR;                /* medium changed error */
  106.     }
  107.  
  108.       if ((ret = chkroot(dev, bs)) == -3)    { /*don't have to show the alert box */ 
  109.         return ERROR;
  110.     } else if (ret != OK)    {
  111.            return err(cruptfmt);
  112.     }
  113.  
  114.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  115.     if (stgpart(dev, bs, (PART *)&pinfo) == ERROR)    {
  116.         if (pinfo > 0) Mfree(pinfo);
  117.         return ERROR;
  118.     }
  119.     if (ext != NO_EXT)    sortpart(pinfo, USER_ED);
  120.  
  121.     /* put partition infomations into the dynamic structure */
  122.     if (part2dpart(npart) == ERROR)        {
  123.         return ERROR;
  124.     }
  125.     menuflg = -1;    /* first time through */
  126.     restept = 1;
  127.     prevnpart = npart;
  128.     for (;;)
  129.     {
  130.     switch (sdoscrbar())
  131.     {
  132.         case SPMENU:            /* chose from menu */
  133.             switch (spartmenu())
  134.             {
  135.                 case PPOK:        *rpinfo = pinfo;
  136.                                 return OK;    /* [OK] */
  137.                 default:
  138.                 case PPCN:        if (pinfo > 0) Mfree(pinfo);
  139.                                 if (headptr > 0) free(headptr);
  140.                                 return BAILOUT;    /* [CANCEL] */
  141.                 case PPEDIT:    restept = 1; 
  142.                                 lowlim = 0;
  143.                                 uplim = 4;
  144.                                 break;        /* continue and edit */
  145.             }
  146.             break;
  147.  
  148.         case EXPERT:    along = 0;
  149.                         lowlim = 0;
  150.                         uplim = 4;
  151.                         restept = 1;
  152.                         ext = 1;        /* set default to 1 */
  153.                         extend = npart-2;
  154.                         switch (doexpert())    {
  155.                             case NOSEL:        if (pinfo > 0)    {
  156.                                                 inipart(pinfo, prevnpart);
  157.                                                 Mfree(pinfo);
  158.                                             }
  159.                                             if (headptr > 0) free(headptr);
  160.                                             return BAILOUT;    /* [CANCEL] */
  161.                             case SELOK:    pnlflg = 1;    
  162.                                         if (pinfo > 0)    {
  163.                                             inipart(pinfo, prevnpart);
  164.                                             Mfree(pinfo);
  165.                                         }
  166.                                         if (dpart2part(ext) == ERROR) {
  167.                                             if (headptr > 0) free(headptr);
  168.                                             if (pinfo > 0) Mfree(pinfo);
  169.                                                 return ERROR;
  170.                                         }
  171.                                         *rpinfo = pinfo;
  172.                                         return OK;
  173.                             default:
  174.                             case TOEDIT: break;
  175.                         }
  176.  
  177.         case SCRUP:      break;
  178.         case SCRDN:      break;
  179.         case SCRBAR:      break;
  180.         case SCREPT:      break;
  181.         case SUNDO:      break;
  182.  
  183.         default:
  184.         case SEPOK:    *rpinfo = pinfo;
  185.                     return OK;
  186.         case SEPCN: if (pinfo > 0) Mfree(pinfo);
  187.                     if (headptr > 0) free(headptr);
  188.                     return BAILOUT;
  189.     }
  190.     }
  191. }
  192.  
  193. int objnums[] = { SPARTNM0, SPARTNM1, SPARTNM2, SPARTNM3};
  194. int objups[] = {SEP0UP, SEP1UP, SEP2UP, SEP3UP};
  195. int objdns[] = {SEP0DN, SEP1DN, SEP2DN, SEP3DN};
  196. int objsizs[] = {SEP0SIZ, SEP1SIZ, SEP2SIZ, SEP3SIZ};
  197. char *sizstr[6] = {"1000.0Mb0", "1000.0Mb0", "1000.0Mb0", "1000.0Mb0", 
  198.                    "1000.0Mb0", " 999 partition(s)"};
  199. char *numstr[4] = {"#999", "#999", "#999", "#999"};
  200.  
  201.  
  202. int objnum[] = { PART1, PART2, PART3, PART4, PARTX, PARTY, PARTZ};
  203. char *xsizstr[7] = {"1000.0Mb0", "1000.0Mb0", "1000.0Mb0", "1000.0Mb0", 
  204.                    "1000.0Mb0", "1000.0Mb0", "1000.0Mb0"};
  205. int objsiz[] = {PART1MB, PART2MB, PART3MB, PART4MB, PARTXMB, PARTYMB, PARTZMB};
  206. char *xnumstr[7] = {"#999", "#999", "#999", "#999", "#999", "#999", "#999"};
  207. int objsel[] = { SELECT1, SELECT2, SELECT3, SELECT4, SELECT5, SELECT6};
  208. char *selstr[6] = {"from #2 to #99", "from #2 to #99", "from #2 to #99", 
  209.                     "from #3 to #99", "from #3 to #99", "from #4 to #99" };
  210. doexpert()
  211. {
  212.  
  213.     int i, lastpno, pno;
  214.     int run = 1;
  215.     int erase = 0;
  216.     int but;
  217.  
  218.     ok2draw = 0;
  219.  
  220.  
  221.     exppnl[TOEDIT].ob_state = NORMAL;
  222.     exppnl[NOSEL].ob_state = NORMAL;
  223.     exppnl[SELOK].ob_state = NORMAL;
  224.  
  225.     drawsel(2, npart-2, 0, exppnl);
  226.     drawsel(2, npart-1, 1, exppnl);
  227.     drawsel(2, npart, 2, exppnl);
  228.     drawsel(3, npart-1, 3, exppnl);
  229.     drawsel(3, npart, 4, exppnl);
  230.     drawsel(4, npart, 5, exppnl);
  231.  
  232.  
  233.     for (i = 0; i < 7; i++)        {
  234.         if (npart > 7)    {
  235.             if (i > 3)    {
  236.                 if (i == 4)
  237.                     lastpno = npart - i + 1;
  238.                 drawpart(i, lastpno++, exppnl);
  239.             } else {
  240.                 drawpart(i, i, exppnl);
  241.             }
  242.         } else if (npart == 5)    {
  243.             if (i > 4)    {
  244.                 pno = -1;
  245.                 drawpart(i, pno, exppnl);
  246.             } else {
  247.                 drawpart(i, i, exppnl);
  248.             }
  249.         } else if (npart == 6)    {
  250.             if (i > 5)    {
  251.                 pno = -1;
  252.                 drawpart(i, pno, exppnl);
  253.             } else {
  254.                 drawpart(i, i, exppnl);
  255.             }
  256.         } else {
  257.             drawpart(i, i, exppnl);
  258.         }
  259.     }
  260.  
  261.     /* set the default selected */
  262.     exppnl[SELECT1].ob_state = NORMAL | SELECTED;
  263.     exppnl[SELECT2].ob_state = NORMAL;
  264.     exppnl[SELECT3].ob_state = NORMAL;
  265.     exppnl[SELECT4].ob_state = NORMAL;
  266.     exppnl[SELECT5].ob_state = NORMAL;
  267.     exppnl[SELECT6].ob_state = NORMAL;
  268.     turnexton(1, npart-2);
  269.  
  270.     ARROW_MOUSE;
  271.     dsplymsg(exppnl);
  272.  
  273.     ++ok2draw;
  274.     while (run)        {
  275.         switch((but = form_do(exppnl, -1)))        {
  276.             case TOEDIT:    run = 0; 
  277.                             break;
  278.             case NOSEL:        run = 0;
  279.                             erase = 1;
  280.                             break;
  281.             case SELOK:        run = 0;
  282.                             erase = 1;
  283.                             break;
  284.             case SELECT1:    ext = 1;
  285.                             extend = npart - 2;
  286.                             turnexton(1, npart-2);
  287.                             break;
  288.             case SELECT2:    ext = 1;
  289.                             extend = npart - 1;
  290.                             turnexton(1, npart-1);
  291.                             break;
  292.             case SELECT3:    ext = 1;
  293.                             extend = npart;
  294.                             turnexton(1, npart);
  295.                             break;
  296.             case SELECT4:    ext = 2;
  297.                             extend = npart - 1;
  298.                             turnexton(2, npart-1);
  299.                             break;
  300.             case SELECT5:    ext = 2;
  301.                             extend = npart;
  302.                             turnexton(2, npart);
  303.                             break;
  304.             case SELECT6:    ext = 3;
  305.                             extend = npart;
  306.                             turnexton(3, npart);
  307.                             break;
  308.         }
  309.     }
  310.     if (erase)    {
  311.         erasemsg();
  312.         BEE_MOUSE;
  313.     }
  314.     return but;
  315. }
  316.  
  317. turnexton(stnum, endnum)
  318. int stnum;        /* the number that start to turn on the extended partition */
  319. int endnum;        /* the number that end to turn on the extended partition */
  320. {
  321.     int i;
  322.  
  323.     if (npart > 7)    {
  324.         endnum = 7 - (npart - endnum);
  325.     }
  326.     for (i = 0; i < 7; i++)    {
  327.         exppnl[objsiz[i]].ob_state = NORMAL;
  328.         if ((i >= stnum) && (i < endnum))    {
  329.             exppnl[objsiz[i]].ob_state |= SELECTED;
  330.         }
  331.         if (ok2draw)    {
  332.             objc_draw(exppnl, objsiz[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  333.         }
  334.  
  335.     }
  336.     ok2draw++;
  337. }
  338.  
  339.  
  340.  
  341.  
  342. drawsel(stnum, tonum, num, pnl)
  343. int stnum;        /* the first extended partition number */
  344. int tonum;        /* the last extended partition number */
  345. int num;        /* the number of selected extended partition scheme */
  346. OBJECT *pnl;
  347. {
  348.  
  349.     /* set the select range in the dialog box */
  350.     calextnum(stnum, tonum, selstr[num]);
  351.     (pnl[objsel[num]].ob_spec)->te_ptext = selstr[num];
  352.     if (ok2draw)    {
  353.         objc_draw(pnl, objsel[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  354.     }
  355. }
  356.  
  357.  
  358. drawpart(num, pno, pnl)
  359. int num;        /* the number of selected extended partition scheme */
  360. int pno;        /* the partition number */
  361. OBJECT *pnl;
  362. {
  363.     DPART *pinfo, *addr();
  364.  
  365.     if (pno == NO_EXT)    { /* not exists */
  366.         pnl[objsiz[num]].ob_spec = "Unused";
  367.         pnl[objsiz[num]].ob_state = NORMAL;
  368.         pnl[objsiz[num]].ob_flags = TOUCHEXIT;
  369.         (pnl[objnum[num]].ob_spec)->te_ptext = "     ";
  370.     } else {
  371.         pinfo = addr(pno);
  372.         stuffamt(pinfo->siz, xsizstr[num], 0);
  373.         pnl[objsiz[num]].ob_spec = xsizstr[num];
  374.         pnl[objsiz[num]].ob_state = NORMAL;
  375.         pnl[objsiz[num]].ob_flags = TOUCHEXIT;
  376.  
  377.         stpartnum(pno+1, xnumstr[num]);
  378.         (pnl[objnum[num]].ob_spec)->te_ptext = xnumstr[num];
  379.     }
  380.     if (ok2draw)    {
  381.         objc_draw(pnl, objsiz[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  382.         objc_draw(pnl, objnum[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  383.     }
  384.  
  385. }
  386.  
  387. sdoscrbar()
  388.  
  389. {
  390.  
  391.     int i, j, but, step;
  392.     int xrun = 1;
  393.     long usesiz;
  394.     DPART *temptr, *addr();
  395.  
  396.     ok2draw = (along) ? 1 : 0;
  397.  
  398.     /* set form for first display */
  399.     scrpnl[SEPOK].ob_state = NORMAL;
  400.     scrpnl[SEPCN].ob_state = NORMAL;
  401.     scrpnl[SPMENU].ob_state = NORMAL;
  402.     scrpnl[SUNDO].ob_state = NORMAL;
  403.  
  404.     if (!first++)    {    /* initially ST partition */
  405.         temptr = headptr;
  406.         for (i = 0; i < npart; i++)    {
  407.             if ((temptr->flg & P_EXISTS) && 
  408.                 (!((temptr->next)->flg & P_EXISTS)))    {
  409.                 temptr->siz += bslsiz + 1; /* add sacrificed space back */
  410.             }
  411.             temptr = temptr->next;
  412.         }
  413.     }
  414.  
  415.     for (i = -1; i < 4; ++i)
  416.          sepadj(0L, i, scrpnl);
  417.     if (restept)    {
  418.         scrpnl[SCREPT].ob_y = 0;
  419.         restept = 0;
  420.     }
  421.     if (!along)        {
  422.         ARROW_MOUSE;
  423.         dsplymsg(scrpnl);
  424.     }
  425.  
  426.     /*
  427.      * Edit the thing;
  428.      * canonical event-driven switch().
  429.      */
  430.     ++ok2draw;
  431.     while (xrun)     {
  432.     along = 0;
  433.     if (npart > 4)    {
  434.         scrpnl[EXPERT].ob_state = NORMAL;
  435.         scrpnl[EXPERT].ob_flags = TOUCHEXIT;
  436.     } else {
  437.         scrpnl[EXPERT].ob_state = DISABLED;
  438.         scrpnl[EXPERT].ob_flags = NONE;
  439.     }
  440.     objc_draw(scrpnl, EXPERT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  441.  
  442.     switch ((but = form_do(scrpnl, -1)))
  443.     {
  444.     case SEPOK:    pnlflg = 1;
  445.                 if (pinfo > 0L)    {
  446.                     inipart(pinfo,prevnpart);
  447.                     Mfree(pinfo);
  448.                 }
  449.                 ext = 1;        /* set the default extended partition */
  450.                 extend = npart - 2;
  451.                 if (dpart2part(ext) == ERROR) return ERROR;
  452.                 xrun = 0;
  453.                 break;
  454.     case SEPCN:    xrun = 0;            /* return */
  455.                     break;
  456.     case EXPERT: if (npart > 4)        {
  457.                     xrun = 0;
  458.                     break;
  459.                  } else {
  460.                      xrun = 1;
  461.                     break;
  462.                  }
  463.     case SCRBAR: if (sdoscrupdn(ROLL4) == ERROR) return ERROR;
  464.                     xrun = 0;
  465.                     break;
  466.     case SCRUP:  if (sdoscrupdn(ROLL1) == ERROR) return ERROR;
  467.                 xrun = 0;
  468.                 break;
  469.     case SCRDN:  if (sdoscrupdn(ROLL1) == ERROR) return ERROR;
  470.                 xrun = 0;
  471.                 break;
  472.     case SCREPT: if (sdoslidebox(scrpnl) == ERROR) return ERROR;
  473.                 xrun = 0;
  474.                 break;
  475.     case SPMENU:    xrun = 0;
  476.                     break;
  477.  
  478.     case SUNDO:     /* restore the starting parameters */
  479.                 lowlim = 0;
  480.                 uplim = 4;
  481.                 if (part2dpart(prevnpart) == ERROR)    return ERROR;
  482.                 for (i = -1; i < NPARTS; ++i)
  483.                     sepadj(0L, i, scrpnl);
  484.                 npart = prevnpart;
  485.                 scrpnl[SCREPT].ob_y = 0;
  486.                 scrpnl[SUNDO].ob_state = NORMAL;
  487.                 objc_draw(scrpnl, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  488.                 objc_draw(scrpnl, SUNDO, MAX_DEPTH, 0, 0, wdesk, hdesk);
  489.                 break;
  490.  
  491.     case SEP0SIZ:xrun = septoggle(0, scrpnl);    break;
  492.     case SEP0UP:    sepadj(MEGABYTE, 0, scrpnl);    break;
  493.     case SEP0DN:    sepadj(-MEGABYTE, 0, scrpnl);    break;
  494.  
  495.     case SEP1SIZ:xrun = septoggle(1, scrpnl);    break;
  496.     case SEP1UP:    sepadj(MEGABYTE, 1, scrpnl);    break;
  497.     case SEP1DN:    sepadj(-MEGABYTE, 1, scrpnl);    break;
  498.  
  499.     case SEP2SIZ:xrun = septoggle(2, scrpnl);    break;
  500.     case SEP2UP:    sepadj(MEGABYTE, 2, scrpnl);    break;
  501.     case SEP2DN:    sepadj(-MEGABYTE, 2, scrpnl);    break;
  502.  
  503.     case SEP3SIZ:xrun = septoggle(3, scrpnl);    break;
  504.     case SEP3UP:    sepadj(MEGABYTE, 3, scrpnl);    break;
  505.     case SEP3DN:    sepadj(-MEGABYTE, 3, scrpnl);    break;
  506.       }
  507.   }
  508.  
  509.  
  510.     /*
  511.      * Draw shrinking box and cleanup the screen;
  512.      * return thing that caused our exit.
  513.      */
  514.     if (!along)    {
  515.         erasemsg();
  516.         BEE_MOUSE;
  517.     }
  518.     return but;
  519. }
  520.  
  521.  
  522.  
  523.  
  524. /* 
  525.  * conver the partition number for the dialog box to the string .
  526.  *
  527.  */
  528.  
  529. calextnum(stnum, tonum, str)
  530.  
  531. int stnum,tonum;
  532. char *str;
  533.  
  534. {
  535.     int  i = 0;
  536.     int addspace = 0;
  537.     char tem[10];
  538.  
  539.     /* set the partition number header */
  540.     *str++ = 'f';
  541.     *str++ = 'r';
  542.     *str++ = 'o';
  543.     *str++ = 'm';
  544.     *str++ = ' ';
  545.     *str++ = '#';
  546.     *str++ = stnum % 10 + '0';
  547.     *str++ = ' ';
  548.     *str++ = 't';
  549.     *str++ = 'o';
  550.     *str++ = ' ';
  551.     *str++ = '#';
  552.     /* conver the integer to ASCII */
  553.     do    {    /* generate digits in reverse order */
  554.         tem[i++] = tonum % 10 + '0';    /* get next digits */
  555.     } while ((tonum /= 10) > 0);        /* delete it */
  556.  
  557.     if (i == 1)    {
  558.         addspace = 1;
  559.     }
  560.     for (; i > 0; )    { /* reverse string 'str' in place */
  561.         *str++ = tem[--i];
  562.     }
  563.     if (addspace)    *str++ = ' ';
  564.        *str = '\0';
  565. }
  566.  
  567.  
  568. sdoscrupdn(roll)
  569. int roll;
  570.  
  571. {
  572.      int gr_mkmx, gr_mkmy;
  573.     int gr_mkmstate, gr_mkkstate;
  574.     int barht, barx, bary;
  575.     int eptx, eptht;
  576.  
  577.     along = 1;
  578.     barht = scrpnl[SCRBAR].ob_height;
  579.     eptht = scrpnl[SCREPT].ob_height;
  580.     graf_mkstate(&gr_mkmx, &gr_mkmy, &gr_mkmstate, &gr_mkkstate);
  581.     objc_offset(scrpnl, SCREPT, &eptx, &epty);
  582.     objc_offset(scrpnl, SCRBAR, &barx, &bary);
  583.     /* check which part of bar was clicked */
  584.     if (gr_mkmy > (epty+eptht))    {    /* low part of bar was clicked */
  585.         if (roll == ROLL4)    {
  586.             if ((eptht > (bary+barht-epty-eptht)) || (lowlim == 20))    {
  587.                 scrpnl[SCREPT].ob_y = barht - eptht;
  588.             } else {
  589.                 scrpnl[SCREPT].ob_y += eptht;
  590.             }
  591.             lowlim = ((24-lowlim) < 4) ? (24) : (lowlim+4); 
  592.             if ((lowlim + 4) > uplim) uplim += 4;
  593.             if (uplim > npart)    {
  594.                 if (creatmem(ROLL4) == ERROR)    {
  595.                     return ERROR;
  596.                 }
  597.             }
  598.         } else if (lowlim == 24)    { /* the empty bar is on the bottom */
  599.             return OK;
  600.         } else {
  601.             if ((eptht > ((bary+barht-epty-eptht) * 4)) || (lowlim == 23))    {
  602.                 scrpnl[SCREPT].ob_y = barht - eptht;
  603.             } else {
  604.                 scrpnl[SCREPT].ob_y += eptht / 4;
  605.             }
  606.             lowlim++;
  607.             if ((lowlim + 4) > uplim)      uplim++;
  608.             if (uplim > npart)    {
  609.                 if (creatmem(ROLL4) == ERROR)    {
  610.                     return ERROR;
  611.                 }
  612.             }
  613.         }
  614.     } else if (gr_mkmy < epty)    {    /* upper part of bar was clicked */
  615.         if (roll == ROLL4)    {
  616.             if ((eptht > (epty - bary)) || (lowlim <= 4))    {
  617.                 scrpnl[SCREPT].ob_y = 0;
  618.                 lowlim = 0;
  619.             } else {
  620.                 scrpnl[SCREPT].ob_y -= eptht;
  621.                 lowlim -= 4;
  622.             }
  623.         } else {
  624.             if ((eptht > ((epty - bary) * 4)) || (lowlim == 1))    {
  625.                 scrpnl[SCREPT].ob_y = 0;
  626.             } else {
  627.                 scrpnl[SCREPT].ob_y -= eptht / 4;
  628.             }
  629.             if (lowlim)     {
  630.                 lowlim--;
  631.             }
  632.         }
  633.     }
  634.     objc_draw(scrpnl,SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  635. }
  636.  
  637.  
  638. #define WHITEBAR 24        /* when the white bar on the bottom, the */
  639.                         /* 'lowlim' will equal to 24 */
  640. sdoslidebox(tree)
  641.  
  642. OBJECT *tree;
  643.  
  644. {
  645.     int gr_wreturn, eptatmax;
  646.     int numofmem;            /*   # of memories to be allocated */
  647.  
  648.     along = 1;
  649.     eptatmax = tree[SCRBAR].ob_height - tree[SCREPT].ob_height;
  650.     gr_wreturn = graf_slidebox(tree, SCRBAR, SCREPT, 1);
  651.     lowlim = (WHITEBAR * gr_wreturn) / 1000;
  652.     if ((lowlim >= uplim) || ((lowlim + 4) > uplim))     {
  653.         uplim = lowlim + 4;
  654.         if (uplim > npart)    {
  655.             numofmem = uplim - npart;
  656.             if (creatmem(numofmem) == ERROR)    {
  657.                 return ERROR;
  658.             }
  659.         }
  660.     }
  661.     /*
  662.     tree[SCREPT].ob_y = (eptatmax * gr_wreturn) / 1000;
  663.     */
  664.     tree[SCREPT].ob_y = (eptatmax * lowlim ) / 24;
  665.     objc_draw(tree, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  666. }
  667.  
  668.  
  669.  
  670. /*
  671.  * Toggle partition in/out of existence.
  672.  */
  673. septoggle(n, pnl)
  674. int n;
  675. OBJECT *pnl;
  676. {
  677.     int i; 
  678.     DPART *pinfo, *ppinfo, *npinfo, *addr();
  679.     /*
  680.      * Toggle existance flag,
  681.      * enforce minimum partition size.
  682.      */
  683.     i = n + lowlim;
  684.     pinfo = addr(i);    /* return the structure pointer */
  685.     ppinfo = addr(i-1);    /* return the previous structure pointer */
  686.     npinfo = addr(i+1);    /* return the next structure pointer */
  687.     if ((!(pinfo->flg & P_EXISTS)) && (pinfo->siz) && (ppinfo)
  688.                             && (ppinfo->flg & P_EXISTS)){
  689.         if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  690.         pinfo->flg = P_EXISTS;
  691.         sepadj(0L, n, pnl);
  692.     } else if (((pinfo->flg ^= P_EXISTS) & P_EXISTS) 
  693.           && !pinfo->siz) {
  694.         /* make extended partition continue */
  695.         if (!i || ((ppinfo) && (ppinfo->flg & P_EXISTS)))        {
  696.             if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  697.             sepadj(MEGABYTE, n, pnl);
  698.         } else {
  699.             sepadj(0L, n, pnl);
  700.         }
  701.     } else if ((!lowlim) && (!i)&&(!(npinfo->flg & P_EXISTS)))    {
  702.         sepadj(0L, n, pnl);
  703.     } else if ((!lowlim) && (!i)&&(pinfo->flg & P_EXISTS))    {
  704.         sepadj(0L, n, pnl);
  705.     } else {             /* do nothing, turn it back to the initial state */
  706.         pinfo->flg ^= P_EXISTS;
  707.         if ((pinfo->flg & P_EXISTS) && (!(npinfo->flg & P_EXISTS))) {
  708.               pinfo->flg ^= P_EXISTS;
  709.             sepadj(0L, n, pnl);
  710.         }
  711.     }
  712.     sepadj(0L, -1, pnl);            /* update #left field */
  713.     return YES;
  714. }
  715.     
  716.  
  717. /*
  718.  * Adjust partition `pno' size by `amt';
  719.  * if `pno' is -1, just recompute and update disk space left indicator.
  720.  *
  721.  * A partition of size zero is disabled.
  722.  */
  723.  
  724. #define HALFMEGA 1024L
  725.  
  726. sepadj(amt, pno, pnl)
  727. long amt;
  728. int pno;
  729. OBJECT *pnl;
  730. {
  731.     int i;
  732.     long siz;
  733.     long sizhas;     /* disk size left in sectors */
  734.     long totsiz = 0;
  735.     DPART *pinfo, *npinfo, *addr();
  736.  
  737.     if (pno < 0) 
  738.         goto fixleft;
  739.     pno += lowlim;
  740.  
  741.     pinfo = headptr;
  742.     /* compute total used */
  743.     while (pinfo->flg & P_EXISTS)    {
  744.             totsiz += pinfo->siz;
  745.             pinfo = pinfo->next;
  746.     }
  747.     pinfo = addr(pno);
  748.     npinfo = addr(pno+1);
  749.     sizhas = disksiz;
  750.  
  751.     /*
  752.      * If total partition size exceeds the disk's
  753.      * capacity, reduce `amt' accordingly.
  754.      */
  755.     if (amt >= 0 && totsiz + amt > sizhas)
  756.     amt = sizhas - totsiz;
  757.  
  758.     if (amt > 0) {
  759.     /*
  760.      * Enforce maximum partition size.
  761.      */
  762.     siz = sizhas - totsiz;            /* siz = #free */
  763.     if (amt > siz) amt = siz;        /* ensure amt <= siz */
  764.     if (pinfo->siz + amt > sizhas)    /* ensure partition not */
  765.         amt = sizhas - pinfo->siz;    /* too big */
  766.  
  767.     /* check the partition size that can't over 256Mb (8K bytes per sect) */
  768.     /* for the reason of hardware                                           */
  769.     /*
  770.     if ((pinfo->siz + amt) > 256 * 2048)    {
  771.         form_alert(1, maxpsize);
  772.         return OK;
  773.     }
  774.     */
  775.     pinfo->siz += amt;        /* bump partition size */
  776.     pinfo->flg = P_EXISTS;
  777.     } else if (amt < 0) {
  778.     amt = -amt;
  779.     if (pinfo->siz > amt) {        /* reduce partition size */
  780.         pinfo->siz -= amt;
  781.         if ((pinfo->siz < HALFMEGA) && (npinfo->flg & P_EXISTS))
  782.             pinfo->siz = amt;
  783.     } else if ((pinfo->siz <= amt) &&
  784.                 (!(npinfo->flg & P_EXISTS)))    {
  785.         /* reduce partition size */
  786.         pinfo->siz = 0L;
  787.     } 
  788.   }
  789.  
  790.     /*
  791.      * Enforce minimum partition size of half mega byte 
  792.      */
  793.     if (pinfo->siz < HALFMEGA)
  794.     pinfo->siz = 0L;
  795.  
  796.     /*
  797.      * Disable partitions of zero size
  798.      */
  799.     if (!pinfo->siz)    {
  800.         pinfo->flg &= ~P_EXISTS;
  801.     }
  802.  
  803.     /*
  804.      * Redraw the thing;
  805.      * if partition is disabled, shadow it and disable UP/DOWN buttons;
  806.      * otherwise setup the buttons, setup size string, and so on...
  807.      */
  808.     pno -= lowlim;
  809.     if (!(pinfo->flg & P_EXISTS)) {
  810.         pnl[objsizs[pno]].ob_spec = "Unused";
  811.         pnl[objsizs[pno]].ob_state = NORMAL;
  812.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  813.  
  814.         pnl[objups[pno]].ob_state = DISABLED;
  815.         pnl[objups[pno]].ob_flags = NONE;
  816.  
  817.         pnl[objdns[pno]].ob_state = DISABLED;
  818.         pnl[objdns[pno]].ob_flags = NONE;
  819.     } else {
  820.         stuffamt(pinfo->siz, sizstr[pno], 0);
  821.         pnl[objsizs[pno]].ob_spec = sizstr[pno];
  822.         pnl[objsizs[pno]].ob_state = NORMAL;
  823.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  824.  
  825.         pnl[objups[pno]].ob_state = NORMAL;
  826.         pnl[objups[pno]].ob_flags = TOUCHEXIT;
  827.  
  828.         pnl[objdns[pno]].ob_state = NORMAL;
  829.         pnl[objdns[pno]].ob_flags = TOUCHEXIT;
  830.     }
  831.  
  832.     /* set the partition numbers in the dialog box */
  833.     stpartnum(lowlim+pno+1, numstr[pno]);
  834.     (pnl[objnums[pno]].ob_spec)->te_ptext = numstr[pno];
  835.  
  836.     if (ok2draw) {
  837.         objc_draw(pnl, objsizs[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  838.         objc_draw(pnl, objups[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  839.         objc_draw(pnl, objdns[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  840.         objc_draw(pnl, objnums[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  841.     }
  842.  
  843.  
  844. fixleft:
  845.  
  846.     /*
  847.      * Compute and redraw 'space left' indicator and
  848.      * calculat the total partitions number */
  849.  
  850.        sizleft = disksiz;
  851.     pinfo = headptr;
  852.     tolpart = 0;
  853.     while ((pinfo->flg & P_EXISTS) && (pinfo->siz > 0))     {
  854.             sizleft -= pinfo->siz;
  855.             tolpart++;  
  856.             pinfo = pinfo->next;
  857.     }
  858.     npart = tolpart;
  859.        stuffamt(sizleft, sizstr[4], 1);
  860.        (pnl[SEPLEFT].ob_spec)->te_ptext = sizstr[4];
  861.  
  862.     totalpart(tolpart, sizstr[5]);
  863.        (pnl[STOLPART].ob_spec)->te_ptext = sizstr[5];
  864.  
  865.     if (ok2draw)    {
  866.         objc_draw(pnl, SEPLEFT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  867.         objc_draw(pnl, STOLPART, MAX_DEPTH, 0, 0, wdesk, hdesk);
  868.     }
  869. }
  870.  
  871. /*
  872.  * Atoi `amt', #blocks, into 999.9Mb (or something like that);
  873.  * assumes enough space in `str'.
  874.  */
  875. stuffamt(amt, str, flag)
  876. long amt;
  877. char *str;
  878. int flag;            /* 1: for Memory left box. */
  879. {
  880.     long mb, frac;
  881.     int i=0;
  882.  
  883.     mb = amt / 2048;
  884.     frac = amt - (2048 * mb);
  885.     if (frac / 16)
  886.         frac /= 205;        /* that's MEGABYTE / 10 */
  887.     else frac = 0;
  888.     if (frac < 0) frac = -frac;
  889.     if (mb < 0) mb = frac = 0;
  890.  
  891.     if (mb > 999)     {
  892.         *str++ = (mb / 1000) + '0';
  893.         i++;
  894.         mb -= 1000 * (mb / 1000);
  895.         if ((!mb) || (mb < 10))    { /* take care mb=1000 or 1001 case */
  896.             *str++ = '0';
  897.             *str++ = '0';
  898.             i += 2;
  899.         } else if (mb < 100)    { /* take care mb=1099 case */
  900.             *str++ = '0';
  901.             i++;
  902.         }
  903.     }
  904.     if (mb > 99) {
  905.         *str++ = (mb / 100) + '0';
  906.         i++;
  907.         mb -= 100 * (mb / 100);
  908.         if ((!mb) || (mb < 10))    {    /* take care mb=100 or 101 cases */
  909.             *str++ = '0';
  910.             i++;
  911.         }
  912.     }
  913.     if (mb > 9) {
  914.         *str++ = (mb / 10) + '0';
  915.         mb -= 10 * (mb / 10);
  916.         i++;
  917.     }
  918.     *str++ = mb + '0';
  919.     i++;
  920.  
  921.     if (frac) {
  922.         *str++ = '.';
  923.         *str++ = frac + '0';
  924.         i += 2;
  925.     }
  926.     *str++ = 'M';
  927.     *str++ = 'b';
  928.     i += 2;
  929.     if (flag)     {        /* for the Memory left box */
  930.         for (; i < 8; i++)
  931.             *str++ = ' ';
  932.     }
  933.     *str = '\0';
  934. }
  935.  
  936.  
  937. /*
  938.  * Partitin button number-to-object translation table.
  939.  */
  940.  
  941. int ppart[] = {
  942.     PPART0, PPART1, PPART2, PPART3,
  943.     PPART4, PPART5, PPART6, PPART7,
  944.     PPART8, PPART9
  945. };
  946.  
  947. /*
  948.  * Throw up menu of canned partitions;
  949.  *    Return PPOK on [OK],
  950.  *         PPCN on [CANCEL],
  951.  *         PPEDIT on [EDIT==>],
  952.  *         ERROR on some error.
  953.  *    if `flag' < 0, this is the first time 
  954.  *    putting up the menu.
  955.  */
  956.  
  957. spartmenu()
  958. {
  959.     int i, but, tem;
  960.     char *s, *pnam, pr_id[10];
  961.     char devnames[NAMSIZ];
  962.  
  963.     /* Figure out partition scheme id */
  964.     /*
  965.     figprid(disksiz, pr_id);
  966.     */
  967.     
  968.     if (menuflg < 0) {
  969.         menuflg = 1;
  970.        
  971.         figprid(disksiz, pr_id);
  972.            /*Get all available partition schemes from wincap 'ID' entries*/ 
  973.            wallents(partnames, pr_id);
  974.         if (!*partnames)    {
  975.             setschm(disksiz, partnames);
  976.         } 
  977.         /*
  978.         if (ttscsi)    {
  979.             setschm(disksiz, partnames);
  980.         } else     {
  981.             Get all available partition schemes from wincap 'ID' entries 
  982.             wallents(partnames, pr_id);
  983.         }
  984.         */
  985.     }
  986.  
  987.     for (i = 0, s = partnames; i < 10 && *s; ++i) {
  988.         p[ppart[i]].ob_type = G_BUTTON;
  989.     p[ppart[i]].ob_spec = (long)s;
  990.     p[ppart[i]].ob_state = NORMAL;
  991.     p[ppart[i]].ob_flags = SELECTABLE | RBUTTON;
  992.     while (*s++)
  993.         ;
  994.     }
  995.  
  996.     /* rest of buttons are invisible and untouchable */
  997.     for (; i < 10; ++i) {
  998.         p[ppart[i]].ob_type = G_IBOX;
  999.     p[ppart[i]].ob_spec = 0L;            /* no thickness */
  1000.     p[ppart[i]].ob_state = DISABLED;        /* nobody home */
  1001.     p[ppart[i]].ob_flags = NONE;            /* disabled */
  1002.     }
  1003.  
  1004.     /* clean up rest of the form and throw it up */
  1005.     p[PPOK].ob_state = NORMAL;
  1006.     p[PPCN].ob_state = NORMAL;
  1007.     p[PPEDIT].ob_state = NORMAL;
  1008.     
  1009.     if((but = execform(p)) == PPCN || but == PPEDIT)
  1010.     return;
  1011.  
  1012.     /* search for partition they picked */
  1013.     pnlflg = 0;                /* partition scheme from menu */
  1014.     for (i = 0; i < 10; ++i)
  1015.     if (p[ppart[i]].ob_state & SELECTED)
  1016.         break;
  1017.     if (i >= 10) return but;        /* nothing changed */
  1018.     pnam = p[ppart[i]].ob_spec;
  1019.  
  1020.     /*
  1021.     if (!ttscsi)    {
  1022.         i = wgetent(pnam, pr_id);                ; (floppy access) 
  1023.         if (i != OK) {
  1024.             nopart[NOSCHPOK].ob_state = NORMAL;
  1025.                (nopart[NOSCHPR].ob_spec)->te_ptext = p[ppart[i]].ob_spec;
  1026.             execform(nopart);
  1027.             return ERROR;
  1028.         }
  1029.     }
  1030.     */
  1031.     npart = 4;
  1032.     ext = NO_EXT;        /* set no extended partition */
  1033.     if (headptr > 0)    free(headptr);
  1034.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)        {
  1035.         err(nomemory);
  1036.         if (pinfo > 0)    Mfree(pinfo);
  1037.         return ERROR;
  1038.     }
  1039.     inipart(&pinfo[0], npart);        /* initialized the 'pinfo' */
  1040.     npart = 0;
  1041.     msetpart(pinfo, pnam, disksiz);
  1042.     /*
  1043.     if (ttscsi)        {
  1044.         msetpart(pinfo, pnam, disksiz);
  1045.     } else {
  1046.         for (i = 0; i < 4; ++i)
  1047.             fillpart(i, &pinfo[i]);
  1048.     }
  1049.     */
  1050.     return but;
  1051. }
  1052.  
  1053.  
  1054. /* 
  1055.  * conver the partition number for the dialog box to the string .
  1056.  *
  1057.  */
  1058.  
  1059. stpartnum(num, str)
  1060.  
  1061. int num;
  1062. char *str;
  1063.  
  1064. {
  1065.     int  i = 0, j=0;
  1066.     char tem[20];
  1067.  
  1068.     /* set the partition number header */
  1069.     *str++ = '#';
  1070.     j++;
  1071.     /* conver the integer to ASCII */
  1072.     do    {    /* generate digits in reverse order */
  1073.         tem[i++] = num % 10 + '0';    /* get next digits */
  1074.     } while ((num /= 10) > 0);        /* delete it */
  1075.  
  1076.     for (; i > 0; )    { /* reverse string 'str' in place */
  1077.         *str++ = tem[--i];
  1078.         j++;
  1079.     }
  1080.     for (; j < 4; j++)
  1081.         *str++ = ' ';
  1082.     *str = '\0';
  1083.  
  1084. }
  1085.  
  1086.  
  1087.  
  1088. /*
  1089.  *  Place partition headers at the appropiate sectors.
  1090.  *    Input:
  1091.  *        pdev - physical device partitions belong to.
  1092.  *        part - partition structure containing the partitions'
  1093.  *               information.
  1094.  *    Return:
  1095.  *        OK - if everything is fine.
  1096.  *        ERROR - error occurs when testing header sectors.
  1097.  *    Comments:
  1098.  *        Making sure that the headers occupy consecutive good 
  1099.  *    sectors.  If necessary, sizes of partitions are adjusted to 
  1100.  *    achieve the above.
  1101.  *        If any size adjustment make a partition bigger than
  1102.  *    the maximum size, the partition will be adjusted to the maximum
  1103.  *    size leaving the excessive sectors wasted.
  1104.  */
  1105.  
  1106. spheader(pdev, part)
  1107.  
  1108. int pdev;    /* physical device number */
  1109. PART *part;    /* partition info */
  1110.  
  1111. {
  1112.     /* Maximum sizes for FAT, root directory and header <in sectors> */
  1113.     long  maxdent;        /* max num entries in root dir */
  1114.     long  start;        /* starting sector number of a partition */
  1115.     long  entries, nument();
  1116.     long  movehdr, temstart, moved, psiz;
  1117.     UWORD maxfsiz, maxdsiz, hdrsiz;
  1118.     long currbsiz;        /* size of BSL b4 pheader is executed */
  1119.     int  pno;            /* partition being dealt with */
  1120.     int  done;            /* tell if location of header is found */
  1121.     int  curr;            /* current sector of header being checked */
  1122.     int  ret;            /* return code from testing header sectors */
  1123.     int     spc;            /* sectors per cluster */
  1124.     int  kindfat;       /* 12 bits fat or 16 bits fat */
  1125.     int  step;            /* the index for check the partitions */
  1126.     long bigsect(), nsect;
  1127.     long stbigsect();
  1128.     long temsect, remain;
  1129.     long cell();
  1130.     
  1131.     
  1132.     /* get the BSL ready ofr later */
  1133.     entries = nument(MEDIA);
  1134.     sortbsl(entries);
  1135.     currbsiz = bslsiz;
  1136.  
  1137.     /* Determine actual sizes and starting sectors for all partitions */
  1138.     for (pno = 0; pno < npart; pno++) {
  1139.         
  1140.         /* Partition 0 starts right after root sect.  The rest starts right
  1141.            after its previous partition ???*/
  1142.         if (pno == 0)
  1143.             start = 1 + currbsiz; 
  1144.         else if (pno == 4)
  1145.             start = part[ext].p_st;    /* start in extened partition */
  1146.         else
  1147.             start = part[pno-1].p_st + part[pno-1].p_siz;
  1148.         
  1149.         /* Check if partition exists.  If it doesn't, move on to next one */
  1150.         if ((!(part[pno].p_flg & P_EXISTS)) || (pno == ext)) {
  1151.             part[pno].p_st = start;
  1152.             continue;
  1153.         }
  1154.         if (pno > 3)     {
  1155.             psiz = part[pno].p_siz - ROOTSECT;
  1156.         } else    {
  1157.             psiz = part[pno].p_siz;
  1158.         }
  1159.  
  1160.         /* estimate the bps */
  1161.         /* MAXSECT = 16MB - 8 */
  1162.         bps = cell((psiz-7)*BPS, (long)MAXSECT);
  1163.         /* the real pbs */
  1164.         bps = BPS * n2power((UWORD)cell(bps, (long)BPS));
  1165.         ratio = bps / BPS;
  1166.         nsect = psiz / ratio;
  1167.  
  1168.         /* Detail of calculations in part.c dopart() */
  1169.         /* find max FAT size. FAT16: 16 bits fat; FAT12: 12bits fat */
  1170.         maxfsiz = ((((nsect / SPC) + 2)*2) / bps) + 1;
  1171.         /* find max root dir entries */
  1172.         if (nsect < 0x5000L)    maxdent = NUMEN;
  1173.         else maxdent = nsect / 80;
  1174.         maxdent = (maxdent + (bps/BPDIR -1)) & ~(bps/BPDIR -1);
  1175.         /* find max root dir size */
  1176.         maxdsiz = (maxdent * BPDIR) / bps + 1;
  1177.  
  1178.            if (pno > 3)    {  /* they are extended partitions */
  1179.         /*-------------------------------------------------------*
  1180.          * Biggest possible header for a extended partition <in sectors> 
  1181.          *    =  Root sector + Boot Sector + 2 FATs + Root Dir    
  1182.          *-------------------------------------------------------*/
  1183.          /* convert it back to 512 bps size */
  1184.             hdrsiz = 1 + ratio + ((maxfsiz * 2) + maxdsiz) * ratio;
  1185.         } else
  1186.         /*-------------------------------------------------------*
  1187.          * Biggest possible header for a partition <in sectors>  *
  1188.          *    =  Boot Sector + 2 FATs + Root Dir         *
  1189.          *-------------------------------------------------------*/
  1190.          /* convert it back to 512 bps size */
  1191.             hdrsiz = (1 + (maxfsiz * 2) + maxdsiz) * ratio;
  1192.     
  1193.     /*-----------------------------------------------------------------*
  1194.      * Look for a chunk of sectors starting at "start" (or after, but  *
  1195.      * as close as possible) which is big enough to hold the biggest   *
  1196.      * possible header.                           *
  1197.      *-----------------------------------------------------------------*/
  1198.     done = 0;       /* assume correct location not found yet */
  1199.     moved = 0;
  1200.     while (!done) {
  1201.         /*----------------------------------------------------------*
  1202.          * Find out if header contains any bad sectors by checking    *
  1203.          * range of sectors to be occupied by the header against    *
  1204.          * the BSL.                                                    *
  1205.          *----------------------------------------------------------*/
  1206.         for (curr = 0; curr < hdrsiz; curr++)    {
  1207.             if (srchbsl(start+curr, entries) == YES)
  1208.                 break;
  1209.         }
  1210.         if (curr < hdrsiz)    {    /* bad sector found in header */
  1211.             /* move header to start after the bad sector */
  1212.             moved += curr + 1;
  1213.             start += curr + 1;
  1214.         } else {
  1215.                if ((ret = testhdr(pdev, start, hdrsiz)) < 0)
  1216.                  return ERROR;
  1217.             if (ret)    {    /* some bad sectors found in header */
  1218.                 entries = nument(MEDIA);
  1219.                 sortbsl(entries);
  1220.             } else {        /* all sectors belong ot header are good */
  1221.                 done = 1;
  1222.             }
  1223.         }
  1224.     }
  1225.     
  1226.     if (moved) {    /* header has been moved */
  1227.         /*-------------------------------------------------------*
  1228.          * Expand previous partition (except if the current one  *
  1229.          * is partition 0, then there is no previous partition), *
  1230.          * and enforce maximum partition size on it.         *
  1231.          *-------------------------------------------------------*/
  1232.         if (ratio > 1)    {    /* big sector */
  1233.             start -= moved;
  1234.             moved = stbigsect(moved);
  1235.             start += moved;
  1236.         }
  1237.         if (pno > 0) {
  1238.             if (part[pno-1].p_siz + moved > disksiz)
  1239.                 part[pno-1].p_siz = disksiz;
  1240.             else
  1241.                 part[pno-1].p_siz += moved;
  1242.         }
  1243.             
  1244.         /* Shrink size of current partition */
  1245.         part[pno].p_siz -= moved;
  1246.     } 
  1247.  
  1248.     /* Where current partition should start */
  1249.     part[pno].p_st = start;
  1250.  
  1251.     /* add the waist sectors of big partition to the next partition */
  1252.     /* partition #3 in the pinfo is the last partition */
  1253.     /* partition # npart-1 in the pinfo is the last partition in 
  1254.         the extended partition */
  1255.     if ((pno != 3) && (pno != npart - 1) && 
  1256.                     (part[pno].p_siz >= MB16))        { /* big partition */
  1257.         temsect = part[pno].p_siz;
  1258.         if (pno > 3)    { /* extended big partition */
  1259.            part[pno].p_siz = ROOTSECT + bigsect(part[pno].p_siz-ROOTSECT);
  1260.         } else {    /* prime big partition */
  1261.            part[pno].p_siz = bigsect(part[pno].p_siz);
  1262.         }
  1263.         remain = temsect - part[pno].p_siz;
  1264.         if (remain)    {
  1265.             part[pno+1].p_siz += remain;
  1266.             part[pno+1].p_st -= remain;
  1267.         }
  1268.     }
  1269.  
  1270.   }
  1271.     /* last existing partition has to sacrifice some space for the BSL    */
  1272.     /* and the root sector of device.                    */
  1273.     if ((ext == 3) || ((!(part[2].p_flg & P_EXISTS)) &&
  1274.                         (!(part[3].p_flg & P_EXISTS))))    { 
  1275.         /* the last partition is inside the extended partitions */
  1276.         step = npart;
  1277.         /* the total extended partition should not inculde the bad sector */
  1278.         /* list and root sector */
  1279.         part[ext].p_siz -= (currbsiz + 1);
  1280.     } else {    /* the last partition is in the prime partitions */
  1281.         step = NPARTS;
  1282.     }
  1283.     for (pno = step-1; pno >= 0; pno--) {
  1284.         if (part[pno].p_flg & P_EXISTS) {
  1285.             part[pno].p_siz -= (currbsiz + 1);
  1286.             break;
  1287.         }
  1288.     }
  1289.  
  1290.     /* have to move partitions (existing or not) which start
  1291.        right after the BSL if BSL has been expanded  */
  1292.     if (bslsiz > currbsiz) {        /* BSL becomes bigger? */
  1293.         for (pno = 0; pno < NPARTS; pno++) {
  1294.             if (part[pno].p_st == currbsiz + 1) {
  1295.                 part[pno].p_st = bslsiz + 1;
  1296.                 if (part[pno].p_siz > 0)
  1297.                     part[pno].p_siz -= (bslsiz - currbsiz);
  1298.             }
  1299.         }
  1300.     }
  1301.   return OK;    /* everything is fine */
  1302. }
  1303.  
  1304.  
  1305. long stbigsect(amt)
  1306. long amt;
  1307.  
  1308. {
  1309.     long numsect;
  1310.     if (ratio > 1)    {
  1311.         numsect = (amt % ratio) ? (amt / ratio + 1) : (amt /ratio);
  1312.         return(numsect * ratio);
  1313.     } else {
  1314.         return(amt);
  1315.     }
  1316. }
  1317.  
  1318.  
  1319. long bigsect(amt)
  1320. long amt;
  1321.  
  1322. {
  1323.     if (ratio > 1)    {
  1324.         return((amt / ratio) * ratio);
  1325.     } else {
  1326.         return(amt);
  1327.     }
  1328. }
  1329.  
  1330. /* 
  1331.  * Given size of a hard disk, figure out
  1332.  * the partition scheme ID to look for.
  1333.  * ID is 2 or more characters long.
  1334.  */
  1335. figprid(hdsiz, pr_id)
  1336. long hdsiz;
  1337. char pr_id[];
  1338. {
  1339.     UWORD mega, over;
  1340.     char numbuf[10];
  1341.     
  1342.     /* Round off disk size in megabytes */    
  1343.     mega = hdsiz / MEGABYTE;
  1344.     
  1345.     /* Round off disk size to nearest 10Mb */
  1346.     /*
  1347.     over = mega % 10;
  1348.     if (over >= 5)
  1349.        mega += (10 - over);
  1350.     else
  1351.        mega -= over;
  1352.     */
  1353.     itoa(mega, numbuf);
  1354.     strcpy(pr_id, numbuf);
  1355. }
  1356.  
  1357.  
  1358.  
  1359. /*
  1360.  * Check if partition scheme selected is _legal_.
  1361.  * _Legal_ means the scheme does not map to non-existing memory.
  1362.  * If it is not, prompt user to pick partition again.
  1363.  *    Input:
  1364.  *        pdev - physical unit we're trying to partition.
  1365.  *        xpinfo - partition block user selected.
  1366.  *    Return:
  1367.  *        OK - if partition scheme is _legal_.
  1368.  *        ERROR - if partition scheme is illegal.
  1369.  */
  1370.  
  1371. chkpart(pdev, xpinfo)
  1372. int pdev;
  1373. PART *xpinfo;
  1374. {
  1375.     char bs[512];
  1376.     SECTOR totsiz;
  1377.     int     i, ret;
  1378.     
  1379.     
  1380.     /* Get partition information from disk's root block.*/
  1381.     if ((ret = getroot(pdev, bs, (SECTOR)0)) != 0) {
  1382.         if (tsterr(ret) != OK)
  1383.             err(rootread);
  1384.         return (1);        /* return error but it is not a size too big */
  1385.     }
  1386.  
  1387.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  1388.     totsiz = 0;
  1389.     for (i = 0; i < NPARTS; i++) {
  1390.         if (xpinfo[i].p_flg & P_EXISTS)    {
  1391.             totsiz += xpinfo[i].p_siz;
  1392.         }
  1393.         if (totsiz > disksiz)
  1394.             return ERROR;     /* size too big */
  1395.     }
  1396.     return OK;
  1397. }
  1398.     
  1399.  
  1400.  
  1401. /*
  1402.  *  Make sure that sectors assigned to a partition header are GOOD.
  1403.  *    Input:
  1404.  *        pdev - physical device number partition belongs to.
  1405.  *        start - starting (physical) sector number header starts.
  1406.  *        hdrsiz - number of sectors header occupies.
  1407.  *    Return:
  1408.  *        OK - if all sectors in header are good.
  1409.  *        positive number - if entries are added to BSL in testing
  1410.  *                    the header.
  1411.  *        ERROR - if somewhere the process went wrong.
  1412.  *    Comments:
  1413.  *        Bad Sectors found are added as USER bad sectors.  
  1414.  *    First, because we can't expand the VENDOR list while preserving
  1415.  *    the USER list.  Second, this is ok, because even if the USER list
  1416.  *    is full, the user should reformat the disk anyway, and if the
  1417.  *    sector is REALLY bad, it would be discovered again then.
  1418.  */
  1419. testhdr(pdev, start, hdrsiz)
  1420. int pdev;
  1421. SECTOR start;
  1422. UWORD hdrsiz;
  1423. {
  1424.     long size, pattern;
  1425.     extern long longrandom();
  1426.     extern int tformat;        /* flag */
  1427.     UWORD sectcnt, list;
  1428.     int ret, nbad, clean=1;
  1429.     SECTOR sect;
  1430.     char *buf;        /* buffer with test data */
  1431.     
  1432.     size = (long)hdrsiz << 9;
  1433.     if ((buf = (char *)Malloc(size)) <= 0) {
  1434.         err(nomemory);
  1435.         ret = NOMEM;
  1436.         goto wrapup;
  1437.     }
  1438.         
  1439.     /*
  1440.      * Try to write to header's sectors.
  1441.      */
  1442.     pattern = longrandom();
  1443.     fillbuf(buf, size, pattern);
  1444.     sectcnt = hdrsiz;
  1445.     sect = start;
  1446.     nbad = 0;
  1447.  
  1448.     if ((ret = wrsects(pdev, sectcnt, buf, sect)) != 0) {
  1449.         if (tsterr(ret) == OK) {
  1450.             ret = ERROR;
  1451.             goto wrapup;
  1452.         }
  1453.         clean = 0;
  1454.         
  1455.         while (sectcnt) {    /* find out which sector is indeed bad */
  1456.         if ((ret = wrsects(pdev, 1, 0L, sect)) != 0) {
  1457.             if (tsterr(ret) == OK) {
  1458.                 ret = ERROR;
  1459.                 goto wrapup;
  1460.             }
  1461.             if (sect < 3) {
  1462.                 ret = err(rsrvbad);
  1463.                 goto wrapup;
  1464.             }
  1465.                     
  1466.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1467.                     
  1468.                 /* buffer is filled up, have to add bad sectors
  1469.                    found so far to the BSL before continuing.   */
  1470.                 if (nbad == WARNBADSECTS) {
  1471.                     /* Decide which list to add to */
  1472.                     if (tformat == TRUE)
  1473.                         list = VENDOR;
  1474.                     else list = USER;
  1475.                        if ((ret=addbsl(pdev, list, nbad)) < 0) {
  1476.                            ret = err(rsrvbad);
  1477.                            goto wrapup;
  1478.                        }
  1479.                        nbad = 0;    /* start counting again */
  1480.                 }
  1481.             }
  1482.             sect++;
  1483.             sectcnt--;
  1484.         }
  1485.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1486.             /* Decide which list to add to */
  1487.             if (tformat == TRUE)
  1488.                 list = VENDOR;
  1489.             else list = USER;
  1490.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1491.                 ret = ERROR;
  1492.                 goto wrapup; 
  1493.             }
  1494.             nbad = 0;
  1495.         }
  1496.     }
  1497.     
  1498.     /* Try to read header's sectors */
  1499.     sectcnt = hdrsiz;
  1500.     sect = start;
  1501.     nbad = 0;
  1502.     if ((ret = rdsects(pdev, sectcnt, buf, sect)) != 0) {
  1503.         if (tsterr(ret) == OK) {
  1504.             ret = ERROR;
  1505.             goto wrapup;
  1506.         }
  1507.         clean = 0;
  1508.         
  1509.         while (sectcnt) {    /* find out which sector is indeed bad */
  1510.         if ((ret = rdsects(pdev, 1, buf, sect)) != 0) {
  1511.             if (tsterr(ret) == OK) {
  1512.                 ret = ERROR;
  1513.                 goto wrapup;
  1514.             }
  1515.                 if (sect < 3) {
  1516.             ret = err(rsrvbad);
  1517.             goto wrapup;
  1518.         }
  1519.                     
  1520.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1521.                     
  1522.                 /* buffer is filled up, have to add bad sectors
  1523.                    found so far to the BSL before continuing.   */
  1524.                 if (nbad == WARNBADSECTS) {
  1525.                     /* Decide which list to add to */
  1526.                     if (tformat == TRUE)
  1527.                     list = VENDOR;
  1528.                     else list = USER;
  1529.                        if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1530.                            ret = ERROR;
  1531.                            goto wrapup;
  1532.                        }
  1533.                        nbad = 0;    /* start counting again */
  1534.                 }
  1535.             }
  1536.             sect++;
  1537.             sectcnt--;
  1538.         }
  1539.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1540.             /* Decide which list to add to */
  1541.             if (tformat == TRUE)
  1542.                 list = VENDOR;
  1543.             else list = USER;
  1544.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1545.                 ret = ERROR;
  1546.                 goto wrapup; 
  1547.             }
  1548.             nbad = 0;
  1549.         }
  1550.     }
  1551. wrapup:
  1552.     if (buf > 0)  Mfree((long)buf);
  1553.     
  1554.     if (ret < 0)
  1555.         return ret;
  1556.         
  1557.     if (!clean) {
  1558.         /* write new bsl back to disk */
  1559.         if (wrbsl(pdev) != OK) {
  1560.             return ERROR;
  1561.         }
  1562.         return 1;
  1563.     }
  1564.         
  1565.     return OK;
  1566. }
  1567.  
  1568. long
  1569. cell(top, bottom)
  1570. long top;
  1571. long bottom;
  1572. {
  1573.     return ((top % bottom) ? (top / bottom + 1) :
  1574.             (top / bottom));
  1575. }
  1576.  
  1577.  
  1578. n2power(num)
  1579. UWORD num;
  1580. {
  1581.     UWORD power = 1;
  1582.  
  1583.     for (;;)    {
  1584.         if (num <= power )    {
  1585.             return (power);
  1586.         }
  1587.         power <<= 1;
  1588.     } 
  1589. }
  1590.  
  1591.  
  1592. DPART
  1593. *addr(index)
  1594. int index;
  1595. {
  1596.     DPART *temptr;
  1597.     int i;
  1598.  
  1599.     if (index < 0)    return nill;
  1600.     if (!index) return (headptr);
  1601.     temptr = headptr->next;
  1602.     for (i = 1; i < index; i++)    {
  1603.         temptr = temptr->next;
  1604.     }
  1605.     return (temptr);
  1606. }
  1607.  
  1608. DPART
  1609. *last()
  1610. {
  1611.     DPART *temptr;
  1612.     int i;
  1613.  
  1614.     if (!headptr) return (headptr);
  1615.     temptr = headptr;
  1616.     while (temptr->next)
  1617.         temptr = temptr->next;
  1618.     return (temptr);
  1619. }
  1620.  
  1621.  
  1622.  
  1623. creatmem(num)
  1624. int num;        /* number of block to malloc */
  1625. {
  1626.     DPART *temptr;
  1627.     DPART *last();
  1628.     int i;
  1629.  
  1630.     if (headptr == nill)    {
  1631.         if ((headptr = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {;
  1632.             err(nomemory);
  1633.             if (headptr > 0) free(headptr);
  1634.             return ERROR;
  1635.         }
  1636.         headptr->next = nill;
  1637.         headptr->siz = 0L;
  1638.         headptr->flg = 0;
  1639.     }
  1640.     temptr = last();
  1641.     for (i = 0; i < num; i++)    {
  1642.         if ((temptr->next = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {
  1643.             err(nomemory);
  1644.             if (headptr > 0) free(headptr);
  1645.             return ERROR;
  1646.  
  1647.         }
  1648.         temptr = temptr->next;
  1649.         temptr->next = nill;
  1650.         temptr->siz = 0L;
  1651.         temptr->flg = 0;
  1652.     }
  1653. }
  1654.  
  1655.  
  1656. dpart2part(extpart)
  1657. int extpart ;    /* set the extended pointer in the 4th place */
  1658. {
  1659.     int i;
  1660.     DPART *temptr;
  1661.  
  1662.     /* if npart > 4; need 1 more space for the extended partition */
  1663.     if (npart > 4)    {
  1664.         i = npart - extend;    /* the index that extended form the end of part. */
  1665.         npart += NPARTS-extpart;    /* add 1 extra space for the extended */
  1666.                                     /* partition and 0 or 1 or 2 space for */
  1667.                                     /* the prime partition in the root */
  1668.         extend = npart - i;    /* move 2 space for 2 prime partition in the root */
  1669.     } else {                /* set the extpart to -1 */
  1670.         npart = 4;
  1671.         extpart = -1;
  1672.         ext = NO_EXT;
  1673.     }
  1674.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)    {
  1675.         err(nomemory);
  1676.         if (pinfo > 0) Mfree(pinfo);
  1677.         free(headptr);
  1678.         return ERROR;
  1679.     }
  1680.     inipart(pinfo, npart);  
  1681.     temptr = headptr;
  1682.     for (i = 0; i < npart; i++)        {
  1683.         if (!(temptr->flg & P_EXISTS)) {
  1684.             if (sizleft > 0) {
  1685.                 if (temptr->siz > sizleft) {
  1686.                     pinfo[i].p_siz = sizleft;
  1687.                 }
  1688.                 sizleft -= temptr->siz;
  1689.             }
  1690.         } else {
  1691.             pinfo[i].p_siz = temptr->siz;
  1692.             pinfo[i].p_flg = P_EXISTS;
  1693.             if (i == extpart)    {
  1694.                 pinfo[i].p_id[0] = 'X';
  1695.                 pinfo[i].p_id[1] = 'G';
  1696.                 pinfo[i].p_id[2] = 'M';
  1697.                 pinfo[i].p_siz = 0L;
  1698.             } else if ((extpart == 1) && ((i == 2) || (i==3)))    {
  1699.                 pinfo[i].p_flg = 0;
  1700.                 pinfo[i].p_siz = 0L;
  1701.             } else if ((extpart == 2) && (i==3))    {
  1702.                 pinfo[i].p_flg = 0;
  1703.                 pinfo[i].p_siz = 0L;
  1704.             } else if (temptr->siz < MB16)    {
  1705.                 pinfo[i].p_id[0] = 'G';
  1706.                 pinfo[i].p_id[1] = 'E';
  1707.                 pinfo[i].p_id[2] = 'M';
  1708.                 temptr = temptr->next;
  1709.             } else {
  1710.                 pinfo[i].p_id[0] = 'B';
  1711.                 pinfo[i].p_id[1] = 'G';
  1712.                 pinfo[i].p_id[2] = 'M';
  1713.                 temptr = temptr->next;
  1714.             }
  1715.         }
  1716.     }
  1717.     free(headptr);
  1718.     if (extpart != NO_EXT)    {
  1719.         asmpart(extpart);
  1720.     }
  1721.     return OK;
  1722. }
  1723.  
  1724.  
  1725. asmpart(extpart)
  1726. int extpart ;    /* the extended partition pointer */
  1727. {
  1728.     int i;
  1729.  
  1730.     /* # of extened partition to add up */
  1731.     for (i = 4; i < extend; i++)        {
  1732.         pinfo[extpart].p_siz += pinfo[i].p_siz;
  1733.     }
  1734.     if (extpart == 3)    {
  1735.         return OK;        /* done */
  1736.     } else     {
  1737.         /* put the last (npart-extend-1) partitions to */
  1738.         /* the 3rd or 4th place as prime partitions */
  1739.         i = extend;
  1740.         if (i < npart)    {
  1741.             pinfo[extpart+1].p_siz = pinfo[i].p_siz;
  1742.             pinfo[extpart+1].p_flg = P_EXISTS;
  1743.             if (pinfo[extpart+1].p_siz < MB16)    {
  1744.                 pinfo[extpart+1].p_id[0] = 'G';
  1745.                 pinfo[extpart+1].p_id[1] = 'E';
  1746.                 pinfo[extpart+1].p_id[2] = 'M';
  1747.             } else {
  1748.                 pinfo[extpart+1].p_id[0] = 'B';
  1749.                 pinfo[extpart+1].p_id[1] = 'G';
  1750.                 pinfo[extpart+1].p_id[2] = 'M';
  1751.             }
  1752.             pinfo[i].p_flg = 0;
  1753.             pinfo[i].p_siz = 0L;
  1754.             pinfo[i].p_id[0] = '0';
  1755.             pinfo[i].p_id[1] = '0';
  1756.             pinfo[i].p_id[2] = '0';
  1757.             npart--;
  1758.         } 
  1759.         if (i++ < npart)    {
  1760.             pinfo[extpart+2].p_siz = pinfo[i].p_siz;
  1761.             pinfo[extpart+2].p_flg = P_EXISTS;
  1762.             if (pinfo[extpart+2].p_siz < MB16)    {
  1763.                 pinfo[extpart+2].p_id[0] = 'G';
  1764.                 pinfo[extpart+2].p_id[1] = 'E';
  1765.                 pinfo[extpart+2].p_id[2] = 'M';
  1766.             } else {
  1767.                 pinfo[extpart+2].p_id[0] = 'B';
  1768.                 pinfo[extpart+2].p_id[1] = 'G';
  1769.                 pinfo[extpart+2].p_id[2] = 'M';
  1770.             }
  1771.             pinfo[i].p_flg = 0;
  1772.             pinfo[i].p_siz = 0L;
  1773.             pinfo[i].p_id[0] = '0';
  1774.             pinfo[i].p_id[1] = '0';
  1775.             pinfo[i].p_id[2] = '0';
  1776.             npart--;
  1777.         }
  1778.     }
  1779. }
  1780.  
  1781.  
  1782. part2dpart(numpart)
  1783. int numpart;
  1784. {
  1785.  
  1786.     int i;
  1787.     DPART *temptr;
  1788.  
  1789.     headptr = nill;
  1790.     if (creatmem(numpart) == ERROR) {
  1791.         return ERROR;
  1792.     }
  1793.     temptr = headptr;
  1794.     for (i = 0; i < numpart; i++) {
  1795.         if (pinfo[i].p_flg & P_EXISTS)    {
  1796.             temptr->siz = pinfo[i].p_siz;
  1797.             temptr->flg = P_EXISTS;
  1798.         } 
  1799.         temptr = temptr->next;
  1800.     }
  1801. }
  1802.