home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / mbwin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  24.6 KB  |  948 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 23
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /**********************************************************************
  4.  * handling the mailbox window
  5.  **********************************************************************/
  6. #pragma load EUDORA_LOAD
  7. #pragma segment MboxWin
  8.  
  9. /************************************************************************
  10.  * the structure for the mailbox window
  11.  ************************************************************************/
  12. typedef enum {FromSideIndex,ToSideIndex} SideEnum;
  13. typedef enum {FromRenameIndex,FromRemoveIndex,FromNewIndex,FromMoveIndex,
  14.     ToRenameIndex,ToRemoveIndex,ToNewIndex,ToMoveIndex,
  15.     FromMenuIndex,ToMenuIndex,ControlCount} ControlEnum;
  16. typedef struct
  17. {
  18.     MenuHandle menu;
  19.     ListHandle list;
  20.     short id;
  21.     long dirId;
  22. } SideType, *SidePtr;
  23. typedef struct
  24. {
  25.     SideType sides[2];
  26.     MyWindowPtr win;
  27.     ControlHandle controls[ControlCount];
  28. } MBType, *MBPtr, **MBHandle;
  29. #define Win (*MBG)->win
  30. #define Controls (*MBG)->controls
  31. #define FromRename (*MBG)->controls[FromRenameIndex]
  32. #define FromRemove (*MBG)->controls[FromRemoveIndex]
  33. #define FromNew (*MBG)->controls[FromNewIndex]
  34. #define FromMenu (*MBG)->controls[FromMenuIndex]
  35. #define ToRename (*MBG)->controls[ToRenameIndex]
  36. #define ToRemove (*MBG)->controls[ToRemoveIndex]
  37. #define ToNew (*MBG)->controls[ToNewIndex]
  38. #define ToMenu (*MBG)->controls[ToMenuIndex]
  39. #define FromMove (*MBG)->controls[FromMoveIndex]
  40. #define ToMove (*MBG)->controls[ToMoveIndex]
  41. #define Sides (*MBG)->sides
  42. #define FromSide Sides[FromSideIndex]
  43. #define ToSide Sides[ToSideIndex]
  44. MBHandle MBG;
  45. #define NSIDES (sizeof(Sides)/sizeof(SideType))
  46. #define DIRID_OF(Side) ((Side).id==MAILBOX_MENU ? MyDirId : (*BoxMap)[(Side).id])
  47.  
  48. /************************************************************************
  49.  * prototypes
  50.  ************************************************************************/
  51.     Boolean MBMenu(MyWindowPtr win, int menu, int item, short modifiers);
  52.     void MBDidResize(MyWindowPtr win, Rect *oldContR);
  53.     void MBUpdate(MyWindowPtr win);
  54.     Boolean MBClose(MyWindowPtr win);
  55.     short MBFill(void);
  56.     short MBFillSide(short whichSide, MenuHandle mh);
  57.     void MBClick(MyWindowPtr win,EventRecord *event);
  58.     void MBCursor(Point mouse);
  59.     void MBActivate(void);
  60.     void MBSetControls(void);
  61.     void MBHit(short which);
  62.     void MBListOpen(short whichSide);
  63.     void MBListClose(short whichSide);
  64.     MenuHandle ParentMailboxMenu(MenuHandle mh,short *itemPtr);
  65.     short FindItemBySubmenu(MenuHandle mh, short subID);
  66.     short MBRefill(short whichSide,UPtr andSelect);
  67.     void DoRenameBox(long inDirId,UPtr name,UPtr newName);
  68.     Boolean DoRemoveBox(MenuHandle mh,UPtr name,Boolean *andShutUp);
  69.     short DeleteMailFolder(MenuHandle mh,short item);
  70.     void DoMoveMailbox(UPtr selectName,short si);
  71.     Boolean SameSelected(void);
  72.     UPtr MBGetData(UPtr data,Cell c,ListHandle list);
  73.     Boolean DontMove(void);
  74.     short CellMenuId(Cell c,short whichSide);
  75.     void MBHelp(MyWindowPtr win,Point mouse);
  76.     void MBFixSideIndices(void);
  77.   void SetSideIndices(short side, MenuHandle mh);
  78.  
  79. /************************************************************************
  80.  * OpenMBWin - open the mailbox window
  81.  ************************************************************************/
  82. void OpenMBWin(void)
  83. {
  84.     if (!MBG)
  85.     {
  86.         short err=0;
  87.         short i;
  88.         Point cSize;
  89.         Rect r, bounds;
  90.         Str31 scratch;
  91.         
  92.         if (!(MBG=NewZH(MBType))) {err=MemError(); goto fail;}
  93.         LDRef(MBG);
  94.         if (!(Win=GetNewMyWindow(MBWIN_WIND,nil,InFront,False,False)))
  95.             {err=MemError(); goto fail;}
  96.         Win->minSize.h = Win->contR.right-Win->contR.left;
  97.         Win->minSize.v = Win->contR.bottom-Win->contR.top;
  98.         SetPort(Win);
  99.         TextFont(0);
  100.         TextSize(0);
  101.         /*
  102.          * controls
  103.          */
  104.         for (i=0;i<=ToMoveIndex;i++)
  105.         {
  106.             if (!(Controls[i]=GetNewControl(MAKE_TO_CNTL,Win)))
  107.                 {err=MemError(); goto fail;}
  108.         }
  109.         SetCTitle(FromMove,GetRString(scratch,MBOX_MOVE));
  110.         SetCTitle(FromRename,GetRString(scratch,MBOX_RENAME));
  111.         SetCTitle(FromRemove,GetRString(scratch,MBOX_REMOVE));
  112.         SetCTitle(FromNew,GetRString(scratch,MBOX_NEW));
  113.         SetCTitle(ToMove,GetRString(scratch,MBOX_MOVE_BACK));
  114.         SetCTitle(ToRename,GetRString(scratch,MBOX_RENAME));
  115.         SetCTitle(ToRemove,GetRString(scratch,MBOX_REMOVE));
  116.         SetCTitle(ToNew,GetRString(scratch,MBOX_NEW));
  117.         
  118.         /*
  119.          * the two popup menus
  120.          */
  121.         if (!(FromMenu=GetNewControl(FROM_MB_CNTL,Win)))
  122.             {err=MemError(); goto fail;}
  123.         if (!(ToMenu=GetNewControl(TO_MB_CNTL,Win)))
  124.             {err=MemError(); goto fail;}
  125.         
  126.         /*
  127.          * list areas
  128.          */
  129.         SetRect(&r,0,0,20,20);
  130.         SetRect(&bounds,0,0,1,0);
  131.         cSize.v = GetLeading(0,0);    cSize.h = 20;
  132.         for (i=0;i<NSIDES;i++)
  133.         {
  134.             if (!(Sides[i].list=
  135.                     LNew(&r,&bounds,cSize,MBWIN_LDEF,Win,False,False,False,True)))
  136.                 {err=MemError(); goto fail;}
  137.             (*Sides[i].list)->indent.v = GetAscent(0,0);
  138.             (*Sides[i].list)->indent.h = 2;
  139.             (*Sides[i].list)->selFlags = lExtendDrag|lNoRect|lNoExtend|lUseSense;
  140.         }
  141.         
  142.         if (MBFill()) goto fail;
  143.         
  144.         Win->didResize = MBDidResize;
  145.         Win->close = MBClose;
  146.         Win->update = MBUpdate;
  147.         Win->position = PositionPrefsTitle;
  148.         Win->click = MBClick;
  149.         Win->qWindow.windowKind = MB_WIN;
  150.         Win->dontControl = True;
  151.         Win->cursor = MBCursor;
  152.         Win->activate = MBActivate;
  153.         Win->help = MBHelp;
  154.         Win->menu = MBMenu;
  155.         ShowMyWindow(Win);
  156.         MyWindowDidResize(Win,&Win->contR);
  157.         UL(MBG);
  158.         return;
  159.         
  160.         fail:
  161.             if (Win) CloseMyWindow(Win);
  162.             else if (MBG) DisposHandle(MBG);
  163.             if (err) WarnUser(COULDNT_MBOX,err);
  164.             return;
  165.     }
  166.     SelectWindow(Win);
  167. }
  168.  
  169. /************************************************************************
  170.  * MBDidResize - resize the MB window
  171.  ************************************************************************/
  172. void MBDidResize(MyWindowPtr win, Rect *oldContR)
  173. {
  174. #pragma unused(oldContR)
  175.     Rect r;
  176.     short hi,wi;
  177.     short h1,h2,h3,h4;
  178.     short v1,v2,v3,v4;
  179.     Point cSize;
  180. #define INSET 6
  181.  
  182.     /*
  183.      * setup some stuff
  184.      */
  185.     hi = (*FromRename)->contrlRect.bottom - (*FromRename)->contrlRect.top;
  186.     h1 = INSET;
  187.     h4 = Win->contR.right-INSET;
  188.     wi = MIN(108,3*(h4-h1-2*INSET)/10);
  189.     h2 = h1 + (h4-h1-wi)/2;
  190.     h3 = h4 - (h2-h1);
  191.     v1 = INSET;
  192.     v2 = 2*INSET+hi;
  193.     v3 = Win->contR.bottom - 3*INSET - 2*hi;
  194.     v4 = v3 + INSET;
  195.     wi = (h2-h1-GROW_SIZE)/2;
  196.  
  197.         
  198.     /*
  199.      * size the left-hand list area, including scroll bar
  200.      */
  201.     SetRect(&r,h1,v2,h2-GROW_SIZE,v3);
  202.     
  203.     /*
  204.      * move the controls - left side
  205.      */
  206.     MoveMyCntl(Win,FromRename,h1,v4,wi,hi);
  207.     MoveMyCntl(Win,FromNew,h2-wi,v4,wi,hi);
  208.     MoveMyCntl(Win,FromRemove,(h1+h2-wi)/2,v4+hi+INSET,wi,hi);
  209.     MoveMyCntl(Win,FromMove,h2+INSET,v2+(v3-v2)/3-hi,h3-h2-2*INSET,hi);
  210.     
  211.     /*
  212.      * right side
  213.      */
  214.     MoveMyCntl(Win,ToRename,h3,v4,wi,hi);
  215.     MoveMyCntl(Win,ToNew,h4-wi,v4,wi,hi);
  216.     MoveMyCntl(Win,ToRemove,(h4+h3-wi)/2,v4+hi+INSET,wi,hi);
  217.     MoveMyCntl(Win,ToMove,h2+INSET,v2+2*(v3-v2)/3,h3-h2-2*INSET,hi);
  218.     
  219.     /*
  220.      * top
  221.      */
  222.     MoveMyCntl(Win,FromMenu,h1,v1,h2-h1,hi);
  223.     MoveMyCntl(Win,ToMenu,h3,v1,h4-h3,hi);
  224.     
  225.     /*
  226.      * left-side list
  227.      */
  228.     LDoDraw(False,FromSide.list);
  229.     (*FromSide.list)->rView = r;
  230.     hi = r.bottom-r.top;
  231.     wi = r.right-r.left;
  232.     cSize.v = GetLeading(0,0);
  233.     cSize.h = wi;
  234.     LSize(wi,hi,FromSide.list);
  235.     LCellSize(cSize,FromSide.list);
  236.     LDoDraw(True,FromSide.list);
  237.     
  238.     /*
  239.      * right-side list
  240.      */
  241.     LDoDraw(False,ToSide.list);
  242.     OffsetRect(&r,h3-h1,0);
  243.     (*ToSide.list)->rView = r;
  244.     LSize(wi,hi,ToSide.list);
  245.     LCellSize(cSize,ToSide.list);
  246.     LDoDraw(True,ToSide.list);
  247.     
  248.     /*
  249.      * redraw
  250.      */
  251.     MBSetControls();
  252.     InvalContent(win);
  253. }
  254.  
  255. #pragma segment Main
  256. /************************************************************************
  257.  * MBClose - close the window
  258.  ************************************************************************/
  259. Boolean MBClose(MyWindowPtr win)
  260. {
  261. #pragma unused(win)
  262.     if (!MBG) return(True);
  263.     if (FromSide.list) LDispose(FromSide.list);
  264.     if (ToSide.list) LDispose(ToSide.list);
  265.     DisposHandle(MBG);
  266.     MBG = nil;
  267.     return(True);
  268. }
  269. #pragma segment MBoxWin
  270.  
  271. /************************************************************************
  272.  * MBUpdate - draw the window
  273.  ************************************************************************/
  274. void MBUpdate(MyWindowPtr win)
  275. {
  276.     Rect r;
  277.     
  278.     r = (*FromSide.list)->rView;
  279.     InsetRect(&r,-1,-1);
  280.     FrameRect(&r);
  281.     r = (*ToSide.list)->rView;
  282.     InsetRect(&r,-1,-1);
  283.     FrameRect(&r);
  284.     LUpdate(((GrafPtr)win)->visRgn,FromSide.list);
  285.     LUpdate(((GrafPtr)win)->visRgn,ToSide.list);
  286. }
  287.  
  288. /************************************************************************
  289.  * MBActivate - activate the window
  290.  ************************************************************************/
  291. void MBActivate(void)
  292. {
  293.     LActivate(Win->isActive,FromSide.list);
  294.     LActivate(Win->isActive,ToSide.list);
  295. }
  296.  
  297. /************************************************************************
  298.  * MBRefill - refill current menus
  299.  ************************************************************************/
  300. short MBRefill(short whichSide,UPtr andSelect)
  301. {
  302.     Point oldCell={0,0};
  303.     short err;
  304.     Boolean selected;
  305.     
  306.     selected = LGetSelect(True,&oldCell,Sides[whichSide].list);
  307.     err = MBFillSide(whichSide,GetMHandle(Sides[whichSide].id));
  308.     if (andSelect)
  309.     {
  310.         Point newCell={0,0};
  311.         if (LSearch(andSelect,2+andSelect[1],nil,&newCell,Sides[whichSide].list))
  312.         {
  313.             oldCell = newCell;
  314.             selected = True;
  315.         }
  316.     }
  317.     if (selected)
  318.     {
  319.         if (oldCell.v>=(*Sides[whichSide].list)->dataBounds.bottom)
  320.             oldCell.v = (*Sides[whichSide].list)->dataBounds.bottom;
  321.         LSetSelect(True,oldCell,Sides[whichSide].list);
  322.         LAutoScroll(Sides[whichSide].list);
  323.     }
  324.     return(err);
  325. }
  326.  
  327. /************************************************************************
  328.  * MBFill - fill the windows
  329.  ************************************************************************/
  330. short MBFill(void)
  331. {
  332.     short err;
  333.     MenuHandle mh=GetMHandle(MAILBOX_MENU);
  334.     if (err=MBFillSide(FromSideIndex,mh)) return(err);
  335.     if (err=MBFillSide(ToSideIndex,mh)) return(err);
  336.     return(noErr);
  337. }
  338.  
  339. /************************************************************************
  340.  * MBFillSide - fill a list from a menu
  341.  ************************************************************************/
  342. short MBFillSide(short whichSide, MenuHandle mh)
  343. {
  344.     Str63 name;
  345.     short i,n;
  346.     Boolean hasSub;
  347.     short base=0;
  348.     Point c;
  349.     short err;
  350.     Rect scrap;
  351.     MenuHandle topMenu;
  352.     ControlHandle topControl = (whichSide?ToMenu : FromMenu);
  353.     
  354.     topMenu = (MenuHandle)*(long *)*(*topControl)->contrlData;
  355.     
  356.     LDoDraw(False,Sides[whichSide].list);
  357.     LDelRow(INFINITY,0,Sides[whichSide].list);
  358.     n = CountMItems(mh);
  359.     c.h = 0;
  360.     SetPort(Win);
  361.     i = (mh==GetMHandle(MAILBOX_MENU)) ? 5 : 1;
  362.     for (;i<=n;i++)
  363.     {
  364.         hasSub = HasSubmenu(mh,i);
  365.         MyGetItem(mh,i,name+1);
  366.         name[0] = hasSub;
  367.         if (!base)
  368.         {
  369.             if (err=LAddRow(n-i+1,INFINITY,Sides[whichSide].list))
  370.             return(WarnUser(COULDNT_MBOX,err));
  371.             base = i;
  372.         }
  373.         c.v = i-base;
  374.         LSetCell(name,name[1]+2,c,Sides[whichSide].list);
  375.     }
  376.     LDoDraw(True,Sides[whichSide].list);
  377.     scrap = (*Sides[whichSide].list)->rView;
  378.     scrap.right += GROW_SIZE;
  379.     InsetRect(&scrap,-2,-2);
  380.     InvalRect(&scrap);
  381.     Sides[whichSide].menu = mh;
  382.     Sides[whichSide].id = (*mh)->menuID;
  383.     Sides[whichSide].dirId = DIRID_OF(Sides[whichSide]);
  384.     
  385.     TrashMenu(topMenu,1);
  386.     while(1)
  387.     {
  388.         if (mh==GetMHandle(MAILBOX_MENU))
  389.         {
  390.             GetDirName(nil,MyVRef,MyDirId,name);
  391.             MyAppendMenu(topMenu,name);
  392.             break;
  393.         }
  394.         else
  395.         {
  396.             mh=ParentMailboxMenu(mh,&i);
  397.             MyGetItem(mh,i,name);
  398.             MyAppendMenu(topMenu,name);
  399.         }
  400.     }
  401.     SetCtlMin(topControl,1);
  402.     SetCtlMax(topControl,CountMItems(topMenu));
  403.     SetCtlValue(topControl,1);
  404.     return(noErr);
  405. }
  406.  
  407. /************************************************************************
  408.  * MBClick - click in mailboxes window
  409.  ************************************************************************/
  410. void MBClick(MyWindowPtr win,EventRecord *event)
  411. {
  412. #pragma unused(win);
  413.     Rect r;
  414.     short i;
  415.     Point pt,c;
  416.     
  417.     pt = event->where;
  418.     GlobalToLocal(&pt);
  419.     for (i=0;i<NSIDES;i++)
  420.     {
  421.         r = (*Sides[i].list)->rView;
  422.         r.right += GROW_SIZE;
  423.         if (PtInRect(pt,&r))
  424.         {
  425.             if (MyLClick(pt,event->modifiers,Sides[i].list))
  426.                 MBListOpen(i);
  427.             while (FirstSelected(&c,Sides[1-i].list))
  428.                 LSetSelect(False,c,Sides[1-i].list);
  429.             break;
  430.         }
  431.     }
  432.     
  433.     if (i>=NSIDES)
  434.         for (i=0;i<ControlCount;i++)
  435.         {
  436.             r = (*Controls[i])->contrlRect;
  437.             if (PtInRect(pt,&r))
  438.             {
  439.                 if ((*Controls[i])->contrlRfCon!='GREY' &&
  440.                         TrackControl(Controls[i],pt,(void *)(-1)))
  441.                     MBHit(i);
  442.                 break;
  443.             }
  444.         }
  445.     
  446.     MBSetControls();
  447. }
  448.  
  449. /************************************************************************
  450.  * MBCursor - set the cursor properly for the mailboxes window
  451.  ************************************************************************/
  452. void MBCursor(Point mouse)
  453. {
  454.     short i;
  455.     
  456.     for (i=0;i<NSIDES;i++)
  457.     {
  458.         if (CursorInRect(mouse,(*Sides[i].list)->rView,MouseRgn))
  459.         {
  460.             SetMyCursor(plusCursor);
  461.             break;
  462.         }
  463.     }
  464.     if (i==NSIDES) SetMyCursor(arrowCursor);
  465. }
  466.  
  467. /************************************************************************
  468.  * MBSetControls - enable or disable the controls, based on current situation
  469.  ************************************************************************/
  470. void MBSetControls(void)
  471. {
  472.     Cell c,nc;
  473.     Boolean fromSelect, fromMultiple, toSelect, toMultiple;
  474.     
  475.     c.h = c.v=0;
  476.     nc = c; toSelect = LGetSelect(True,&nc,ToSide.list);
  477.     nc.v++; toMultiple = toSelect && LGetSelect(True,&nc,ToSide.list);
  478.     nc = c; fromSelect = LGetSelect(True,&nc,FromSide.list);
  479.     nc.v++; fromMultiple = fromSelect && LGetSelect(True,&nc,FromSide.list);
  480.     
  481.     SetGreyControl(FromMove,!fromSelect||toSelect||DontMove());
  482.     SetGreyControl(FromRename,!fromSelect||fromMultiple);
  483.     SetGreyControl(FromRemove,!fromSelect);
  484.     SetGreyControl(ToMove,!toSelect||fromSelect||DontMove());
  485.     SetGreyControl(ToRename,!toSelect||toMultiple);
  486.     SetGreyControl(ToRemove,!toSelect);
  487. }
  488.  
  489. /************************************************************************
  490.  * MBHit - a control item was hit
  491.  ************************************************************************/
  492. void MBHit(short which)
  493. {
  494.     Point c;
  495.     Str63 data,otherData,newData;
  496.     Boolean andShutUp=False;
  497.     Boolean needRefill=False;
  498.     UPtr fromSelect = nil;
  499.     UPtr toSelect = nil;
  500.     short si,lev;
  501.     MenuHandle mh;
  502.     long moreJunk;
  503.     Boolean folder;
  504.     long newDirId;
  505.     
  506.     si = which<=FromMoveIndex || which==FromMenuIndex ? FromSideIndex : ToSideIndex;
  507.     switch (which)
  508.     {
  509.         case FromRenameIndex:
  510.         case ToRenameIndex:
  511.             FirstSelected(&c,Sides[si].list);
  512.             MBGetData(data,c,Sides[si].list);
  513.             DoRenameBox(DIRID_OF(Sides[si]),data+1,newData+1);
  514.             newData[0] = data[0];
  515.             fromSelect = newData;
  516.             if (FirstSelected(&c,Sides[1-si].list))
  517.             {
  518.                 MBGetData(otherData,c,Sides[1-si].list);
  519.                 toSelect = FromSide.id==ToSide.id && EqualString(data+1,otherData+1,False,True) ?
  520.                     newData:otherData;
  521.             }
  522.             needRefill=True;
  523.             break;
  524.         case FromRemoveIndex:
  525.         case ToRemoveIndex:
  526.             for (c.h = c.v = 0;LGetSelect(True,&c, Sides[si].list);c.v++)
  527.             {
  528.                 MBGetData(data,c,Sides[si].list);
  529.                 if (!DoRemoveBox(Sides[si].menu,data+1,&andShutUp)) break;
  530.             }
  531.             needRefill=True;
  532.             break;
  533.         case FromMoveIndex:
  534.         case ToMoveIndex:
  535.             DoMoveMailbox(otherData,si);
  536.             if (FirstSelected(&c,Sides[1-si].list)) toSelect = otherData;
  537.             needRefill = True;
  538.             break;
  539.         case FromNewIndex:
  540.         case ToNewIndex:
  541.             if (GetNewMailbox(DIRID_OF(Sides[si]),data,&folder,&newDirId,nil))
  542.             {
  543.                 needRefill = True;
  544.                 fromSelect = data;
  545.             }
  546.             break;
  547.         case FromMenuIndex:
  548.         case ToMenuIndex:
  549.             lev = GetCtlValue(Controls[which]);
  550.             if (lev>1)
  551.             {
  552.                 mh = Sides[si].menu;
  553.                 while (--lev) mh = ParentMailboxMenu(mh,&moreJunk);
  554.                 MBFillSide(si,mh);
  555.             }
  556.             break;
  557.     }
  558.     if (needRefill)
  559.     {
  560.         BuildBoxMenus();
  561.         if (si==FromSideIndex) MBTickle(fromSelect,toSelect);
  562.         else MBTickle(toSelect,fromSelect);
  563.     }
  564. }
  565.  
  566. /************************************************************************
  567.  * MBListOpen - open some stuff from a list handle
  568.  ************************************************************************/
  569. void MBListOpen(short whichSide)
  570. {
  571.     Cell c;
  572.     Str63 data;
  573.     
  574.     for (c.h = c.v = 0;LGetSelect(True,&c,Sides[whichSide].list);c.v++)
  575.     {
  576.         MBGetData(data,c,Sides[whichSide].list);
  577.         if (!data[0])
  578.             (void) GetMailbox(DIRID_OF(Sides[whichSide]),data+1,True);
  579.         else
  580.         {
  581.             MBFillSide(whichSide,GetMHandle(CellMenuId(c,whichSide)));
  582.             break;
  583.         }
  584.     }
  585. }
  586.  
  587. /************************************************************************
  588.  * ParentMailboxMenu - find the menu enclosing this one
  589.  ************************************************************************/
  590. MenuHandle ParentMailboxMenu(MenuHandle mh,short *itemPtr)
  591. {
  592.     short myID, curID;
  593.     
  594.     curID = myID = (*mh)->menuID;
  595.     while (--curID)
  596.     {
  597.         mh = GetMHandle(curID);
  598.         if (*itemPtr = FindItemBySubmenu(mh,myID)) return(mh);
  599.     }
  600.     
  601.     mh = GetMHandle(MAILBOX_MENU);
  602.     if (*itemPtr = FindItemBySubmenu(mh,myID)) return(mh);
  603.     return(nil);
  604. }
  605.  
  606. /************************************************************************
  607.  * FindItemBySubmenu - find a menu item with a given submenu
  608.  ************************************************************************/
  609. short FindItemBySubmenu(MenuHandle mh, short subID)
  610. {
  611.     short item, newID;
  612.     for (item=CountMItems(mh);HasSubmenu(mh,item);item--)
  613.     {
  614.         GetItemMark(mh,item,&newID);
  615.         if (newID==subID) return(item);
  616.     }
  617.     return(0);
  618. }
  619.  
  620.  
  621. /************************************************************************
  622.  * DoRenameBox - handle interaction with the user for renaming a mailbox
  623.  ************************************************************************/
  624. void DoRenameBox(long inDirId,UPtr name,UPtr newName)
  625. {
  626.     DialogPtr dgPtr;
  627.     short item;
  628.     TOCHandle tocH;
  629.     Boolean isFolder=IsItAFolder(MyVRef,inDirId,name);
  630.     long newDirId;
  631.     
  632.     if (!isFolder && (!(tocH=TOCByName(inDirId,name)) || (*tocH)->which))
  633.     {
  634.         WarnUser(MAYNT_RENAME_BOX,0);
  635.         return;
  636.     }
  637.     
  638.     MyParamText(name,"","","");
  639.     
  640.     ThirdCenterDialog(RENAME_BOX_DLOG);
  641.     if ((dgPtr = GetNewDialog(RENAME_BOX_DLOG,nil,InFront))==nil)
  642.     {
  643.         WarnUser(GENERAL,MemError());
  644.         return;
  645.     }
  646.     
  647.     SetDIText(dgPtr,NEW_MAILBOX_NAME,name);
  648.     ShowWindow(dgPtr);
  649.     HiliteButtonOne(dgPtr);
  650.     do
  651.     {
  652.         MyParamText(name,"","","");
  653.         SelIText(dgPtr,NEW_MAILBOX_NAME,0,INFINITY);
  654.         PushCursor(iBeamCursor);
  655.         ModalDialog(DlgFilter,&item);
  656.         PopCursor();
  657.         GetDIText(dgPtr,NEW_MAILBOX_NAME,newName);
  658.     }
  659.     while (item==1 && !EqualString(name,newName,False,True) &&
  660.                  BadMailboxName(inDirId,newName,isFolder,&newDirId));
  661.     
  662.     DisposDialog(dgPtr);
  663.     
  664.     if (item==1)
  665.     {
  666.         if (isFolder)
  667.         {
  668.             if (!EqualString(name,newName,False,True))
  669.                 HDelete(MyVRef,inDirId,newName);
  670.             if (HRename(MyVRef,inDirId,name,newName)) return;
  671.         }
  672.         else
  673.         {
  674.             if (!EqualString(name,newName,False,True))
  675.                 HDelete(MyVRef,inDirId,newName);
  676.             if (RenameMailbox(inDirId,name,newName,isFolder)) return;
  677.             (*tocH)->dirty = True;
  678.             PCopy((*tocH)->name,newName);
  679.             SetWTitle((*tocH)->win,newName);
  680.         }
  681.     }
  682. }
  683.  
  684. /************************************************************************
  685.  * DoRemoveBox - interact with the user before removing a mailbox
  686.  ************************************************************************/
  687. Boolean DoRemoveBox(MenuHandle mh,UPtr name,Boolean *andShutUp)
  688. {
  689.     TOCHandle tocH;
  690.     Boolean isFolder;
  691.     Boolean isEmpty;
  692.     short clicked;
  693.     long inDirId;
  694.     
  695.     inDirId = (mh==GetMHandle(MAILBOX_MENU))? MyDirId : (*BoxMap)[(*mh)->menuID];
  696.     isFolder = IsItAFolder(MyVRef,inDirId,name);    
  697.     if (isFolder)
  698.         isEmpty = FolderFileCount(inDirId,name)<=0;
  699.     else
  700.     {
  701.         if (!(tocH=TOCByName(inDirId,name))) return(False);
  702.         if ((*tocH)->which)
  703.         {
  704.             WarnUser(MAYNT_DELETE_BOX,0);
  705.             return(False);
  706.         }
  707.         isEmpty = (*tocH)->count==0;
  708.     }
  709.     
  710.     if (!*andShutUp)
  711.     {
  712.         clicked = AlertStr(isEmpty?DELETE_EMPTY_ALRT:DELETE_NON_EMPTY_ALRT,
  713.                                              Caution,name);
  714.         if (clicked==4) *andShutUp = True;
  715.         else if (clicked!=2) return(False);
  716.     }
  717.     
  718.     if (isFolder)
  719.     {
  720.         short item = FindItemByName(mh,name); 
  721.         if (DeleteMailFolder(mh,item)) return(False);
  722.     }
  723.     else
  724.         RemoveMailbox(inDirId,name);
  725.     return(True);
  726. }
  727.  
  728. /************************************************************************
  729.  * DeleteMailFolder - delete a folder, including contents
  730.  ************************************************************************/
  731. short DeleteMailFolder(MenuHandle mh,short item)
  732. {
  733.     short err=0;
  734.     Str31 name;
  735.     Str31 boxName;
  736.     MenuHandle subMh;
  737.     long dirId = mh==GetMHandle(MAILBOX_MENU) ?
  738.                                              MyDirId :(*BoxMap)[(*mh)->menuID];
  739.     
  740.     MyGetItem(mh,item,name);
  741.     GetItemMark(mh,item,&item);
  742.     if (!item) return(FileSystemError(DELETING_BOX,name,fnfErr));
  743.     subMh = GetMHandle(item);
  744.     
  745.     for (item=CountMItems(subMh);item;item--)
  746.         if (HasSubmenu(subMh,item))
  747.         {
  748.             if (err=DeleteMailFolder(subMh,item)) return(err);
  749.         }
  750.         else
  751.         {
  752.             MyGetItem(subMh,item,boxName);
  753.             RemoveMailbox((*BoxMap)[(*subMh)->menuID],boxName);
  754.         }
  755.     
  756.     /*
  757.      * are we deleting or changing the index of a folder we're displaying?
  758.      */
  759.     {
  760.         short side;
  761.         for (side=0;side<=1;side++)
  762.             if (Sides[side].id==(*subMh)->menuID)
  763.                 SetSideIndices(side,mh);
  764.     }
  765.  
  766.     /*
  767.      * do the deletion
  768.      */
  769.     HSetVol(nil,MyVRef,MyDirId);
  770.     if (err=HDelete(MyVRef,dirId,name))
  771.         FileSystemError(DELETING_BOX,name,err);
  772.     if (err) return(err);
  773. }
  774.  
  775. /************************************************************************
  776.  * SetSideIndices - set the side information based on a menu
  777.  ************************************************************************/
  778. void SetSideIndices(short side, MenuHandle mh)
  779. {
  780.     Sides[side].menu = mh;
  781.     Sides[side].id = (*mh)->menuID;
  782.     Sides[side].dirId = DIRID_OF(Sides[side]);
  783. }
  784.  
  785. /************************************************************************
  786.  * 
  787.  ************************************************************************/
  788.  
  789. void DoMoveMailbox(UPtr selectName,short si)
  790. {
  791.     Str63 fromName;
  792.     Str15 suffix;
  793.     UPtr toName=nil;
  794.     long fromDirId, toDirId, finalDirId;
  795.     Cell c;
  796.     short err;
  797.     TOCHandle tocH;
  798.     
  799.     c.h = c.v = 0;
  800.     toDirId = finalDirId = DIRID_OF(Sides[1-si]);
  801.     fromDirId = DIRID_OF(Sides[si]);
  802.     for (c.h=c.v=0;LGetSelect(True,&c,Sides[si].list);c.v++)
  803.     {
  804.         MBGetData(fromName,c,Sides[si].list);
  805.         if (err=HMove(MyVRef,fromDirId,fromName+1,toDirId,toName))
  806.             {FileSystemError(MOVE_MAILBOX,fromName,err); return;}
  807.         PCat(fromName+1,GetRString(suffix,TOC_SUFFIX));
  808.         if ((err=HMove(MyVRef,fromDirId,fromName+1,toDirId,toName)) &&
  809.                 err!=fnfErr)
  810.             {FileSystemError(MOVE_MAILBOX,fromName,err); return;}
  811.         fromName[1] -= *suffix;
  812.         if (tocH=FindTOC(fromDirId,fromName+1))
  813.             (*tocH)->dirId = finalDirId;
  814.         PCopy(selectName,fromName);
  815.     }
  816. }
  817.  
  818. /************************************************************************
  819.  * MBFixSideIndices - make sure the id and dirId match for both sides
  820.  ************************************************************************/
  821. void MBFixSideIndices(void)
  822. {
  823.   short i,j,newid;
  824.   for (i=0;i<=1;i++)
  825.       if (DIRID_OF(Sides[i])!=Sides[i].dirId)
  826.         {
  827.             newid = MAILBOX_MENU;
  828.             for (j=0;j<GetHandleSize(BoxMap)/sizeof(short);j++)
  829.               if ((*BoxMap)[j]==Sides[i].dirId) {newid=j;break;}
  830.             SetSideIndices(i,GetMHandle(newid));
  831.         }
  832. }
  833.  
  834. /************************************************************************
  835.  * CellMenuId - find the menu id for a given cell in a list
  836.  ************************************************************************/
  837. short CellMenuId(Cell c,short whichSide)
  838. {
  839.     short item,id;
  840.     Str63 data;
  841.     
  842.     MBGetData(data,c,Sides[whichSide].list);
  843.     if (!data[0]) return(0);
  844.     item = FindItemByName(Sides[whichSide].menu,data+1);
  845.     GetItemMark(Sides[whichSide].menu,item,&id);
  846.     return(id);
  847. }
  848.  
  849. UPtr MBGetData(UPtr data,Cell c,ListHandle list)
  850. {
  851.     short junk=64;
  852.     LGetCell(data,&junk,c,list);
  853.     return(data);
  854. }
  855.  
  856. Boolean DontMove(void)
  857. {
  858.     short unSelId;
  859.     Cell c;
  860.     short si;
  861.     
  862.     if (FromSide.id==ToSide.id) return(True);
  863.     c.h = c.v = 0;
  864.     if (FirstSelected(&c,ToSide.list)) si = ToSideIndex;
  865.     else if (FirstSelected(&c,FromSide.list)) si = FromSideIndex;
  866.     else return(False);
  867.     
  868.     unSelId = Sides[1-si].id;
  869.     
  870.     do
  871.     {
  872.         if (CellMenuId(c,si)==unSelId) return(True);
  873.         c.v++;
  874.     }
  875.     while(LGetSelect(True,&c,Sides[si].list));
  876.  
  877.     return(False);
  878. }
  879.  
  880. void MBTickle(UPtr fromSelect,UPtr toSelect)
  881. {
  882.     if (MBG)
  883.     {
  884.         MBFixSideIndices();
  885.         (void) MBRefill(FromSideIndex,fromSelect);
  886.         (void) MBRefill(ToSideIndex,toSelect);
  887.     }
  888. }
  889.  
  890. #pragma segment Balloon
  891. /************************************************************************
  892.  * MBHelp - provide help for the mailbox window
  893.  ************************************************************************/
  894. void MBHelp(MyWindowPtr win,Point mouse)
  895. {
  896. #pragma unused(win);
  897.     Rect r;
  898.     short i;
  899.     short hnum=1;
  900.     
  901.     for (i=0;i<NSIDES;i++)
  902.     {
  903.         r = (*Sides[i].list)->rView;
  904.         r.right += GROW_SIZE;
  905.         if (PtInRect(mouse,&r))
  906.         {
  907.             HelpRect(&r,MBWIN_HELP_STRN+hnum,100);
  908.             return;
  909.         }
  910.     }
  911.     hnum++;
  912.     
  913.     for (i=0;i<ControlCount;i++,hnum+=2)
  914.     {
  915.         r = (*Controls[i])->contrlRect;
  916.         if (PtInRect(mouse,&r))
  917.         {
  918.             if ((*Controls[i])->contrlRfCon!='GREY') hnum++;
  919.             HelpRect(&r,MBWIN_HELP_STRN+hnum,100);
  920.             return;
  921.         }
  922.     }
  923. }
  924.  
  925. #pragma segment MboxWin
  926. /************************************************************************
  927.  * MBMenu - menu choice in the mailbox window
  928.  ************************************************************************/
  929. Boolean MBMenu(MyWindowPtr win, int menu, int item, short modifiers)
  930. {
  931. #pragma unused(win,modifiers)
  932.     
  933.     switch (menu)
  934.     {
  935.         case FILE_MENU:
  936.             switch(item)
  937.             {
  938.                 case FILE_OPEN_ITEM:
  939.                     MBListOpen(FromSideIndex);
  940.                     MBListOpen(ToSideIndex);
  941.                     return(True);
  942.                     break;
  943.             }
  944.             break;
  945.     }
  946.     return(False);
  947. }
  948.