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