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 / HDX500 / STEPART.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  45.5 KB  |  1,792 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 "error.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.                 objc_draw(scrpnl, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  487.                 break;
  488.  
  489.     case SEP0SIZ:xrun = septoggle(0, scrpnl);    break;
  490.     case SEP0UP:    sepadj(MEGABYTE, 0, scrpnl);    break;
  491.     case SEP0DN:    sepadj(-MEGABYTE, 0, scrpnl);    break;
  492.  
  493.     case SEP1SIZ:xrun = septoggle(1, scrpnl);    break;
  494.     case SEP1UP:    sepadj(MEGABYTE, 1, scrpnl);    break;
  495.     case SEP1DN:    sepadj(-MEGABYTE, 1, scrpnl);    break;
  496.  
  497.     case SEP2SIZ:xrun = septoggle(2, scrpnl);    break;
  498.     case SEP2UP:    sepadj(MEGABYTE, 2, scrpnl);    break;
  499.     case SEP2DN:    sepadj(-MEGABYTE, 2, scrpnl);    break;
  500.  
  501.     case SEP3SIZ:xrun = septoggle(3, scrpnl);    break;
  502.     case SEP3UP:    sepadj(MEGABYTE, 3, scrpnl);    break;
  503.     case SEP3DN:    sepadj(-MEGABYTE, 3, scrpnl);    break;
  504.       }
  505.   }
  506.  
  507.  
  508.     /*
  509.      * Draw shrinking box and cleanup the screen;
  510.      * return thing that caused our exit.
  511.      */
  512.     if (!along)    {
  513.         erasemsg();
  514.         BEE_MOUSE;
  515.     }
  516.     return but;
  517. }
  518.  
  519.  
  520.  
  521.  
  522. /* 
  523.  * conver the partition number for the dialog box to the string .
  524.  *
  525.  */
  526.  
  527. calextnum(stnum, tonum, str)
  528.  
  529. int stnum,tonum;
  530. char *str;
  531.  
  532. {
  533.     int  i = 0;
  534.     int addspace = 0;
  535.     char tem[10];
  536.  
  537.     /* set the partition number header */
  538.     *str++ = 'f';
  539.     *str++ = 'r';
  540.     *str++ = 'o';
  541.     *str++ = 'm';
  542.     *str++ = ' ';
  543.     *str++ = '#';
  544.     *str++ = stnum % 10 + '0';
  545.     *str++ = ' ';
  546.     *str++ = 't';
  547.     *str++ = 'o';
  548.     *str++ = ' ';
  549.     *str++ = '#';
  550.     /* conver the integer to ASCII */
  551.     do    {    /* generate digits in reverse order */
  552.         tem[i++] = tonum % 10 + '0';    /* get next digits */
  553.     } while ((tonum /= 10) > 0);        /* delete it */
  554.  
  555.     if (i == 1)    {
  556.         addspace = 1;
  557.     }
  558.     for (; i > 0; )    { /* reverse string 'str' in place */
  559.         *str++ = tem[--i];
  560.     }
  561.     if (addspace)    *str++ = ' ';
  562.        *str = '\0';
  563. }
  564.  
  565.  
  566. sdoscrupdn(roll)
  567. int roll;
  568.  
  569. {
  570.      int gr_mkmx, gr_mkmy;
  571.     int gr_mkmstate, gr_mkkstate;
  572.     int barht, barx, bary;
  573.     int eptx, eptht;
  574.  
  575.     along = 1;
  576.     barht = scrpnl[SCRBAR].ob_height;
  577.     eptht = scrpnl[SCREPT].ob_height;
  578.     graf_mkstate(&gr_mkmx, &gr_mkmy, &gr_mkmstate, &gr_mkkstate);
  579.     objc_offset(scrpnl, SCREPT, &eptx, &epty);
  580.     objc_offset(scrpnl, SCRBAR, &barx, &bary);
  581.     /* check which part of bar was clicked */
  582.     if (gr_mkmy > (epty+eptht))    {    /* low part of bar was clicked */
  583.         if (roll == ROLL4)    {
  584.             if ((eptht > (bary+barht-epty-eptht)) || (lowlim == 20))    {
  585.                 scrpnl[SCREPT].ob_y = barht - eptht;
  586.             } else {
  587.                 scrpnl[SCREPT].ob_y += eptht;
  588.             }
  589.             lowlim = ((24-lowlim) < 4) ? (24) : (lowlim+4); 
  590.             if ((lowlim + 4) > uplim) uplim += 4;
  591.             if (uplim > npart)    {
  592.                 if (creatmem(ROLL4) == ERROR)    {
  593.                     return ERROR;
  594.                 }
  595.             }
  596.         } else if (lowlim == 24)    { /* the empty bar is on the bottom */
  597.             return OK;
  598.         } else {
  599.             if ((eptht > ((bary+barht-epty-eptht) * 4)) || (lowlim == 23))    {
  600.                 scrpnl[SCREPT].ob_y = barht - eptht;
  601.             } else {
  602.                 scrpnl[SCREPT].ob_y += eptht / 4;
  603.             }
  604.             lowlim++;
  605.             if ((lowlim + 4) > uplim)      uplim++;
  606.             if (uplim > npart)    {
  607.                 if (creatmem(ROLL4) == ERROR)    {
  608.                     return ERROR;
  609.                 }
  610.             }
  611.         }
  612.     } else if (gr_mkmy < epty)    {    /* upper part of bar was clicked */
  613.         if (roll == ROLL4)    {
  614.             if ((eptht > (epty - bary)) || (lowlim <= 4))    {
  615.                 scrpnl[SCREPT].ob_y = 0;
  616.                 lowlim = 0;
  617.             } else {
  618.                 scrpnl[SCREPT].ob_y -= eptht;
  619.                 lowlim -= 4;
  620.             }
  621.         } else {
  622.             if ((eptht > ((epty - bary) * 4)) || (lowlim == 1))    {
  623.                 scrpnl[SCREPT].ob_y = 0;
  624.             } else {
  625.                 scrpnl[SCREPT].ob_y -= eptht / 4;
  626.             }
  627.             if (lowlim)     {
  628.                 lowlim--;
  629.             }
  630.         }
  631.     }
  632.     objc_draw(scrpnl,SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  633. }
  634.  
  635.  
  636. #define WHITEBAR 24        /* when the white bar on the bottom, the */
  637.                         /* 'lowlim' will equal to 24 */
  638. sdoslidebox(tree)
  639.  
  640. OBJECT *tree;
  641.  
  642. {
  643.     int gr_wreturn, eptatmax;
  644.     int numofmem;            /*   # of memories to be allocated */
  645.  
  646.     along = 1;
  647.     eptatmax = tree[SCRBAR].ob_height - tree[SCREPT].ob_height;
  648.     gr_wreturn = graf_slidebox(tree, SCRBAR, SCREPT, 1);
  649.     lowlim = (WHITEBAR * gr_wreturn) / 1000;
  650.     if ((lowlim >= uplim) || ((lowlim + 4) > uplim))     {
  651.         uplim = lowlim + 4;
  652.         if (uplim > npart)    {
  653.             numofmem = uplim - npart;
  654.             if (creatmem(numofmem) == ERROR)    {
  655.                 return ERROR;
  656.             }
  657.         }
  658.     }
  659.     /*
  660.     tree[SCREPT].ob_y = (eptatmax * gr_wreturn) / 1000;
  661.     */
  662.     tree[SCREPT].ob_y = (eptatmax * lowlim ) / 24;
  663.     objc_draw(tree, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  664. }
  665.  
  666.  
  667.  
  668. /*
  669.  * Toggle partition in/out of existence.
  670.  */
  671. septoggle(n, pnl)
  672. int n;
  673. OBJECT *pnl;
  674. {
  675.     int i; 
  676.     DPART *pinfo, *ppinfo, *npinfo, *addr();
  677.     /*
  678.      * Toggle existance flag,
  679.      * enforce minimum partition size.
  680.      */
  681.     i = n + lowlim;
  682.     pinfo = addr(i);    /* return the structure pointer */
  683.     ppinfo = addr(i-1);    /* return the previous structure pointer */
  684.     npinfo = addr(i+1);    /* return the next structure pointer */
  685.     if ((!(pinfo->flg & P_EXISTS)) && (pinfo->siz) && (ppinfo)
  686.                             && (ppinfo->flg & P_EXISTS)){
  687.         if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  688.         pinfo->flg = P_EXISTS;
  689.         sepadj(0L, n, pnl);
  690.     } else if (((pinfo->flg ^= P_EXISTS) & P_EXISTS) 
  691.           && !pinfo->siz) {
  692.         /* make extended partition continue */
  693.         if (!i || ((ppinfo) && (ppinfo->flg & P_EXISTS)))        {
  694.             if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  695.             sepadj(MEGABYTE, n, pnl);
  696.         } else {
  697.             sepadj(0L, n, pnl);
  698.         }
  699.     } else if ((!lowlim) && (!i)&&(!(npinfo->flg & P_EXISTS)))    {
  700.         sepadj(0L, n, pnl);
  701.     } else if ((!lowlim) && (!i)&&(pinfo->flg & P_EXISTS))    {
  702.         sepadj(0L, n, pnl);
  703.     } else {             /* do nothing, turn it back to the initial state */
  704.         pinfo->flg ^= P_EXISTS;
  705.         if ((pinfo->flg & P_EXISTS) && (!(npinfo->flg & P_EXISTS))) {
  706.               pinfo->flg ^= P_EXISTS;
  707.             sepadj(0L, n, pnl);
  708.         }
  709.     }
  710.     sepadj(0L, -1, pnl);            /* update #left field */
  711.     return YES;
  712. }
  713.     
  714.  
  715. /*
  716.  * Adjust partition `pno' size by `amt';
  717.  * if `pno' is -1, just recompute and update disk space left indicator.
  718.  *
  719.  * A partition of size zero is disabled.
  720.  */
  721.  
  722. #define HALFMEGA 1024L
  723.  
  724. sepadj(amt, pno, pnl)
  725. long amt;
  726. int pno;
  727. OBJECT *pnl;
  728. {
  729.     int i;
  730.     long siz;
  731.     long sizhas;     /* disk size left in sectors */
  732.     long totsiz = 0;
  733.     DPART *pinfo, *npinfo, *addr();
  734.  
  735.     if (pno < 0) 
  736.         goto fixleft;
  737.     pno += lowlim;
  738.  
  739.     pinfo = headptr;
  740.     /* compute total used */
  741.     while (pinfo->flg & P_EXISTS)    {
  742.             totsiz += pinfo->siz;
  743.             pinfo = pinfo->next;
  744.     }
  745.     pinfo = addr(pno);
  746.     npinfo = addr(pno+1);
  747.     sizhas = disksiz;
  748.  
  749.     /*
  750.      * If total partition size exceeds the disk's
  751.      * capacity, reduce `amt' accordingly.
  752.      */
  753.     if (amt >= 0 && totsiz + amt > sizhas)
  754.     amt = sizhas - totsiz;
  755.  
  756.     if (amt > 0) {
  757.     /*
  758.      * Enforce maximum partition size.
  759.      */
  760.     siz = sizhas - totsiz;            /* siz = #free */
  761.     if (amt > siz) amt = siz;        /* ensure amt <= siz */
  762.     if (pinfo->siz + amt > sizhas)    /* ensure partition not */
  763.         amt = sizhas - pinfo->siz;    /* too big */
  764.  
  765.     /* check the partition size that can't over 256Mb (8K bytes per sect) */
  766.     /* for the reason of hardware                                           */
  767.     if ((pinfo->siz + amt) > 256 * 2048)    {
  768.         form_alert(1, maxpsize);
  769.         return OK;
  770.     }
  771.     pinfo->siz += amt;        /* bump partition size */
  772.     pinfo->flg = P_EXISTS;
  773.     } else if (amt < 0) {
  774.     amt = -amt;
  775.     if (pinfo->siz > amt) {        /* reduce partition size */
  776.         pinfo->siz -= amt;
  777.         if ((pinfo->siz < HALFMEGA) && (npinfo->flg & P_EXISTS))
  778.             pinfo->siz = amt;
  779.     } else if ((pinfo->siz <= amt) &&
  780.                 (!(npinfo->flg & P_EXISTS)))    {
  781.         /* reduce partition size */
  782.         pinfo->siz = 0L;
  783.     } 
  784.   }
  785.  
  786.     /*
  787.      * Enforce minimum partition size of half mega byte 
  788.      */
  789.     if (pinfo->siz < HALFMEGA)
  790.     pinfo->siz = 0L;
  791.  
  792.     /*
  793.      * Disable partitions of zero size
  794.      */
  795.     if (!pinfo->siz)    {
  796.         pinfo->flg &= ~P_EXISTS;
  797.     }
  798.  
  799.     /*
  800.      * Redraw the thing;
  801.      * if partition is disabled, shadow it and disable UP/DOWN buttons;
  802.      * otherwise setup the buttons, setup size string, and so on...
  803.      */
  804.     pno -= lowlim;
  805.     if (!(pinfo->flg & P_EXISTS)) {
  806.         pnl[objsizs[pno]].ob_spec = "Unused";
  807.         pnl[objsizs[pno]].ob_state = NORMAL;
  808.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  809.  
  810.         pnl[objups[pno]].ob_state = DISABLED;
  811.         pnl[objups[pno]].ob_flags = NONE;
  812.  
  813.         pnl[objdns[pno]].ob_state = DISABLED;
  814.         pnl[objdns[pno]].ob_flags = NONE;
  815.     } else {
  816.         stuffamt(pinfo->siz, sizstr[pno], 0);
  817.         pnl[objsizs[pno]].ob_spec = sizstr[pno];
  818.         pnl[objsizs[pno]].ob_state = NORMAL;
  819.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  820.  
  821.         pnl[objups[pno]].ob_state = NORMAL;
  822.         pnl[objups[pno]].ob_flags = TOUCHEXIT;
  823.  
  824.         pnl[objdns[pno]].ob_state = NORMAL;
  825.         pnl[objdns[pno]].ob_flags = TOUCHEXIT;
  826.     }
  827.  
  828.     /* set the partition numbers in the dialog box */
  829.     stpartnum(lowlim+pno+1, numstr[pno]);
  830.     (pnl[objnums[pno]].ob_spec)->te_ptext = numstr[pno];
  831.  
  832.     if (ok2draw) {
  833.         objc_draw(pnl, objsizs[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  834.         objc_draw(pnl, objups[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  835.         objc_draw(pnl, objdns[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  836.         objc_draw(pnl, objnums[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  837.     }
  838.  
  839.  
  840. fixleft:
  841.  
  842.     /*
  843.      * Compute and redraw 'space left' indicator and
  844.      * calculat the total partitions number */
  845.  
  846.        sizleft = disksiz;
  847.     pinfo = headptr;
  848.     tolpart = 0;
  849.     while ((pinfo->flg & P_EXISTS) && (pinfo->siz > 0))     {
  850.             sizleft -= pinfo->siz;
  851.             tolpart++;  
  852.             pinfo = pinfo->next;
  853.     }
  854.     npart = tolpart;
  855.        stuffamt(sizleft, sizstr[4], 1);
  856.        (pnl[SEPLEFT].ob_spec)->te_ptext = sizstr[4];
  857.  
  858.     totalpart(tolpart, sizstr[5]);
  859.        (pnl[STOLPART].ob_spec)->te_ptext = sizstr[5];
  860.  
  861.     if (ok2draw)    {
  862.         objc_draw(pnl, SEPLEFT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  863.         objc_draw(pnl, STOLPART, MAX_DEPTH, 0, 0, wdesk, hdesk);
  864.     }
  865. }
  866.  
  867. /*
  868.  * Atoi `amt', #blocks, into 999.9Mb (or something like that);
  869.  * assumes enough space in `str'.
  870.  */
  871. stuffamt(amt, str, flag)
  872. long amt;
  873. char *str;
  874. int flag;            /* 1: for Memory left box. */
  875. {
  876.     long mb, frac;
  877.     int i=0;
  878.  
  879.     mb = amt / 2048;
  880.     frac = amt - (2048 * mb);
  881.     if (frac / 16)
  882.         frac /= 205;        /* that's MEGABYTE / 10 */
  883.     else frac = 0;
  884.     if (frac < 0) frac = -frac;
  885.     if (mb < 0) mb = frac = 0;
  886.  
  887.     if (mb > 999)     {
  888.         *str++ = (mb / 1000) + '0';
  889.         i++;
  890.         mb -= 1000 * (mb / 1000);
  891.         if ((!mb) || (mb < 10))    { /* take care mb=1000 or 1001 case */
  892.             *str++ = '0';
  893.             *str++ = '0';
  894.             i += 2;
  895.         } else if (mb < 100)    { /* take care mb=1099 case */
  896.             *str++ = '0';
  897.             i++;
  898.         }
  899.     }
  900.     if (mb > 99) {
  901.         *str++ = (mb / 100) + '0';
  902.         i++;
  903.         mb -= 100 * (mb / 100);
  904.         if ((!mb) || (mb < 10))    {    /* take care mb=100 or 101 cases */
  905.             *str++ = '0';
  906.             i++;
  907.         }
  908.     }
  909.     if (mb > 9) {
  910.         *str++ = (mb / 10) + '0';
  911.         mb -= 10 * (mb / 10);
  912.         i++;
  913.     }
  914.     *str++ = mb + '0';
  915.     i++;
  916.  
  917.     if (frac) {
  918.         *str++ = '.';
  919.         *str++ = frac + '0';
  920.         i += 2;
  921.     }
  922.     *str++ = 'M';
  923.     *str++ = 'b';
  924.     i += 2;
  925.     if (flag)     {        /* for the Memory left box */
  926.         for (; i < 8; i++)
  927.             *str++ = ' ';
  928.     }
  929.     *str = '\0';
  930. }
  931.  
  932.  
  933. /*
  934.  * Partitin button number-to-object translation table.
  935.  */
  936.  
  937. int ppart[] = {
  938.     PPART0, PPART1, PPART2, PPART3,
  939.     PPART4, PPART5, PPART6, PPART7,
  940.     PPART8, PPART9
  941. };
  942.  
  943. /*
  944.  * Throw up menu of canned partitions;
  945.  *    Return PPOK on [OK],
  946.  *         PPCN on [CANCEL],
  947.  *         PPEDIT on [EDIT==>],
  948.  *         ERROR on some error.
  949.  *    if `flag' < 0, this is the first time 
  950.  *    putting up the menu.
  951.  */
  952.  
  953. spartmenu()
  954. {
  955.     int i, but, tem;
  956.     char *s, *pnam, pr_id[10];
  957.  
  958.     /* Figure out partition scheme id */
  959.     /*
  960.     figprid(disksiz, pr_id);
  961.     */
  962.     
  963.     if (menuflg < 0) {
  964.         menuflg = 1;
  965.        
  966.         setschm(disksiz, partnames);
  967.         /*
  968.         if (ttscsi)    {
  969.             setschm(disksiz, partnames);
  970.         } else     {
  971.             Get all available partition schemes from wincap 'ID' entries 
  972.             wallents(partnames, pr_id);
  973.         }
  974.         */
  975.     }
  976.  
  977.     for (i = 0, s = partnames; i < 10 && *s; ++i) {
  978.         p[ppart[i]].ob_type = G_BUTTON;
  979.     p[ppart[i]].ob_spec = (long)s;
  980.     p[ppart[i]].ob_state = NORMAL;
  981.     p[ppart[i]].ob_flags = SELECTABLE | RBUTTON;
  982.     while (*s++)
  983.         ;
  984.     }
  985.  
  986.     /* rest of buttons are invisible and untouchable */
  987.     for (; i < 10; ++i) {
  988.         p[ppart[i]].ob_type = G_IBOX;
  989.     p[ppart[i]].ob_spec = 0L;            /* no thickness */
  990.     p[ppart[i]].ob_state = DISABLED;        /* nobody home */
  991.     p[ppart[i]].ob_flags = NONE;            /* disabled */
  992.     }
  993.  
  994.     /* clean up rest of the form and throw it up */
  995.     p[PPOK].ob_state = NORMAL;
  996.     p[PPCN].ob_state = NORMAL;
  997.     p[PPEDIT].ob_state = NORMAL;
  998.     
  999.     if((but = execform(p)) == PPCN || but == PPEDIT)
  1000.     return;
  1001.  
  1002.     /* search for partition they picked */
  1003.     pnlflg = 0;                /* partition scheme from menu */
  1004.     for (i = 0; i < 10; ++i)
  1005.     if (p[ppart[i]].ob_state & SELECTED)
  1006.         break;
  1007.     if (i >= 10) return but;        /* nothing changed */
  1008.     pnam = p[ppart[i]].ob_spec;
  1009.  
  1010.     /*
  1011.     if (!ttscsi)    {
  1012.         i = wgetent(pnam, pr_id);                ; (floppy access) 
  1013.         if (i != OK) {
  1014.             nopart[NOSCHPOK].ob_state = NORMAL;
  1015.                (nopart[NOSCHPR].ob_spec)->te_ptext = p[ppart[i]].ob_spec;
  1016.             execform(nopart);
  1017.             return ERROR;
  1018.         }
  1019.     }
  1020.     */
  1021.     npart = 4;
  1022.     ext = NO_EXT;        /* set no extended partition */
  1023.     if (headptr > 0)    free(headptr);
  1024.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)        {
  1025.         err(nomemory);
  1026.         if (pinfo > 0)    Mfree(pinfo);
  1027.         return ERROR;
  1028.     }
  1029.     inipart(&pinfo[0], npart);        /* initialized the 'pinfo' */
  1030.     npart = 0;
  1031.     msetpart(pinfo, pnam, disksiz);
  1032.     /*
  1033.     if (ttscsi)        {
  1034.         msetpart(pinfo, pnam, disksiz);
  1035.     } else {
  1036.         for (i = 0; i < 4; ++i)
  1037.             fillpart(i, &pinfo[i]);
  1038.     }
  1039.     */
  1040.     return but;
  1041. }
  1042.  
  1043.  
  1044. /* 
  1045.  * conver the partition number for the dialog box to the string .
  1046.  *
  1047.  */
  1048.  
  1049. stpartnum(num, str)
  1050.  
  1051. int num;
  1052. char *str;
  1053.  
  1054. {
  1055.     int  i = 0, j=0;
  1056.     char tem[20];
  1057.  
  1058.     /* set the partition number header */
  1059.     *str++ = '#';
  1060.     j++;
  1061.     /* conver the integer to ASCII */
  1062.     do    {    /* generate digits in reverse order */
  1063.         tem[i++] = num % 10 + '0';    /* get next digits */
  1064.     } while ((num /= 10) > 0);        /* delete it */
  1065.  
  1066.     for (; i > 0; )    { /* reverse string 'str' in place */
  1067.         *str++ = tem[--i];
  1068.         j++;
  1069.     }
  1070.     for (; j < 4; j++)
  1071.         *str++ = ' ';
  1072.     *str = '\0';
  1073.  
  1074. }
  1075.  
  1076.  
  1077.  
  1078. /*
  1079.  *  Place partition headers at the appropiate sectors.
  1080.  *    Input:
  1081.  *        pdev - physical device partitions belong to.
  1082.  *        part - partition structure containing the partitions'
  1083.  *               information.
  1084.  *    Return:
  1085.  *        OK - if everything is fine.
  1086.  *        ERROR - error occurs when testing header sectors.
  1087.  *    Comments:
  1088.  *        Making sure that the headers occupy consecutive good 
  1089.  *    sectors.  If necessary, sizes of partitions are adjusted to 
  1090.  *    achieve the above.
  1091.  *        If any size adjustment make a partition bigger than
  1092.  *    the maximum size, the partition will be adjusted to the maximum
  1093.  *    size leaving the excessive sectors wasted.
  1094.  */
  1095.  
  1096. spheader(pdev, part)
  1097.  
  1098. int pdev;    /* physical device number */
  1099. PART *part;    /* partition info */
  1100.  
  1101. {
  1102.     /* Maximum sizes for FAT, root directory and header <in sectors> */
  1103.     long  maxdent;        /* max num entries in root dir */
  1104.     long  start;        /* starting sector number of a partition */
  1105.     long  entries, nument();
  1106.     long  movehdr, temstart, moved, psiz;
  1107.     UWORD maxfsiz, maxdsiz, hdrsiz;
  1108.     long currbsiz;        /* size of BSL b4 pheader is executed */
  1109.     int  pno;            /* partition being dealt with */
  1110.     int  done;            /* tell if location of header is found */
  1111.     int  curr;            /* current sector of header being checked */
  1112.     int  ret;            /* return code from testing header sectors */
  1113.     int     spc;            /* sectors per cluster */
  1114.     int  kindfat;       /* 12 bits fat or 16 bits fat */
  1115.     int  step;            /* the index for check the partitions */
  1116.     long bigsect(), nsect;
  1117.     long stbigsect();
  1118.     long temsect, remain;
  1119.     long cell();
  1120.     
  1121.     
  1122.     /* get the BSL ready ofr later */
  1123.     entries = nument(MEDIA);
  1124.     sortbsl(entries);
  1125.     currbsiz = bslsiz;
  1126.  
  1127.     /* Determine actual sizes and starting sectors for all partitions */
  1128.     for (pno = 0; pno < npart; pno++) {
  1129.         
  1130.         /* Partition 0 starts right after root sect.  The rest starts right
  1131.            after its previous partition ???*/
  1132.         if (pno == 0)
  1133.             start = 1 + currbsiz; 
  1134.         else if (pno == 4)
  1135.             start = part[ext].p_st;    /* start in extened partition */
  1136.         else
  1137.             start = part[pno-1].p_st + part[pno-1].p_siz;
  1138.         
  1139.         /* Check if partition exists.  If it doesn't, move on to next one */
  1140.         if ((!(part[pno].p_flg & P_EXISTS)) || (pno == ext)) {
  1141.             part[pno].p_st = start;
  1142.             continue;
  1143.         }
  1144.         if (pno > 3)     {
  1145.             psiz = part[pno].p_siz - ROOTSECT;
  1146.         } else    {
  1147.             psiz = part[pno].p_siz;
  1148.         }
  1149.  
  1150.         /* estimate the bps */
  1151.         /* MAXSECT = 16MB - 8 */
  1152.         bps = cell((psiz-7)*BPS, (long)MAXSECT);
  1153.         /* the real pbs */
  1154.         bps = BPS * n2power((UWORD)cell(bps, (long)BPS));
  1155.         ratio = bps / BPS;
  1156.         nsect = psiz / ratio;
  1157.  
  1158.         /* Detail of calculations in part.c dopart() */
  1159.         /* find max FAT size. FAT16: 16 bits fat; FAT12: 12bits fat */
  1160.         maxfsiz = ((((nsect / SPC) + 2)*2) / bps) + 1;
  1161.         /* find max root dir entries */
  1162.         if (nsect < 0x5000L)    maxdent = NUMEN;
  1163.         else maxdent = nsect / 80;
  1164.         maxdent = (maxdent + (bps/BPDIR -1)) & ~(bps/BPDIR -1);
  1165.         /* find max root dir size */
  1166.         maxdsiz = (maxdent * BPDIR) / bps + 1;
  1167.  
  1168.            if (pno > 3)    {  /* they are extended partitions */
  1169.         /*-------------------------------------------------------*
  1170.          * Biggest possible header for a extended partition <in sectors> 
  1171.          *    =  Root sector + Boot Sector + 2 FATs + Root Dir    
  1172.          *-------------------------------------------------------*/
  1173.          /* convert it back to 512 bps size */
  1174.             hdrsiz = 1 + ratio + ((maxfsiz * 2) + maxdsiz) * ratio;
  1175.         } else
  1176.         /*-------------------------------------------------------*
  1177.          * Biggest possible header for a partition <in sectors>  *
  1178.          *    =  Boot Sector + 2 FATs + Root Dir         *
  1179.          *-------------------------------------------------------*/
  1180.          /* convert it back to 512 bps size */
  1181.             hdrsiz = (1 + (maxfsiz * 2) + maxdsiz) * ratio;
  1182.     
  1183.     /*-----------------------------------------------------------------*
  1184.      * Look for a chunk of sectors starting at "start" (or after, but  *
  1185.      * as close as possible) which is big enough to hold the biggest   *
  1186.      * possible header.                           *
  1187.      *-----------------------------------------------------------------*/
  1188.     done = 0;       /* assume correct location not found yet */
  1189.     moved = 0;
  1190.     while (!done) {
  1191.         /*----------------------------------------------------------*
  1192.          * Find out if header contains any bad sectors by checking    *
  1193.          * range of sectors to be occupied by the header against    *
  1194.          * the BSL.                                                    *
  1195.          *----------------------------------------------------------*/
  1196.         for (curr = 0; curr < hdrsiz; curr++)    {
  1197.             if (srchbsl(start+curr, entries) == YES)
  1198.                 break;
  1199.         }
  1200.         if (curr < hdrsiz)    {    /* bad sector found in header */
  1201.             /* move header to start after the bad sector */
  1202.             moved += curr + 1;
  1203.             start += curr + 1;
  1204.         } else {
  1205.                if ((ret = testhdr(pdev, start, hdrsiz)) < 0)
  1206.                  return ERROR;
  1207.             if (ret)    {    /* some bad sectors found in header */
  1208.                 entries = nument(MEDIA);
  1209.                 sortbsl(entries);
  1210.             } else {        /* all sectors belong ot header are good */
  1211.                 done = 1;
  1212.             }
  1213.         }
  1214.     }
  1215.     
  1216.     if (moved) {    /* header has been moved */
  1217.         /*-------------------------------------------------------*
  1218.          * Expand previous partition (except if the current one  *
  1219.          * is partition 0, then there is no previous partition), *
  1220.          * and enforce maximum partition size on it.         *
  1221.          *-------------------------------------------------------*/
  1222.         if (ratio > 1)    {    /* big sector */
  1223.             start -= moved;
  1224.             moved = stbigsect(moved);
  1225.             start += moved;
  1226.         }
  1227.         if (pno > 0) {
  1228.             if (part[pno-1].p_siz + moved > disksiz)
  1229.                 part[pno-1].p_siz = disksiz;
  1230.             else
  1231.                 part[pno-1].p_siz += moved;
  1232.         }
  1233.             
  1234.         /* Shrink size of current partition */
  1235.         part[pno].p_siz -= moved;
  1236.     } 
  1237.  
  1238.     /* Where current partition should start */
  1239.     part[pno].p_st = start;
  1240.  
  1241.     /* add the waist sectors of big partition to the next partition */
  1242.     /* partition #3 in the pinfo is the last partition */
  1243.     /* partition # npart-1 in the pinfo is the last partition in 
  1244.         the extended partition */
  1245.     if ((pno != 3) && (pno != npart - 1) && 
  1246.                     (part[pno].p_siz >= MB16))        { /* big partition */
  1247.         temsect = part[pno].p_siz;
  1248.         if (pno > 3)    { /* extended big partition */
  1249.            part[pno].p_siz = ROOTSECT + bigsect(part[pno].p_siz-ROOTSECT);
  1250.         } else {    /* prime big partition */
  1251.            part[pno].p_siz = bigsect(part[pno].p_siz);
  1252.         }
  1253.         remain = temsect - part[pno].p_siz;
  1254.         if (remain)    {
  1255.             part[pno+1].p_siz += remain;
  1256.             part[pno+1].p_st -= remain;
  1257.         }
  1258.     }
  1259.  
  1260.   }
  1261.     /* last existing partition has to sacrifice some space for the BSL    */
  1262.     /* and the root sector of device.                    */
  1263.     if ((ext == 3) || ((!(part[2].p_flg & P_EXISTS)) &&
  1264.                         (!(part[3].p_flg & P_EXISTS))))    { 
  1265.         /* the last partition is inside the extended partitions */
  1266.         step = npart;
  1267.         /* the total extended partition should not inculde the bad sector */
  1268.         /* list and root sector */
  1269.         part[ext].p_siz -= (currbsiz + 1);
  1270.     } else {    /* the last partition is in the prime partitions */
  1271.         step = NPARTS;
  1272.     }
  1273.     for (pno = step-1; pno >= 0; pno--) {
  1274.         if (part[pno].p_flg & P_EXISTS) {
  1275.             part[pno].p_siz -= (currbsiz + 1);
  1276.             break;
  1277.         }
  1278.     }
  1279.  
  1280.     /* have to move partitions (existing or not) which start
  1281.        right after the BSL if BSL has been expanded  */
  1282.     if (bslsiz > currbsiz) {        /* BSL becomes bigger? */
  1283.         for (pno = 0; pno < NPARTS; pno++) {
  1284.             if (part[pno].p_st == currbsiz + 1) {
  1285.                 part[pno].p_st = bslsiz + 1;
  1286.                 if (part[pno].p_siz > 0)
  1287.                     part[pno].p_siz -= (bslsiz - currbsiz);
  1288.             }
  1289.         }
  1290.     }
  1291.   return OK;    /* everything is fine */
  1292. }
  1293.  
  1294.  
  1295. long stbigsect(amt)
  1296. long amt;
  1297.  
  1298. {
  1299.     long numsect;
  1300.     if (ratio > 1)    {
  1301.         numsect = (amt % ratio) ? (amt / ratio + 1) : (amt /ratio);
  1302.         return(numsect * ratio);
  1303.     } else {
  1304.         return(amt);
  1305.     }
  1306. }
  1307.  
  1308.  
  1309. long bigsect(amt)
  1310. long amt;
  1311.  
  1312. {
  1313.     if (ratio > 1)    {
  1314.         return((amt / ratio) * ratio);
  1315.     } else {
  1316.         return(amt);
  1317.     }
  1318. }
  1319.  
  1320. /* 
  1321.  * Given size of a hard disk, figure out
  1322.  * the partition scheme ID to look for.
  1323.  * ID is 2 or more characters long.
  1324.  */
  1325. figprid(hdsiz, pr_id)
  1326. long hdsiz;
  1327. char pr_id[];
  1328. {
  1329.     UWORD mega, over;
  1330.     char numbuf[10];
  1331.     
  1332.     /* Round off disk size in megabytes */    
  1333.     mega = hdsiz / MEGABYTE;
  1334.     
  1335.     /* Round off disk size to nearest 10Mb */
  1336.     /*
  1337.     over = mega % 10;
  1338.     if (over >= 5)
  1339.        mega += (10 - over);
  1340.     else
  1341.        mega -= over;
  1342.     */
  1343.     itoa(mega, numbuf);
  1344.     strcpy(pr_id, numbuf);
  1345. }
  1346.  
  1347.  
  1348.  
  1349. /*
  1350.  * Check if partition scheme selected is _legal_.
  1351.  * _Legal_ means the scheme does not map to non-existing memory.
  1352.  * If it is not, prompt user to pick partition again.
  1353.  *    Input:
  1354.  *        pdev - physical unit we're trying to partition.
  1355.  *        xpinfo - partition block user selected.
  1356.  *    Return:
  1357.  *        OK - if partition scheme is _legal_.
  1358.  *        ERROR - if partition scheme is illegal.
  1359.  */
  1360.  
  1361. chkpart(pdev, xpinfo)
  1362. int pdev;
  1363. PART *xpinfo;
  1364. {
  1365.     char bs[512];
  1366.     SECTOR totsiz;
  1367.     int     i, ret;
  1368.     
  1369.     
  1370.     /* Get partition information from disk's root block.*/
  1371.     if ((ret = getroot(pdev, bs, (SECTOR)0)) != 0) {
  1372.         if (tsterr(ret) != OK)
  1373.             err(rootread);
  1374.         return (1);        /* return error but it is not a size too big */
  1375.     }
  1376.  
  1377.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  1378.     totsiz = 0;
  1379.     for (i = 0; i < NPARTS; i++) {
  1380.         if (xpinfo[i].p_flg & P_EXISTS)    {
  1381.             totsiz += xpinfo[i].p_siz;
  1382.         }
  1383.         if (totsiz > disksiz)
  1384.             return ERROR;     /* size too big */
  1385.     }
  1386.     return OK;
  1387. }
  1388.     
  1389.  
  1390.  
  1391. /*
  1392.  *  Make sure that sectors assigned to a partition header are GOOD.
  1393.  *    Input:
  1394.  *        pdev - physical device number partition belongs to.
  1395.  *        start - starting (physical) sector number header starts.
  1396.  *        hdrsiz - number of sectors header occupies.
  1397.  *    Return:
  1398.  *        OK - if all sectors in header are good.
  1399.  *        positive number - if entries are added to BSL in testing
  1400.  *                    the header.
  1401.  *        ERROR - if somewhere the process went wrong.
  1402.  *    Comments:
  1403.  *        Bad Sectors found are added as USER bad sectors.  
  1404.  *    First, because we can't expand the VENDOR list while preserving
  1405.  *    the USER list.  Second, this is ok, because even if the USER list
  1406.  *    is full, the user should reformat the disk anyway, and if the
  1407.  *    sector is REALLY bad, it would be discovered again then.
  1408.  */
  1409. testhdr(pdev, start, hdrsiz)
  1410. int pdev;
  1411. SECTOR start;
  1412. UWORD hdrsiz;
  1413. {
  1414.     long size, pattern;
  1415.     extern long longrandom();
  1416.     extern int tformat;        /* flag */
  1417.     UWORD sectcnt, list;
  1418.     int ret, nbad, clean=1;
  1419.     SECTOR sect;
  1420.     char *buf;        /* buffer with test data */
  1421.     
  1422.     size = (long)hdrsiz << 9;
  1423.     if ((buf = (char *)Malloc(size)) <= 0) {
  1424.         err(nomemory);
  1425.         ret = NOMEM;
  1426.         goto wrapup;
  1427.     }
  1428.         
  1429.     /*
  1430.      * Try to write to header's sectors.
  1431.      */
  1432.     pattern = longrandom();
  1433.     fillbuf(buf, size, pattern);
  1434.     sectcnt = hdrsiz;
  1435.     sect = start;
  1436.     nbad = 0;
  1437.  
  1438.     if ((ret = wrsects(pdev, sectcnt, buf, sect)) != 0) {
  1439.         if (tsterr(ret) == OK) {
  1440.             ret = ERROR;
  1441.             goto wrapup;
  1442.         }
  1443.         clean = 0;
  1444.         
  1445.         while (sectcnt) {    /* find out which sector is indeed bad */
  1446.         if ((ret = wrsects(pdev, 1, 0L, sect)) != 0) {
  1447.             if (tsterr(ret) == OK) {
  1448.                 ret = ERROR;
  1449.                 goto wrapup;
  1450.             }
  1451.             if (sect < 3) {
  1452.                 ret = err(rsrvbad);
  1453.                 goto wrapup;
  1454.             }
  1455.                     
  1456.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1457.                     
  1458.                 /* buffer is filled up, have to add bad sectors
  1459.                    found so far to the BSL before continuing.   */
  1460.                 if (nbad == WARNBADSECTS) {
  1461.                     /* Decide which list to add to */
  1462.                     if (tformat == TRUE)
  1463.                         list = VENDOR;
  1464.                     else list = USER;
  1465.                        if ((ret=addbsl(pdev, list, nbad)) < 0) {
  1466.                            ret = err(rsrvbad);
  1467.                            goto wrapup;
  1468.                        }
  1469.                        nbad = 0;    /* start counting again */
  1470.                 }
  1471.             }
  1472.             sect++;
  1473.             sectcnt--;
  1474.         }
  1475.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1476.             /* Decide which list to add to */
  1477.             if (tformat == TRUE)
  1478.                 list = VENDOR;
  1479.             else list = USER;
  1480.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1481.                 ret = ERROR;
  1482.                 goto wrapup; 
  1483.             }
  1484.             nbad = 0;
  1485.         }
  1486.     }
  1487.     
  1488.     /* Try to read header's sectors */
  1489.     sectcnt = hdrsiz;
  1490.     sect = start;
  1491.     nbad = 0;
  1492.     if ((ret = rdsects(pdev, sectcnt, buf, sect)) != 0) {
  1493.         if (tsterr(ret) == OK) {
  1494.             ret = ERROR;
  1495.             goto wrapup;
  1496.         }
  1497.         clean = 0;
  1498.         
  1499.         while (sectcnt) {    /* find out which sector is indeed bad */
  1500.         if ((ret = rdsects(pdev, 1, buf, sect)) != 0) {
  1501.             if (tsterr(ret) == OK) {
  1502.                 ret = ERROR;
  1503.                 goto wrapup;
  1504.             }
  1505.                 if (sect < 3) {
  1506.             ret = err(rsrvbad);
  1507.             goto wrapup;
  1508.         }
  1509.                     
  1510.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1511.                     
  1512.                 /* buffer is filled up, have to add bad sectors
  1513.                    found so far to the BSL before continuing.   */
  1514.                 if (nbad == WARNBADSECTS) {
  1515.                     /* Decide which list to add to */
  1516.                     if (tformat == TRUE)
  1517.                     list = VENDOR;
  1518.                     else list = USER;
  1519.                        if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1520.                            ret = ERROR;
  1521.                            goto wrapup;
  1522.                        }
  1523.                        nbad = 0;    /* start counting again */
  1524.                 }
  1525.             }
  1526.             sect++;
  1527.             sectcnt--;
  1528.         }
  1529.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1530.             /* Decide which list to add to */
  1531.             if (tformat == TRUE)
  1532.                 list = VENDOR;
  1533.             else list = USER;
  1534.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1535.                 ret = ERROR;
  1536.                 goto wrapup; 
  1537.             }
  1538.             nbad = 0;
  1539.         }
  1540.     }
  1541. wrapup:
  1542.     if (buf > 0)  Mfree((long)buf);
  1543.     
  1544.     if (ret < 0)
  1545.         return ret;
  1546.         
  1547.     if (!clean) {
  1548.         /* write new bsl back to disk */
  1549.         if (wrbsl(pdev) != OK) {
  1550.             return ERROR;
  1551.         }
  1552.         return 1;
  1553.     }
  1554.         
  1555.     return OK;
  1556. }
  1557.  
  1558. long
  1559. cell(top, bottom)
  1560. long top;
  1561. long bottom;
  1562. {
  1563.     return ((top % bottom) ? (top / bottom + 1) :
  1564.             (top / bottom));
  1565. }
  1566.  
  1567.  
  1568. n2power(num)
  1569. UWORD num;
  1570. {
  1571.     UWORD power = 1;
  1572.  
  1573.     for (;;)    {
  1574.         if (num <= power )    {
  1575.             return (power);
  1576.         }
  1577.         power <<= 1;
  1578.     } 
  1579. }
  1580.  
  1581.  
  1582. DPART
  1583. *addr(index)
  1584. int index;
  1585. {
  1586.     DPART *temptr;
  1587.     int i;
  1588.  
  1589.     if (index < 0)    return nill;
  1590.     if (!index) return (headptr);
  1591.     temptr = headptr->next;
  1592.     for (i = 1; i < index; i++)    {
  1593.         temptr = temptr->next;
  1594.     }
  1595.     return (temptr);
  1596. }
  1597.  
  1598. DPART
  1599. *last()
  1600. {
  1601.     DPART *temptr;
  1602.     int i;
  1603.  
  1604.     if (!headptr) return (headptr);
  1605.     temptr = headptr;
  1606.     while (temptr->next)
  1607.         temptr = temptr->next;
  1608.     return (temptr);
  1609. }
  1610.  
  1611.  
  1612.  
  1613. creatmem(num)
  1614. int num;        /* number of block to malloc */
  1615. {
  1616.     DPART *temptr;
  1617.     DPART *last();
  1618.     int i;
  1619.  
  1620.     if (headptr == nill)    {
  1621.         if ((headptr = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {;
  1622.             err(nomemory);
  1623.             if (headptr > 0) free(headptr);
  1624.             return ERROR;
  1625.         }
  1626.         headptr->next = nill;
  1627.         headptr->siz = 0L;
  1628.         headptr->flg = 0;
  1629.     }
  1630.     temptr = last();
  1631.     for (i = 0; i < num; i++)    {
  1632.         if ((temptr->next = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {
  1633.             err(nomemory);
  1634.             if (headptr > 0) free(headptr);
  1635.             return ERROR;
  1636.  
  1637.         }
  1638.         temptr = temptr->next;
  1639.         temptr->next = nill;
  1640.         temptr->siz = 0L;
  1641.         temptr->flg = 0;
  1642.     }
  1643. }
  1644.  
  1645.  
  1646. dpart2part(extpart)
  1647. int extpart ;    /* set the extended pointer in the 4th place */
  1648. {
  1649.     int i;
  1650.     DPART *temptr;
  1651.  
  1652.     /* if npart > 4; need 1 more space for the extended partition */
  1653.     if (npart > 4)    {
  1654.         i = npart - extend;    /* the index that extended form the end of part. */
  1655.         npart += NPARTS-extpart;    /* add 1 extra space for the extended */
  1656.                                     /* partition and 0 or 1 or 2 space for */
  1657.                                     /* the prime partition in the root */
  1658.         extend = npart - i;    /* move 2 space for 2 prime partition in the root */
  1659.     } else {                /* set the extpart to -1 */
  1660.         npart = 4;
  1661.         extpart = -1;
  1662.         ext = NO_EXT;
  1663.     }
  1664.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)    {
  1665.         err(nomemory);
  1666.         if (pinfo > 0) Mfree(pinfo);
  1667.         free(headptr);
  1668.         return ERROR;
  1669.     }
  1670.     inipart(pinfo, npart);  
  1671.     temptr = headptr;
  1672.     for (i = 0; i < npart; i++)        {
  1673.         if (!(temptr->flg & P_EXISTS)) {
  1674.             if (sizleft > 0) {
  1675.                 if (temptr->siz > sizleft) {
  1676.                     pinfo[i].p_siz = sizleft;
  1677.                 }
  1678.                 sizleft -= temptr->siz;
  1679.             }
  1680.         } else {
  1681.             pinfo[i].p_siz = temptr->siz;
  1682.             pinfo[i].p_flg = P_EXISTS;
  1683.             if (i == extpart)    {
  1684.                 pinfo[i].p_id[0] = 'X';
  1685.                 pinfo[i].p_id[1] = 'G';
  1686.                 pinfo[i].p_id[2] = 'M';
  1687.                 pinfo[i].p_siz = 0L;
  1688.             } else if ((extpart == 1) && ((i == 2) || (i==3)))    {
  1689.                 pinfo[i].p_flg = 0;
  1690.                 pinfo[i].p_siz = 0L;
  1691.             } else if ((extpart == 2) && (i==3))    {
  1692.                 pinfo[i].p_flg = 0;
  1693.                 pinfo[i].p_siz = 0L;
  1694.             } else if (temptr->siz < MB16)    {
  1695.                 pinfo[i].p_id[0] = 'G';
  1696.                 pinfo[i].p_id[1] = 'E';
  1697.                 pinfo[i].p_id[2] = 'M';
  1698.                 temptr = temptr->next;
  1699.             } else {
  1700.                 pinfo[i].p_id[0] = 'B';
  1701.                 pinfo[i].p_id[1] = 'G';
  1702.                 pinfo[i].p_id[2] = 'M';
  1703.                 temptr = temptr->next;
  1704.             }
  1705.         }
  1706.     }
  1707.     free(headptr);
  1708.     if (extpart != NO_EXT)    {
  1709.         asmpart(extpart);
  1710.     }
  1711.     return OK;
  1712. }
  1713.  
  1714.  
  1715. asmpart(extpart)
  1716. int extpart ;    /* the extended partition pointer */
  1717. {
  1718.     int i;
  1719.  
  1720.     /* # of extened partition to add up */
  1721.     for (i = 4; i < extend; i++)        {
  1722.         pinfo[extpart].p_siz += pinfo[i].p_siz;
  1723.     }
  1724.     if (extpart == 3)    {
  1725.         return OK;        /* done */
  1726.     } else     {
  1727.         /* put the last (npart-extend-1) partitions to */
  1728.         /* the 3rd or 4th place as prime partitions */
  1729.         i = extend;
  1730.         if (i < npart)    {
  1731.             pinfo[extpart+1].p_siz = pinfo[i].p_siz;
  1732.             pinfo[extpart+1].p_flg = P_EXISTS;
  1733.             if (pinfo[extpart+1].p_siz < MB16)    {
  1734.                 pinfo[extpart+1].p_id[0] = 'G';
  1735.                 pinfo[extpart+1].p_id[1] = 'E';
  1736.                 pinfo[extpart+1].p_id[2] = 'M';
  1737.             } else {
  1738.                 pinfo[extpart+1].p_id[0] = 'B';
  1739.                 pinfo[extpart+1].p_id[1] = 'G';
  1740.                 pinfo[extpart+1].p_id[2] = 'M';
  1741.             }
  1742.             pinfo[i].p_flg = 0;
  1743.             pinfo[i].p_siz = 0L;
  1744.             pinfo[i].p_id[0] = '0';
  1745.             pinfo[i].p_id[1] = '0';
  1746.             pinfo[i].p_id[2] = '0';
  1747.             npart--;
  1748.         } 
  1749.         if (i++ < npart)    {
  1750.             pinfo[extpart+2].p_siz = pinfo[i].p_siz;
  1751.             pinfo[extpart+2].p_flg = P_EXISTS;
  1752.             if (pinfo[extpart+2].p_siz < MB16)    {
  1753.                 pinfo[extpart+2].p_id[0] = 'G';
  1754.                 pinfo[extpart+2].p_id[1] = 'E';
  1755.                 pinfo[extpart+2].p_id[2] = 'M';
  1756.             } else {
  1757.                 pinfo[extpart+2].p_id[0] = 'B';
  1758.                 pinfo[extpart+2].p_id[1] = 'G';
  1759.                 pinfo[extpart+2].p_id[2] = 'M';
  1760.             }
  1761.             pinfo[i].p_flg = 0;
  1762.             pinfo[i].p_siz = 0L;
  1763.             pinfo[i].p_id[0] = '0';
  1764.             pinfo[i].p_id[1] = '0';
  1765.             pinfo[i].p_id[2] = '0';
  1766.             npart--;
  1767.         }
  1768.     }
  1769. }
  1770.  
  1771.  
  1772. part2dpart(numpart)
  1773. int numpart;
  1774. {
  1775.  
  1776.     int i;
  1777.     DPART *temptr;
  1778.  
  1779.     headptr = nill;
  1780.     if (creatmem(numpart) == ERROR) {
  1781.         return ERROR;
  1782.     }
  1783.     temptr = headptr;
  1784.     for (i = 0; i < numpart; i++) {
  1785.         if (pinfo[i].p_flg & P_EXISTS)    {
  1786.             temptr->siz = pinfo[i].p_siz;
  1787.             temptr->flg = P_EXISTS;
  1788.         } 
  1789.         temptr = temptr->next;
  1790.     }
  1791. }
  1792.