home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / windows / c / fldrvw / folders.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-27  |  30.3 KB  |  1,310 lines

  1. /********************************************************************/
  2. /*            Folder View - Drag and drop directory viewer          */
  3. /*               Public Domain (P) 1992  Benjamin Cooley            */
  4. /*               folders.cpp - FolderView Folder Classes            */
  5. /********************************************************************/
  6.  
  7. #include "include.h"
  8. #pragma hdrstop
  9.  
  10. #include "fldrview.h"
  11.  
  12. static PTFolderView MatchSkipView = NULL;
  13.  
  14. /*****************************************/
  15. /* TMainView - Main folder window object */
  16. /*****************************************/
  17.  
  18. TStreamableClass RegMainView("MainView", TMainView::build, __DELTA(TMainView));
  19.  
  20. TMainView::TMainView(Pchar APath)
  21.   : TMDIFrame(APath, MNU_Main)
  22. {
  23.     ChildMenuPos = 2;
  24.  
  25.     strcpy(title, APath);
  26.     if (title[strlen(title) - 1] != '\\')
  27.     {
  28.         Pchar ptr = title + strlen(title) - 1;
  29.         while (ptr != title && *ptr != '\\') ptr--;
  30.         ptr++;
  31.         char save = *ptr;
  32.         *ptr = NULL;
  33.         strcpy(dir, title);
  34.         *ptr = save;
  35.         strcpy(wildcard, ptr);
  36.     }
  37.     else
  38.     {
  39.         strcpy(dir, title);
  40.         wildcard[0] = NULL;
  41.     }
  42.  
  43.     FolderView = this;
  44.     focusedicon = NULL;
  45.             
  46.   /* Allocate all icon */
  47.     alliconsarray = new TkUnsortedArray(0, 0, 50);
  48.  
  49.   /* Create Other View */
  50.     otherview = new TFolderView(this, "Other Files", "*.*");
  51. }
  52.  
  53. #pragma argsused
  54. TMainView::TMainView(StreamableInit s)
  55.   : TMDIFrame("", MNU_Main)
  56. {
  57.     ChildMenuPos = 2;
  58.  
  59.     title[0] = NULL;
  60.     dir[0] = NULL;
  61.     wildcard[0] = NULL;
  62.  
  63.     FolderView = this;
  64.     focusedicon = NULL;
  65.  
  66.   /* Initialize all icon array */
  67.     alliconsarray = NULL;
  68. }
  69.  
  70. TMainView::~TMainView()
  71. {
  72.     alliconsarray->flush(TShouldDelete::Delete);
  73.     delete alliconsarray;
  74. }
  75.  
  76. void TMainView::SetupWindow()
  77. {
  78.     TMDIFrame::SetupWindow();
  79.  
  80.     SetCaption(title);
  81.     UpdateAllIcons();
  82. }
  83.  
  84. void TMainView::ShutDownWindow()
  85. {
  86.     ShuttingDown = TRUE;
  87.  
  88.     SaveWindow();
  89.     
  90.     TMDIFrame::ShutDownWindow();
  91. }
  92.  
  93. int TMainView::ViewType()
  94. {
  95.     if (strlen(dir) > 3) return FOLDERVIEW_DIRECTORY;
  96.         else return FOLDERVIEW_DRIVE;
  97. }
  98.  
  99. Pchar TMainView::GetClassName()
  100. {
  101.     if (ViewType() == FOLDERVIEW_DIRECTORY) return "FOLDERVIEW_DIR";
  102.         else if (ViewType() == FOLDERVIEW_DRIVE) return "FOLDERVIEW_DRIVE";
  103.         else return TMDIFrame::GetClassName();
  104. }
  105.  
  106. void TMainView::GetWindowClass(WNDCLASS _FAR &AWndClass)
  107. {
  108.     TMDIFrame::GetWindowClass(AWndClass);
  109.  
  110.     if (ViewType() == FOLDERVIEW_DIRECTORY)
  111.         AWndClass.hIcon = LoadIcon(
  112.             GetModule()->hInstance, MAKEINTRESOURCE(ICO_Directory));
  113.         else AWndClass.hIcon = LoadIcon(
  114.             GetModule()->hInstance, MAKEINTRESOURCE(ICO_HardDrive));
  115.     AWndClass.style |= CS_DBLCLKS;
  116. }
  117.  
  118. void TMainView::SaveWindow()
  119. {
  120.     char filepath[MAXPATH];
  121.     char filename[FILELEN];
  122.         
  123.   /* Find directory name (create new entry if one not already there) */
  124.     GetPrivateProfileString(ProfileDirectories, title, "",
  125.         filename, FILELEN, ProfileName);
  126.     if (!*filename)
  127.     {
  128.         ffblk affblk;
  129.  
  130.         int newfilenum = 0;
  131.         strcpy(filepath, FolderInfoPath);
  132.         strcat(filepath, FolderInfoWildcard);
  133.         int found = !findfirst(filepath, &affblk, 0);
  134.         while (found)
  135.         {
  136.             int filenum = atoi(affblk.ff_name + FolderInfoFileCountPos);
  137.             if (filenum > newfilenum) newfilenum = filenum;
  138.             found = !findnext(&affblk);
  139.         }
  140.         newfilenum++;
  141.         strcpy(filename, FolderInfoFileName);
  142.         char temp[10];
  143.         itoa(newfilenum + 10000, temp, 10);
  144.         memcpy(filename + FolderInfoFileCountPos,
  145.             temp + 5 - FolderInfoFileCountLen,
  146.             FolderInfoFileCountLen);
  147.     }
  148.  
  149.   /* Make sure directory exists */
  150.     strcpy(filepath, FolderInfoPath);
  151.     filepath[strlen(filepath) - 1] = NULL;
  152.     unsigned attr;
  153.     BOOL failed = FALSE;
  154.     if (_dos_getfileattr(filepath, &attr))
  155.     {
  156.         if (mkdir(filepath)) failed = TRUE;
  157.     } else if (!(attr & FA_DIREC)) failed = TRUE;
  158.     if (failed)
  159.     {
  160.         MessageBox(HWindow, "Couldn't create FLDRINFO directory. "
  161.             "Folder setup saved.", "FolderView",
  162.             MB_ICONSTOP | MB_OK);
  163.         return;
  164.     }
  165.  
  166.   /* Make filename and save file */
  167.     strcpy(filepath, FolderInfoPath);
  168.     strcat(filepath, filename);
  169.     ofpstream os(filepath, ios::out | ios::trunc);
  170.     if (!os.fail())
  171.     {
  172.         Pchar buf = new char[FILEBUFSIZE];
  173.         os.setbuf(buf, FILEBUFSIZE);
  174.         os << this;
  175.         os.close();
  176.         delete buf;
  177.     }
  178.     WritePrivateProfileString(
  179.            ProfileDirectories, title, filename, ProfileName);
  180.  
  181. }
  182.  
  183. int TMainView::FindAllIconIndex(Pchar name)
  184. {
  185.     for (int c = 0; c < NumAllIcons(); c++)
  186.     {
  187.         PTIcon icon = GetAllIcon(c);
  188.         if (!strcmp(name, icon->Name())) return c;
  189.     }
  190.     return -1;
  191. }
  192.  
  193. PTIcon TMainView::FindAllIcon(Pchar name)
  194. {
  195.     for (int c = 0; c < NumAllIcons(); c++)
  196.     {
  197.         PTIcon icon = GetAllIcon(c);
  198.         if (!strcmp(name, icon->Name())) return icon;
  199.     }
  200.     return NULL;
  201. }
  202.  
  203. PTFolderView TMainView::GetFileView(Pchar name, int attrib)
  204. {
  205.     PTFolderView view, firstview;
  206.     view = firstview = (PTFolderView)GetFirstChild();
  207.     if (view)
  208.     {
  209.         do
  210.         {
  211.             if (view != MatchSkipView)
  212.             {
  213.                 if (view != otherview)
  214.                     if (view->WildcardMatch(name, attrib)) return view;
  215.             }
  216.             view = (PTFolderView)view->Next();
  217.         } while (view != firstview);
  218.     }
  219.     return otherview;
  220. }
  221.  
  222. #pragma argsused
  223. static void ArrangeViewIcons(Pvoid view, Pvoid data)
  224. {
  225.     ((PTFolderView)((PTWindowsObject)view))->ArrangeIcons();
  226. }
  227.  
  228. void TMainView::ArrangeAllIcons()
  229. {
  230.     ForEach(ArrangeViewIcons, NULL);
  231.     ArrangeIcons();
  232. }
  233.  
  234. void TMainView::UpdateAllIcons(PTFolderView newview)
  235. {
  236.     int c;
  237.     PTIcon icon;
  238.     PTFolderView view;
  239.  
  240.   /* Save focus icon name */
  241.     char focusedname[FILELEN];
  242.     if (focusedicon)
  243.       strcpy(focusedname, focusedicon->Name());
  244.       else *focusedname = NULL;
  245.  
  246.     char dirbuf[MAXDIR];
  247.     Pchar ptr = stpcpy(dirbuf, title);
  248.     if (*(ptr - 1) == '\\') strcpy(ptr, "*.*");
  249.  
  250.     ffblk affblk;
  251.     PTkUnsortedArray newicons = new TkUnsortedArray(0, 0, 50);
  252.     BOOL *iconunchanged = new BOOL[NumAllIcons()];
  253.     memset(iconunchanged, 0, sizeof(BOOL) * NumAllIcons());
  254.  
  255.     int found = !findfirst(dirbuf, &affblk, FA_DIREC);
  256.     while (found)
  257.     {
  258.         if (affblk.ff_name[0] != '.')
  259.         {
  260.             strlwr(affblk.ff_name);
  261.             int iconindex = FindAllIconIndex(affblk.ff_name);
  262.             if (iconindex == -1)
  263.             {
  264.                 view = GetFileView(affblk.ff_name, affblk.ff_attrib);
  265.                 icon = TIcon::NewIcon(*view, affblk);
  266.                 newicons->add(*icon);
  267.             }
  268.             else
  269.             {
  270.                 icon = GetAllIcon(iconindex);
  271.                 if (!icon->FolderView()) // Set to new view if old view NULL
  272.                 {
  273.                     view = GetFileView(icon->Name(), icon->Attrib());
  274.                 }
  275.                 else                     // Check if should be in new view
  276.                 if (newview && newview->WildcardMatch(affblk.ff_name, affblk.ff_attrib))
  277.                     view = newview;
  278.                     else view = icon->FolderView();
  279.                 if (icon->ShouldUpdate(affblk) || icon->FolderView() != view)
  280.                 {
  281.                     icon = TIcon::NewIcon(*view, affblk);
  282.                     newicons->add(*icon);
  283.                 }
  284.                 else
  285.                 {
  286.                     iconunchanged[iconindex] = TRUE;
  287.                 }
  288.             }
  289.         }
  290.         found = !findnext(&affblk);
  291.     }
  292.  
  293.   /* Delete all changed icons */
  294.     for (c = NumAllIcons() - 1; c >= 0; c--)
  295.     {
  296.         if (!iconunchanged[c])
  297.         {
  298.             icon = GetAllIcon(c);
  299.             icon->FolderView()->DeleteIcon(icon);
  300.         }
  301.     }
  302.  
  303.   /* Add new icons */
  304.     for (c = 0; c < newicons->itemsInArray(); c++)
  305.     {
  306.         icon = &((RTIcon)((*newicons)[c]));
  307.         alliconsarray->add(*icon);
  308.         icon->FolderView()->AddIcon(icon);
  309.     }
  310.  
  311.   /* Delete intermediate arrays */
  312.     newicons->flush(TShouldDelete::NoDelete);
  313.     delete newicons;
  314.     delete iconunchanged;
  315.  
  316.   /* Reset focus icon */
  317.     focusedicon = NULL;
  318.     if (*focusedname)
  319.     {
  320.         focusedicon = FindAllIcon(focusedname);
  321.         if (focusedicon) FocusIcon(focusedicon);
  322.     }
  323.     if (!focusedicon && NumAllIcons() > 0)
  324.         FocusIcon(GetAllIcon(0));
  325.     ArrangeAllIcons();
  326. }
  327.  
  328. void TMainView::UpdateMenu(PTFolderView view)
  329. {
  330.     int sortorder = view->GetSortOrder();
  331.     int viewmode = view->GetView();
  332.  
  333.     HMENU menu = GetMenu(HWindow);
  334.     if (sortorder == SORT_BYNAME)
  335.       CheckMenuItem(menu, CM_SortByName, MF_BYCOMMAND | MF_CHECKED);
  336.       else CheckMenuItem(menu, CM_SortByName, MF_BYCOMMAND | MF_UNCHECKED);
  337.     if (sortorder == SORT_BYEXT)
  338.       CheckMenuItem(menu, CM_SortByExtension, MF_BYCOMMAND | MF_CHECKED);
  339.       else CheckMenuItem(menu, CM_SortByExtension, MF_BYCOMMAND | MF_UNCHECKED);
  340.     if (sortorder == SORT_BYDATE)
  341.       CheckMenuItem(menu, CM_SortByDateTime, MF_BYCOMMAND | MF_CHECKED);
  342.       else CheckMenuItem(menu, CM_SortByDateTime, MF_BYCOMMAND | MF_UNCHECKED);
  343.     if (sortorder == SORT_BYSIZE)
  344.       CheckMenuItem(menu, CM_SortBySize, MF_BYCOMMAND | MF_CHECKED);
  345.       else CheckMenuItem(menu, CM_SortBySize, MF_BYCOMMAND | MF_UNCHECKED);
  346.     if (sortorder == SORT_BYDESC)
  347.       CheckMenuItem(menu, CM_SortByDescription, MF_BYCOMMAND | MF_CHECKED);
  348.       else CheckMenuItem(menu, CM_SortByDescription, MF_BYCOMMAND | MF_UNCHECKED);
  349.  
  350.     if (viewmode == VIEW_ICON)
  351.       CheckMenuItem(menu, CM_ViewIcons, MF_BYCOMMAND | MF_CHECKED);
  352.       else CheckMenuItem(menu, CM_ViewIcons, MF_BYCOMMAND | MF_UNCHECKED);
  353.     if (viewmode == VIEW_NAME)
  354.       CheckMenuItem(menu, CM_ViewNames, MF_BYCOMMAND | MF_CHECKED);
  355.       else CheckMenuItem(menu, CM_ViewNames, MF_BYCOMMAND | MF_UNCHECKED);
  356.     if (viewmode == VIEW_ALL)
  357.       CheckMenuItem(menu, CM_ViewAll, MF_BYCOMMAND | MF_CHECKED);
  358.       else CheckMenuItem(menu, CM_ViewAll, MF_BYCOMMAND | MF_UNCHECKED);
  359. }
  360.  
  361. void TMainView::FocusIcon(PTIcon icon)
  362. {
  363.     if (icon == focusedicon) return;
  364.     if (focusedicon)
  365.         focusedicon->SetStateFlag(IS_FOCUSED, FALSE);
  366.     focusedicon = icon;
  367.     if (focusedicon)
  368.     {
  369.         focusedicon->SetStateFlag(IS_FOCUSED, TRUE);
  370.         focusedicon->FolderView()->ScrollToIcon(focusedicon);
  371.     }
  372. }
  373.  
  374. void TMainView::WMCommand(RTMessage Msg)
  375. {
  376.     PTDialog dialog;
  377.  
  378.     if (!Msg.LP.Lo)
  379.     {
  380.         switch (Msg.WParam)
  381.         {
  382.           case CM_SortByName:
  383.           case CM_SortByExtension:
  384.           case CM_SortByDateTime:
  385.           case CM_SortBySize:
  386.           case CM_SortByDescription:
  387.             if (ActiveChild)
  388.                 ((PTFolderView)ActiveChild)->
  389.                     MenuCommand(Msg.WParam);
  390.             break;
  391.           case CM_ViewIcons:
  392.           case CM_ViewNames:
  393.           case CM_ViewAll:
  394.             if (ActiveChild)
  395.                 ((PTFolderView)ActiveChild)->
  396.                     MenuCommand(Msg.WParam);
  397.             break;
  398.           case CM_About:
  399.             dialog = new TDialog(this, DLG_About);
  400.             GetModule()->ExecDialog(dialog);
  401.             break;
  402.           case CM_NewSubView:
  403.             struct {
  404.                 char title[MAXPATH];
  405.                 char wildcard[MAXPATH];
  406.             } buf;
  407.             dialog = new TDialog(this, DLG_NewSubView);
  408.             new TEdit(dialog, 101, MAXPATH);
  409.             new TEdit(dialog, 102, MAXPATH);
  410.             buf.title[0] = NULL;
  411.             buf.wildcard[0] = NULL;
  412.             dialog->SetTransferBuffer(&buf);
  413.             dialog->EnableTransfer();
  414.             if (GetModule()->ExecDialog(dialog) == IDOK)
  415.             {
  416.                 if (buf.title[0] == NULL)
  417.                     strcpy(buf.title, "SubView");
  418.                 if (buf.wildcard[0] == NULL)
  419.                     strcpy(buf.wildcard, "*.*"); 
  420.                 PTFolderView view = new TFolderView(this, buf.title, buf.wildcard);
  421.                 UpdateAllIcons(view);
  422.                 GetModule()->MakeWindow(view);
  423.             }
  424.             break;
  425.         }
  426.     }
  427.     TMDIFrame::WMCommand(Msg);
  428. }
  429.  
  430. static void SetAllMainViews(Pvoid view, Pvoid mainview)
  431. {
  432.     ((PTFolderView)((PTWindowsObject)view))->
  433.         SetMainView((PTMainView)mainview);
  434. }
  435.  
  436. Pvoid TMainView::read(Ripstream is)
  437. {
  438.     is.readString(title, TITLELEN);
  439.     is.readString(dir, MAXPATH);
  440.     is.readString(wildcard, MAXPATH);
  441.     BOOL iszoomed;
  442.     is >> Attr.X >> Attr.Y >> Attr.W >> Attr.H >> iszoomed;
  443.     if (iszoomed) Attr.Style |= WS_MAXIMIZE;
  444.         else Attr.Style &= ~((long)WS_MAXIMIZE);
  445.  
  446.     int numicons;
  447.     is >> numicons;
  448.     alliconsarray = new TkUnsortedArray(numicons + 25, 0, 50);
  449.     for (int c = 0; c < numicons; c++)
  450.     {
  451.         PTIcon icon = NULL;
  452.         is >> icon;
  453.         alliconsarray->add(*icon);
  454.     } 
  455.  
  456.     char filename[FILELEN];
  457.     is.readString(filename, FILELEN);
  458.     if (*filename) focusedicon = FindAllIcon(filename);
  459.  
  460.     GetChildren(is);
  461.     otherview = NULL;
  462.     is >> otherview;
  463.  
  464.     ForEach(SetAllMainViews, (Pvoid)this);
  465.  
  466.     return this;
  467. }
  468.  
  469. void TMainView::write(Ropstream os)
  470. {
  471.     os.writeString(title);
  472.     os.writeString(dir);
  473.     os.writeString(wildcard);
  474.     BOOL iszoomed;
  475.     if(HWindow) iszoomed = IsZoomed(HWindow);
  476.         else iszoomed = FALSE;
  477.     os << Attr.X << Attr.Y << Attr.W << Attr.H << iszoomed;
  478.  
  479.     os << (int)NumAllIcons();
  480.     for (int c = 0; c < NumAllIcons(); c++)
  481.     {
  482.         os << GetAllIcon(c);
  483.     }
  484.  
  485.     if (focusedicon)
  486.         os.writeString(focusedicon->Name());
  487.         else os.writeString("");
  488.  
  489.     PutChildren(os);
  490.     os << otherview;
  491.  
  492. }
  493.  
  494. /*************************************************/
  495. /* TFolderView - Subwindow in main folder window */
  496. /*************************************************/
  497.  
  498. TStreamableClass RegSubView("FolderView", TFolderView::build, __DELTA(TFolderView));
  499.  
  500. void TFolderView::InitFolderView()
  501. {
  502.  
  503.   /* Set Window Attributes */
  504.     Attr.Style |= WS_VSCROLL | WS_HSCROLL;
  505.  
  506.   /* Allocate new icon array */
  507.     oldfont = NULL;
  508.     sortorder = SORT_BYNAME;
  509.     view = VIEW_ICON;
  510.     displayitems = DISPLAY_NAME | DISPLAY_DESC | DISPLAY_DATE |
  511.       DISPLAY_TIME | DISPLAY_SIZE | DISPLAY_ATTRIB;
  512.  
  513.   /* Set up scroller */
  514.     Scroller = new TScroller(this, IconSpaceWidth, IconSpaceHeight, 0, 0);
  515.     Scroller->AutoMode = FALSE;
  516.     Scroller->TrackMode = FALSE;
  517. }
  518.  
  519. TFolderView::TFolderView(PTMainView AMainView, Pchar ATitle, Pchar AWildCard)
  520.   : TWindow(AMainView, ATitle)
  521. {
  522.  
  523.   /* Set Subview Attributes */
  524.     Attr.Style = WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_OVERLAPPED |
  525.         WS_VSCROLL | WS_HSCROLL | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
  526.  
  527.   /* Set Title */
  528.     strcpy(title, ATitle);
  529.     strcpy(wildcard, AWildCard);
  530.  
  531.   /* Init window */
  532.     InitFolderView();
  533.  
  534.   /* View icon array */
  535.     icons = new TkSortedArray(0, 0, 50);
  536.  
  537.   /* Set Main View */
  538.       mainview = AMainView;
  539.  
  540.   /* Set allicons pointer */
  541.     allicons = AMainView->AllIconsPtr();
  542. }
  543.  
  544. #pragma argsused
  545. TFolderView::TFolderView(StreamableInit s)
  546.   : TWindow(NULL, "")
  547. {
  548.     SetFlags(WB_MDICHILD, TRUE); // Make sure window is MDI child
  549.  
  550.   /* Set Subview Attributes */
  551.     Attr.Style = WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_OVERLAPPED |
  552.         WS_VSCROLL | WS_HSCROLL | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
  553.  
  554.   /* Set window desc */
  555.     title[0] = NULL;
  556.     wildcard[0] = NULL;
  557.  
  558.   /* Init window */
  559.     InitFolderView();
  560.  
  561.   /* Set pointers */
  562.     icons = NULL;
  563.     mainview = NULL;
  564.     allicons = NULL;
  565. }
  566.  
  567. TFolderView::~TFolderView()
  568. {
  569.     icons->flush(TShouldDelete::NoDelete);
  570.     delete icons;
  571. }
  572.  
  573. void TFolderView::ShutDownWindow()
  574. {
  575.     PTMainView mv = mainview; // Keep copy for use after shutdown
  576.  
  577.     if (!ShuttingDown) // If not closing all windows
  578.     {
  579.         MatchSkipView = this;
  580.         for (int c = 0; c < NumIcons(); c++)
  581.         {
  582.             PTIcon icon = GetIcon(c);
  583.             PTFolderView view = mainview->GetFileView(icon->Name(), icon->Attrib());
  584.              view->AddIcon(icon);
  585.         }
  586.         MatchSkipView = NULL;
  587.         icons->flush(TShouldDelete::NoDelete);
  588.     }
  589.  
  590.     TWindow::ShutDownWindow();
  591.  
  592.     if (!ShuttingDown) // If not closing all windows
  593.         mv->ArrangeAllIcons(); // Remember: can't use 'mainview' after
  594.                                // object has been deleted
  595.  
  596. }
  597.  
  598. Pchar TFolderView::GetClassName()
  599. {
  600.     return "FOLDERVIEW_VIEW";
  601. }
  602.  
  603. void TFolderView::GetWindowClass(WNDCLASS _FAR &AWndClass)
  604. {
  605.     TWindow::GetWindowClass(AWndClass);
  606.     AWndClass.style |= CS_DBLCLKS;
  607.     AWndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ICO_View));
  608. }
  609.  
  610. #define SHOWMODE_NORMAL (0)
  611. #define SHOWMODE_ZOOMED (1)
  612. #define SHOWMODE_ICON   (2)
  613.  
  614. Pvoid TFolderView::read(Ripstream is)
  615. {
  616.     is.readString(title, TITLELEN);
  617.     is.readString(wildcard, MAXPATH);
  618.     int showmode;
  619.     is >> Attr.X >> Attr.Y >> Attr.W >> Attr.H >>
  620.       showmode >> sortorder >> view >> displayitems;
  621.     if (showmode == SHOWMODE_ZOOMED) Attr.Style |= WS_MAXIMIZE;
  622.       else if (showmode == SHOWMODE_ICON) Attr.Style |= WS_MINIMIZE;
  623.       else Attr.Style &= ~((long)WS_MAXIMIZE | (long)WS_MINIMIZE);
  624.     int numicons;
  625.     is >> numicons;
  626.     icons = new TkSortedArray(numicons + 25, 0, 50);
  627.     for (int c = 0; c < numicons; c++)
  628.     {
  629.         PTIcon icon = NULL;
  630.         is >> icon;
  631.         icon->SetFolderView(this);
  632.         icons->add(*icon);
  633.     }
  634.     mainview = FolderView;
  635.  
  636.     return this;
  637. }
  638.  
  639. void TFolderView::write(Ropstream os)
  640. {
  641.     os.writeString(title);
  642.     os.writeString(wildcard);
  643.     int showmode = SHOWMODE_NORMAL;
  644.     if (HWindow)
  645.     {
  646.         if (IsZoomed(HWindow)) showmode = SHOWMODE_ZOOMED;
  647.           else if (IsIconic(HWindow)) showmode = SHOWMODE_ICON;
  648.     }
  649.     os << Attr.X << Attr.Y << Attr.W << Attr.H <<
  650.       showmode << sortorder << view << displayitems;
  651.     os << NumIcons();
  652.     for (int c = 0; c < NumIcons(); c++)
  653.     {
  654.         os << GetIcon(c);
  655.     }
  656. }
  657.  
  658. void TFolderView::SetMainView(PTMainView newmainview)
  659. {
  660.     mainview = newmainview;
  661.     allicons = mainview->AllIconsPtr();
  662. }
  663.  
  664. void TFolderView::SetScroller()
  665. {
  666.     if (!IsIconic(HWindow))
  667.     {
  668.         if (view == VIEW_ICON)
  669.         {
  670.             RECT R;
  671.             GetClientRect(HWindow, &R);
  672.             int lines = 0;
  673.             if (NumIcons() > 0)
  674.               lines =
  675.                 (GetIcon(NumIcons() - 1)->PosY() / IconSpaceHeight + 1) -
  676.                   (R.bottom / IconSpaceHeight);
  677.             Scroller->SetUnits(1, IconSpaceHeight);
  678.             Scroller->SetRange(0, lines);
  679.         }
  680.         else if (view == VIEW_NAME)
  681.         {
  682.             RECT R;
  683.             GetClientRect(HWindow, &R);
  684.             int columns = 0;
  685.             if (NumIcons() > 0)
  686.               columns =
  687.                 (GetIcon(NumIcons() - 1)->PosX() / IconNameWidth + 1) -
  688.                   (R.right / IconNameWidth);
  689.             if (columns < 1) columns = 0;
  690.             Scroller->SetUnits(IconNameWidth, 1);
  691.             Scroller->SetRange(columns, 0);
  692.         }
  693.         if (view == VIEW_ALL)
  694.         {
  695.             RECT R;
  696.             GetClientRect(HWindow, &R);
  697.             int lines = NumIcons() - (R.bottom / IconNameHeight);
  698.             if (lines < 1) lines = 0;
  699.             Scroller->SetUnits(1, IconNameHeight);
  700.             Scroller->SetRange(0, lines);
  701.         }
  702.  
  703.     }
  704. }
  705.  
  706. void TFolderView::SetupWindow()
  707. {
  708.     TWindow::SetupWindow();
  709.  
  710.     SetCaption(title);
  711.     ArrangeIcons();
  712.     mainview->UpdateMenu(this);
  713.      SetScroller();
  714. }
  715.  
  716. void TFolderView::AddIcon(PTIcon icon)
  717. {
  718.     icon->SetFolderView(this);
  719.     icons->add(*icon);
  720. }
  721.  
  722. void TFolderView::DetachIcon(PTIcon icon)
  723. {
  724.     int index = -1;
  725.     for (int c = 0; c < NumIcons(); c++)
  726.         if (GetIcon(c) == icon) index = c;
  727.     if (index >= 0) icons->detach(index, TShouldDelete::NoDelete);
  728.     icon->SetFolderView(NULL);
  729. }
  730.  
  731. void TFolderView::DeleteIcon(PTIcon icon)
  732. {
  733.     int c;
  734.  
  735.     int index = -1;
  736.     for (c = 0; c < NumIcons(); c++)
  737.         if (GetIcon(c) == icon) index = c;
  738.     if (index >= 0) icons->detach(index, TShouldDelete::NoDelete);
  739.     index = -1;
  740.     for (c = 0; c < mainview->NumAllIcons(); c++)
  741.         if (mainview->GetAllIcon(c) == icon) index = c;
  742.     if (index >= 0) (*allicons)->detach(index, TShouldDelete::Delete);
  743. }
  744.  
  745. void TFolderView::Paint(HDC PaintDC, PAINTSTRUCT &PaintInfo)
  746. {
  747.     TWindow::Paint(PaintDC, PaintInfo);
  748.  
  749.     HFONT oldfont = SelectObject(PaintDC, Font);
  750.  
  751.     for (int c = 0; c < NumIcons(); c++)
  752.     {
  753.         GetIcon(c)->Paint(PaintDC);
  754.     }
  755.  
  756.     SelectObject(PaintDC, oldfont);
  757. }
  758.  
  759. int TFolderView::GetAdjacentIcon(int startnum, int dir)
  760. {
  761.     int delta;
  762.     int numicons = NumIcons();
  763.     PTIcon start = GetIcon(startnum);
  764.     if ((dir == ADJACENTICON_LEFT) ||
  765.         (dir == ADJACENTICON_UP)) delta = -1;
  766.         else delta = 1;
  767.     int c = startnum + delta;
  768.     while (c >= 0 && c < numicons)
  769.     {
  770.         PTIcon icon = GetIcon(c);
  771.         switch (dir)
  772.         {
  773.           case ADJACENTICON_LEFT:
  774.             if (icon->PosX() < start->PosX())
  775.                 if (icon->PosY() <= start->PosY())
  776.                     return c;
  777.             break;
  778.           case ADJACENTICON_UP:
  779.             if (icon->PosY() < start->PosY())
  780.                 if (icon->PosX() <= start->PosX())
  781.                     return c;
  782.             break;
  783.           case ADJACENTICON_RIGHT:
  784.             if (icon->PosX() > start->PosX())
  785.                 if (icon->PosY() >= start->PosY())
  786.                     return c;
  787.             break;
  788.           case ADJACENTICON_DOWN:
  789.             if (icon->PosY() > start->PosY())
  790.                 if (icon->PosX() >= start->PosX())
  791.                     return c;
  792.             break;
  793.         }
  794.         c += delta;
  795.     }
  796.     return startnum;
  797. }
  798.  
  799. void TFolderView::ScrollToIcon(PTIcon icon)
  800. {
  801.     RECT w, *i;
  802.  
  803.     i = icon->GetRect();
  804.     GetClientRect(HWindow, &w);
  805.     int width = w.right;
  806.     int height = w.bottom;
  807.     OffsetRect(&w,
  808.         (int)(Scroller->XPos * Scroller->XUnit),
  809.         (int)(Scroller->YPos * Scroller->YUnit));
  810.  
  811.     int newposx = (int)Scroller->XPos;
  812.     int newposy = (int)Scroller->YPos;
  813.     if (i->left < w.left)
  814.         newposx = i->left / Scroller->XUnit;
  815.     else if (i->right > w.right)
  816.         newposx = (i->right + Scroller->XUnit - width)
  817.           / Scroller->XUnit;
  818.  
  819.     if (i->top < w.top)
  820.         newposy = i->top / Scroller->YUnit;
  821.     else if (i->bottom > w.bottom)
  822.         newposy = (i->bottom + Scroller->YUnit - height)
  823.           / Scroller->YUnit;
  824.  
  825.     if ((newposx != Scroller->XPos) ||
  826.         (newposy != Scroller->YPos))
  827.           Scroller->ScrollTo(newposx, newposy);
  828. }
  829.  
  830. void TFolderView::WMKeyDown(RTMessage Msg)
  831. {
  832.     if (FocusedIcon() &&
  833.       FocusedIcon()->FolderView() != this)
  834.     {
  835.         FocusedIcon()->FolderView()->WMKeyDown(Msg);
  836.         return;
  837.     }
  838.  
  839.     int focusednum = GetIconNumber(FocusedIcon());
  840.     if (focusednum < 0) return;
  841.  
  842.     switch (Msg.WParam)
  843.     {
  844.       case VK_LEFT:
  845.         focusednum = GetAdjacentIcon(focusednum, ADJACENTICON_LEFT);
  846.         break;
  847.       case VK_RIGHT:
  848.         focusednum = GetAdjacentIcon(focusednum, ADJACENTICON_RIGHT);
  849.         break;
  850.       case VK_UP:
  851.         focusednum = GetAdjacentIcon(focusednum, ADJACENTICON_UP);
  852.         break;
  853.       case VK_DOWN:
  854.         focusednum = GetAdjacentIcon(focusednum, ADJACENTICON_DOWN);
  855.         break;
  856.       case VK_HOME:
  857.         focusednum = 0;
  858.         break;
  859.       case VK_END:
  860.         focusednum = NumIcons() - 1;
  861.         break;
  862.       case VK_SPACE:
  863.         SelectIcons(GetIcon(focusednum), SELECT_MULTIPLE);
  864.         return;
  865.     }
  866.  
  867.     FocusIcon(GetIcon(focusednum));
  868. }
  869.  
  870. void TFolderView::WMSize(RTMessage Msg)
  871. {
  872.     if ( Msg.WParam == SIZENORMAL )
  873.     {
  874.         RECT WndRect;
  875.         GetWindowRect(HWindow, &WndRect);
  876.         Attr.H = WndRect.bottom - WndRect.top;
  877.         Attr.W = WndRect.right - WndRect.left;
  878.     }
  879.  
  880.     DefWndProc(Msg);
  881.  
  882.     SetScroller();
  883.     ArrangeIcons();
  884. }
  885.  
  886. void TFolderView::WMLButtonDown(RTMessage Msg)
  887. {
  888.     POINT p = MAKEPOINT(Msg.LParam);
  889.     p.x += (int)(Scroller->XPos * Scroller->XUnit);
  890.     p.y += (int)(Scroller->YPos * Scroller->YUnit);
  891.     PTIcon icon = OnIcon(p);
  892.     if (icon)
  893.     {
  894.         if (Msg.WParam & MK_SHIFT)
  895.           SelectIcons(icon, SELECT_RANGE);
  896.         else if (Msg.WParam & MK_CONTROL)
  897.           SelectIcons(icon, SELECT_MULTIPLE);
  898.         else
  899.           SelectIcons(icon, SELECT_SINGLE);
  900.  
  901.       /* Set MouseDown stuff */
  902.         MouseDown = TRUE;
  903.         MouseDownIcon = icon;
  904.         MouseDownIconX = p.x - icon->PosX() - IconLeft;
  905.         MouseDownIconY = p.y - icon->PosY() - IconTop;
  906.     }
  907. }
  908.  
  909. #pragma argsused
  910. void TFolderView::WMMouseMove(RTMessage Msg)
  911. {
  912.     if (MouseDown)
  913.     {
  914.         if (!Dragging)
  915.         {
  916.             Dragging = TRUE;
  917.             DragIconCursor =
  918.                 MouseDownIcon->CreateCursor(MouseDownIconX, MouseDownIconY);
  919.             DragCursor = DragIconCursor;
  920.             SetCursor(DragIconCursor);
  921.             SetCapture(HWindow);
  922.         }
  923.     }
  924. }
  925.  
  926. #pragma argsused
  927. void TFolderView::WMLButtonUp(RTMessage Msg)
  928. {
  929.     if (Dragging)
  930.     {
  931.         ReleaseCapture();
  932.         SetCursor(LoadCursor(NULL, IDC_ARROW));
  933.         if (DragIconCursor) DestroyCursor(DragIconCursor);
  934.     }
  935.     Dragging = FALSE;
  936.     MouseDown = FALSE;
  937. }
  938.  
  939. #pragma argsused
  940. void TFolderView::WMLButtonDblClk(RTMessage Msg)
  941. {
  942.     POINT p = MAKEPOINT(Msg.LParam);
  943.     p.x += (int)(Scroller->XPos * Scroller->XUnit);
  944.     p.y += (int)(Scroller->YPos * Scroller->YUnit);
  945.     PTIcon icon = OnIcon(p);
  946.     if (icon) icon->Open();
  947. }
  948.  
  949. int TFolderView::GetIconNumber(PTIcon icon)
  950. {
  951.     if (!icon) return -1;
  952.     int iconnum = -1;
  953.     int numicons = NumIcons();
  954.     if (numicons > 0)
  955.     {
  956.         int c = 0;
  957.         while ((GetIcon(c) != icon) && (c < numicons)) c++;
  958.         if (c < numicons) iconnum = c;
  959.     }
  960.     return iconnum;
  961. }
  962.  
  963. void TFolderView::MenuCommand(WORD command)
  964. {
  965.     switch (command)
  966.     {
  967.       case CM_SortByName:
  968.       case CM_SortByExtension:
  969.       case CM_SortByDateTime:
  970.       case CM_SortBySize:
  971.       case CM_SortByDescription:
  972.         SetSortOrder(command - CM_SortByName + 1);
  973.         break;
  974.       case CM_ViewIcons:
  975.       case CM_ViewNames:
  976.       case CM_ViewAll:
  977.         SetView(command - CM_ViewIcons + 1);
  978.         break;
  979.     }
  980. }
  981.  
  982. void TFolderView::WMMDIActivate(RTMessage Msg)
  983. {
  984.     TWindow::WMMDIActivate(Msg);
  985.  
  986.     if (Msg.WParam)
  987.         mainview->UpdateMenu(this);
  988. }
  989.  
  990. HDC TFolderView::GetDC()
  991. {
  992.     HDC dc = ::GetDC(HWindow);
  993.     oldfont = SelectObject(dc, Font);
  994.     SetViewportOrg(dc,
  995.         -(int)(Scroller->XPos * Scroller->XUnit),
  996.         -(int)(Scroller->YPos * Scroller->YUnit));
  997.     return dc;
  998. }
  999.  
  1000. void TFolderView::ReleaseDC(HDC dc)
  1001. {
  1002.     SelectObject(dc, oldfont);
  1003.     ::ReleaseDC(HWindow, dc);
  1004. }
  1005.  
  1006.  
  1007. int TFolderView::FindIconIndex(Pchar name)
  1008. {
  1009.     for (int c = 0; c < NumIcons(); c++)
  1010.     {
  1011.         PTIcon icon = GetIcon(c);
  1012.         if (!strcmp(name, icon->Name())) return c;
  1013.     }
  1014.     return -1;
  1015. }
  1016.  
  1017. PTIcon TFolderView::FindIcon(Pchar name)
  1018. {
  1019.     for (int c = 0; c < NumIcons(); c++)
  1020.     {
  1021.         PTIcon icon = GetIcon(c);
  1022.         if (!strcmp(name, icon->Name())) return icon;
  1023.     }
  1024.     return NULL;
  1025. }
  1026.  
  1027. void TFolderView::ArrangeIcons()
  1028. {
  1029.     if (!HWindow) return;
  1030.  
  1031.     RECT R, rect;
  1032.     GetClientRect(HWindow, &R);
  1033.  
  1034.     int x = R.left;
  1035.     int y = R.top;
  1036.  
  1037.     if (view == VIEW_ICON)
  1038.     {
  1039.         int c = 0;
  1040.         while (c < NumIcons())
  1041.         {
  1042.             rect.left = x;
  1043.             rect.top = y;
  1044.             rect.right = x + IconSpaceWidth - 1;
  1045.             rect.bottom = y + IconSpaceHeight - 1;
  1046.             GetIcon(c)->SetRect(rect);
  1047.             c++;
  1048.             x += IconSpaceWidth;
  1049.             if ((x + IconSpaceHeight - 1) > R.right)
  1050.             {
  1051.                 x = R.left;
  1052.                 y += IconSpaceHeight;
  1053.             }
  1054.         }
  1055.     }
  1056.  
  1057.     else if (view == VIEW_NAME)
  1058.     {
  1059.         int c = 0;
  1060.         while (c < NumIcons())
  1061.         {
  1062.             rect.left = x;
  1063.             rect.top = y;
  1064.             rect.right = x + IconNameWidth - 1;
  1065.             rect.bottom = y + IconNameHeight - 1;
  1066.             GetIcon(c)->SetRect(rect);
  1067.             c++;
  1068.             y += IconNameHeight;
  1069.             if ((y + IconNameHeight - 1) > R.bottom)
  1070.             {
  1071.                 y = R.top;
  1072.                 x += IconNameWidth;
  1073.             }
  1074.         }
  1075.     }
  1076.  
  1077.     else if (view == VIEW_ALL)
  1078.     {
  1079.         for (int c = 0; c < NumIcons(); c++)
  1080.         {
  1081.             rect.left = R.left;
  1082.             rect.top = y;
  1083.             rect.right = R.right - 1;
  1084.             rect.bottom = y + IconNameHeight - 1;
  1085.             GetIcon(c)->SetRect(rect);
  1086.             y += IconNameHeight;
  1087.         }
  1088.     }
  1089.  
  1090.     InvalidateRect(HWindow, NULL, TRUE);
  1091. }
  1092.  
  1093. void TFolderView::SetSortOrder(int neworder)
  1094. {
  1095.     sortorder = neworder;
  1096.  
  1097.     PTkSortedArray newicons = new TkSortedArray(0, 0, 50);
  1098.     for (int c = 0; c < NumIcons(); c++)
  1099.     {
  1100.         PTIcon icon = GetIcon(c);
  1101.         newicons->add(*icon);
  1102.     }
  1103.     icons->flush(TShouldDelete::NoDelete);
  1104.     delete icons;
  1105.     icons = newicons;
  1106.  
  1107.     ArrangeIcons();
  1108.     mainview->UpdateMenu(this);
  1109. }
  1110.  
  1111. void TFolderView::SetView(int newview)
  1112. {
  1113.     view = newview;
  1114.     if (view == VIEW_ICON)
  1115.         Scroller->SetUnits(IconSpaceWidth, IconSpaceHeight);
  1116.     else if (view == VIEW_NAME)
  1117.         Scroller->SetUnits(IconNameWidth, IconNameHeight);
  1118.     else if (view == VIEW_ALL)
  1119.         Scroller->SetUnits(1, IconNameHeight);
  1120.     Scroller->XPos = 0;
  1121.     Scroller->YPos = 0;
  1122.     SetScroller();
  1123.     ArrangeIcons();
  1124.     mainview->UpdateMenu(this);
  1125. }
  1126.  
  1127. PTIcon TFolderView::OnIcon(POINT p)
  1128. {
  1129.     for (int c = 0; c < NumIcons(); c++)
  1130.     {
  1131.         PTIcon icon = GetIcon(c);
  1132.         if (icon->PointOn(p))
  1133.             return icon;
  1134.     }
  1135.     return NULL;
  1136. }
  1137.  
  1138. void TFolderView::RedrawIcon(PTIcon icon)
  1139. {
  1140.     if (icon) icon->RedrawIcon();
  1141. }
  1142.  
  1143. void TFolderView::SelectIcons(PTIcon selicon, int mode)
  1144. {
  1145.     PTIcon icon;
  1146.     int c;
  1147.  
  1148.     switch (mode)
  1149.     {
  1150.       case SELECT_SINGLE:
  1151.         FocusIcon(NULL);
  1152.         for (c = 0; c < NumAllIcons(); c++)
  1153.         {
  1154.             icon = GetAllIcon(c);
  1155.             if (selicon == icon)
  1156.                 icon->SetState(icon->GetState() | IS_FOCUSED | IS_SELECTED);
  1157.                 else icon->SetState(icon->GetState() &
  1158.                   ~(IS_FOCUSED | IS_SELECTED));
  1159.         }
  1160.         FocusIcon(selicon);
  1161.         break;
  1162.       case SELECT_RANGE:
  1163.         BOOL select = FALSE;
  1164.         PTIcon ficon = FocusedIcon();
  1165.         FocusIcon(NULL);
  1166.         PTIcon sicon = selicon;
  1167.         for (c = 0; c < NumIcons(); c++)
  1168.         {
  1169.             icon = GetIcon(c);
  1170.             if (((icon == ficon) || (icon == sicon)) && !select)
  1171.             {
  1172.                 if ((icon == ficon) && (icon != sicon)) ficon = NULL;
  1173.                   else if ((icon == sicon) && (icon != ficon)) sicon = NULL;
  1174.                 select = TRUE;
  1175.             }
  1176.             if (select)
  1177.             {
  1178.                 if (icon == selicon)
  1179.                     icon->SetState(
  1180.                       icon->GetState() | IS_FOCUSED | IS_SELECTED);
  1181.                     else icon->SetState(
  1182.                       (icon->GetState() & ~IS_FOCUSED) | IS_SELECTED);
  1183.             }
  1184.             else
  1185.               icon->SetState(icon->GetState() & ~(IS_FOCUSED | IS_SELECTED));
  1186.             if (((icon == ficon) || (icon == sicon)) && select)
  1187.               select = FALSE;
  1188.         }
  1189.         FocusIcon(selicon);
  1190.         break;
  1191.       case SELECT_MULTIPLE:
  1192.         FocusIcon(NULL);
  1193.         int flags = selicon->GetState() | IS_FOCUSED;
  1194.         if (flags & IS_SELECTED) flags &= ~IS_SELECTED;
  1195.             else flags |= IS_SELECTED;
  1196.         selicon->SetState(flags);
  1197.         if (FocusedIcon())
  1198.           if (selicon != FocusedIcon())
  1199.             FocusedIcon()->SetState(FocusedIcon()->GetState() & ~IS_FOCUSED);
  1200.         FocusIcon(selicon);
  1201.         break;
  1202.     }
  1203. }
  1204.  
  1205. void TFolderView::SelectIcon(PTIcon icon)
  1206. {
  1207.     if (icon) icon->SetStateFlag(IS_SELECTED, TRUE);
  1208. }
  1209.  
  1210. void TFolderView::DeselectIcon(PTIcon icon)
  1211. {
  1212.     if (icon) icon->SetStateFlag(IS_SELECTED, FALSE);
  1213. }
  1214.  
  1215. void TFolderView::ToggleIconSelection(PTIcon icon)
  1216. {
  1217.     if (icon) icon->SetStateFlag(IS_SELECTED, !icon->GetStateFlag(IS_SELECTED));
  1218. }
  1219.  
  1220. BOOL TFolderView::WildcardMatch(Pchar name, int attrib)
  1221. {
  1222.     Pchar wild = wildcard;
  1223.     Pchar file;
  1224.     BOOL filenot;
  1225.     BOOL match = FALSE;
  1226.  
  1227.     while (*wild)
  1228.     {
  1229.         while (*wild && *wild == ' ') wild++;
  1230.         if (*wild == '-')
  1231.         {
  1232.             filenot = TRUE;
  1233.             wild++;
  1234.         } else filenot = FALSE;     
  1235.  
  1236.         file = name;
  1237.         while (*file && *wild)
  1238.         {
  1239.  
  1240.             if (*file == '.')
  1241.             {
  1242.                 file++;
  1243.                 while (*wild && *wild != '.') wild++;
  1244.                 if (*wild) wild++;
  1245.             }
  1246.  
  1247.             if (*wild == '(')
  1248.             {
  1249.                 if (attrib == FA_DIREC && !strcmp(wild, "(dir)"))
  1250.                 {
  1251.                     wild += 5;
  1252.                     goto matched;
  1253.                 }
  1254.                 else if (attrib == FA_SYSTEM && !strcmp(wild, "(system)"))
  1255.                 {
  1256.                     wild += 8;
  1257.                     goto matched;
  1258.                 }
  1259.                 else if (attrib == FA_HIDDEN && !strcmp(wild, "(hidden)"))
  1260.                 {
  1261.                     wild += 8;
  1262.                     goto matched;
  1263.                 }
  1264.                 else if (attrib == FA_RDONLY && !strcmp(wild, "(rdonly)"))
  1265.                 {
  1266.                     wild += 8;
  1267.                     goto matched;
  1268.                 }
  1269.                 else if (attrib == FA_ARCH && !strcmp(wild, "(archive)"))
  1270.                 {
  1271.                     wild += 9;
  1272.                     goto matched;
  1273.                 }
  1274.             }
  1275.  
  1276.             if (*wild == '*')
  1277.             {
  1278.                 file++;
  1279.             }
  1280.             else if (*wild == '?')
  1281.             {
  1282.                 wild++;
  1283.                 file++;
  1284.             }
  1285.             else if (*wild != *file)
  1286.             {
  1287.                 goto failed;
  1288.             }
  1289.             else
  1290.             {
  1291.                 wild++;
  1292.                 file++;
  1293.             }
  1294.         }
  1295.         while (*wild && *wild == '?') wild++;
  1296.         if (*wild == '*') wild++;
  1297.         if ((*wild != ' ') &&
  1298.             (*wild != *file)) goto failed;
  1299.  
  1300. matched:
  1301.         if (filenot) match = FALSE;
  1302.             else match = TRUE;
  1303.  
  1304. failed:
  1305.         while (*wild && *wild != ' ') wild++;
  1306.     }
  1307.  
  1308.     return match;
  1309. }
  1310.