home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / listpm2.zip / source / list.cpp < prev    next >
C/C++ Source or Header  |  1996-07-10  |  20KB  |  544 lines

  1. /*
  2.     listPM list files under Presentation Manager. Uses Open Class Libarary.
  3.     Copyright (C) 1996  Paul Elliott
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     Paul Elliott
  20.     3987 South Gessner #224
  21.     Houston Tx 77063
  22.     Paul.Elliott@Hrnowl.LoneStar.Org
  23. */
  24. #include "listpm.h"            // constants for resourse libarary.
  25.                                // do not edit listpm.h, but use URE to modify.
  26.  
  27. #include "list.hpp"            // List window defined.
  28. #include "listthrd.hpp"        // List threads defined
  29. #include "glbsize.hpp"         // How to store ISize externally.
  30. #include "glbfont.hpp"         // How to store IFont Externally.
  31. #include "glbwrap.hpp"         // How to save word wrap options.
  32.  
  33. #include "findmle.hpp"         // How to find text in MLE.
  34. #include "OneOf.hpp"           // define one of a kind of object at runtime.
  35. #include "IsDir.hpp"           // is file a directory?
  36.  
  37. // Global statics interfacing external storage.
  38. // we want One of these objects, but they must be initializied
  39. // after application argc argv are set.
  40. static OneOf<SizeStore> resizer;                 // source of ISize
  41. static OneOf<ExternalFont> font_source;          // source of IFont s
  42. static OneOf<ExternalWrap> wrap_source;          // source of wrap booleans.
  43.  
  44. // main window consturctor.
  45. // mostly constructed via ctor.
  46. ListFrame::ListFrame( const IString file) :
  47.                   file_displayed(file),                        //save title
  48.                   // frame window from resource id & style
  49.                   IFrameWindow( WIN_UICLLISTER ,
  50.  
  51.                       IFrameWindow::defaultStyle() |          // default style
  52.                       IFrameWindow::shellPosition  |          // wps positions
  53.                       IFrameWindow::accelerator    |          // accelerator
  54.                       IFrameWindow::border         |          // and border
  55.                       IFrameWindow::menuBar        |          // and menu
  56.                       IFrameWindow::minimizedIcon  |          // icon for
  57.                                                               // minimization
  58.                       IFrameWindow::sizingBorder   |          // border sizing
  59.                       IFrameWindow::systemMenu     |          // system menu
  60.                       IFrameWindow::titleBar       ),         // with title bar
  61.  
  62.                   acc ( WIN_UICLLISTER , this),               // accelerator
  63.                   info(this),                                 // info area
  64.  
  65.                   // multiline edit field
  66.                   mle ( MLE_TEXT ,this , this, IRectangle(),
  67.                     (IMultiLineEdit::defaultStyle()           // default style
  68.                     | IMultiLineEdit::readOnly                // readonly
  69.                     | IMultiLineEdit::verticalScroll          // scroll vert
  70.                     | IMultiLineEdit::horizontalScroll ) ),   // edit client
  71.                   title( this, STR_TITLE ),                   // title bar
  72.                   help(ID_HELPTABLE,this),                    // attach help win
  73.                   search_dialog( *this , help )               // search dialog.
  74.  
  75. {   // code for constructor
  76.     ICommandHandler::handleEventsFor(this);       // attach command handler.
  77.     IMenuHandler::handleEventsFor(this);          // attach menu handler.
  78.     IResizeHandler::handleEventsFor(this);        // attach resize handler.
  79.  
  80.     SizeStore& l_resizer = resizer;               // get stoed window size
  81.     if (l_resizer.sizeExternal() )                // if an ISize is external
  82.     {
  83.         // get external size
  84.         ISize external_size( l_resizer );
  85.  
  86.         ISize current_size = external_size;
  87.  
  88.         // set window to that size
  89.         sizeTo(current_size);
  90.  
  91.         // code to insure that the window is positioned on the desk
  92.         // top if possible.
  93.  
  94.         // get size of desktop.
  95.         ISize desk_size = IWindow::desktopWindow()->size();
  96.  
  97.         // get position currently proposed.
  98.         IPoint current_position = position();
  99.  
  100.         // assume current position good.
  101.         IPoint new_position = current_position;
  102.  
  103.         if (                            // if positioning is possible!
  104.            // right of window is off screen
  105.            ( current_position.x() + current_size.width() >
  106.                desk_size.width() ) &&
  107.  
  108.            // the whole window will fit on the screen
  109.            ( current_size.width() <= desk_size.width() )
  110.            )
  111.          {
  112.             // degree of freedom in positioning.
  113.             int x_slop = desk_size.width() - current_size.width();
  114.  
  115.             // a plausible pull back from against the right wall.
  116.             int x_pullback = desk_size.width() / 10;
  117.             if ( x_pullback > x_slop) x_pullback = x_slop;
  118.  
  119.             // reanomize the pullback.
  120.             x_pullback *= float(rand()) / float(RAND_MAX) ;
  121.  
  122.             // new position is against right wall pulled back by random amount.
  123.             new_position.setX( x_slop - x_pullback );
  124.          };
  125.  
  126.         // this code is same as above except for doing y co-ordinate.
  127.         if (
  128.            // bottom of window is off screen
  129.            ( current_position.y() + current_size.height() >
  130.               desk_size.height() ) &&
  131.  
  132.            // the whole window will fit on the screen
  133.            ( current_size.height() <= desk_size.height() )
  134.            )
  135.         {
  136.             int y_slop = desk_size.height() - current_size.height();
  137.             int y_pullback = desk_size.height() / 10;
  138.             if ( y_pullback > y_slop) y_pullback = y_slop;
  139.             y_pullback *= float(rand()) / float(RAND_MAX) ;
  140.             new_position.setY( y_slop - y_pullback );
  141.         };
  142.  
  143.         // if we have decided to move the window, move it.
  144.         if ( new_position != current_position) moveTo( new_position );
  145.     };
  146.  
  147.     // if font is stored.
  148.     ExternalFont& l_font_source = font_source;
  149.     if ( l_font_source.FontExistsExternally() )
  150.     {
  151.         // then set the stored font.
  152.         mle.setFont( l_font_source );
  153.     };
  154.  
  155.     Boolean word_wrap = false;                  // assume no word wrap
  156.  
  157.     // if WW option stored.
  158.     ExternalWrap& l_wrap_source = wrap_source;
  159.     if ( l_wrap_source.wrapExternal() )
  160.     {
  161.          word_wrap = l_wrap_source;             // get WW option.
  162.     };
  163.     mle.enableWordWrap(word_wrap);              // set WW option into
  164.                                                 // edit client.
  165.  
  166.  
  167.     info.setText(file);                           // set info displayed
  168.                                                   // in info area
  169.     info.setInactiveText(file);                   // ditto, inactive
  170.     setClient( &mle );                            // set edit window as client
  171.  
  172.     help.addLibraries("listpm.hlp");              // library to use for help
  173.     help.setTitle(STR_EXENAME);                   // title of help library.
  174.     IHelpHandler::handleEventsFor(this);          // help handler.
  175.  
  176.  
  177.     // if requested file is accessable
  178.     if (file != "") if ( access(file,04) )
  179.     {
  180.       // if file is not accesable, complain bitterly and leave.
  181.       mle.setFocus();
  182.       show();
  183.       IMessageBox ( this )
  184.          .show(ERR_NOTREAD,IMessageBox::information);
  185.     }
  186.     else
  187.     {
  188.       // if accessable, load into client window.
  189.       mle.importFromFile(file, IMultiLineEdit::cfText );
  190.     };
  191.     mle.setCursorPosition ( 0 );                  // set cursor at 0,0
  192.     mle.setFocus();                               // give edit area focus, and
  193.     show();                                       // show.
  194.  
  195.  
  196. };
  197.  
  198. // command handler for main window.
  199. // this code overrides ICommandHandler, gets called
  200. // when command event caused by user from menu, accelerator.
  201. Boolean ListFrame::command( ICommandEvent& event )
  202. {
  203.  
  204.  
  205.    // classify the request.
  206.    switch (  event.commandId() )
  207.    {
  208.     // change font request
  209.     // user wants to change font.
  210.     case IDM_FONT:
  211.        {
  212.           // get current font
  213.           IFont font = mle.font();
  214.           // and store in the settings
  215.           IFontDialog::Settings fsettings( &font );
  216.           // set the title.
  217.           fsettings.setTitle(STR_FONTTITLE);
  218.           // create dialog to get the new font.
  219.           IFontDialog dlg(IWindow::desktopWindow(),this,
  220.                       IFontDialog::defaultStyle() |
  221.                       IFontDialog::resetButton,
  222.                       fsettings);
  223.           // when the constructor returns, dialog has run
  224.  
  225.           if(dlg.pressedOK() )                 // if user said ok.
  226.           {
  227.              mle.setFont(font);                // store new font
  228.  
  229.              // ask user if he want to store this new font as the new default.
  230.              // create message box.
  231.              IMessageBox msg(this);
  232.              if (
  233.                   msg.show(STR_DEFAULTFONT,
  234.                             IMessageBox::queryIcon |
  235.                             IMessageBox::yesNoButton ) ==
  236.                     IMessageBox::yes
  237.                 )
  238.               {
  239.                 // store the new font.
  240.                 ExternalFont(font_source) << font;
  241.               };
  242.           };
  243.           return true;                         // we have handled.
  244.        };
  245.  
  246.     // word wrap on request.
  247.     case IDM_ON:
  248.        {
  249.           // set word wrap if not already.
  250.           if( ! mle.isWordWrap() ) mle.enableWordWrap();
  251.  
  252.           // record word wrapping;
  253.           ExternalWrap(wrap_source) << true;
  254.           return true;     // we have handled.
  255.        };
  256.  
  257.     // word wrap off request.
  258.     case IDM_OFF:
  259.        {
  260.           // if on turn it off
  261.           if( mle.isWordWrap() ) mle.disableWordWrap();
  262.  
  263.           // record no word wrapping;
  264.           ExternalWrap(wrap_source) << false;
  265.           return true;
  266.        };
  267.  
  268.     // open new file on new window request.
  269.     // user wants to open a new file.
  270.     case IDM_OPENNEW :
  271.        {
  272.           char fullfile[_MAX_PATH];            // space for full path name.
  273.  
  274.           // get full path of our current file
  275.           _fullpath(fullfile,file(),sizeof(fullfile));
  276.  
  277.           // fields to break path into
  278.           char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
  279.  
  280.           // break fullpath into fields
  281.           _splitpath(fullfile,drive,dir,fname,ext);
  282.  
  283.           char usepath[_MAX_PATH];             // space for path to use.
  284.  
  285.           // create path to use, with wild card filename.
  286.           _makepath(usepath,drive,dir,"*","");
  287.  
  288.           // declare settings.
  289.           IFileDialog::Settings fsettings;
  290.  
  291.           // set the indicated file name to search for
  292.           fsettings.setFileName( usepath );
  293.  
  294.           // set the ititial drive as has been discovered.
  295.           fsettings.setInitialDrive(drive);
  296.  
  297.           // set title of the  get file name dialog.
  298.           fsettings.setTitle(STR_TITLENEW);
  299.  
  300.           // dialog is to get an existing file.
  301.           fsettings.setOpenDialog();
  302.  
  303.           // declare the dialog on the current frame, with the settings.
  304.           IFileDialog dlg( IWindow::desktopWindow(), this,
  305.                 IFileDialog::defaultStyle(),
  306.                 fsettings);
  307.           // The above call will return when the above modal dialog
  308.           // has already run.
  309.  
  310.           // set the focus back to our edit ring.
  311.           mle.setFocus();
  312.  
  313.           // if the dialog ran successfully.
  314.           if ( dlg.pressedOK() )
  315.           {
  316.              // for each file selected by the dialog.
  317.              for(int i=0; i< dlg.selectedFileCount() ; i++)
  318.              {
  319.                // start a whole new thread to handle the new frame.
  320.                // the new ListThreadFn will be stored in a managed pointer
  321.                // and will be destroyed when the thread exits!
  322.                IThread list ( new ListThreadFn ( dlg.fileName(i) ) );
  323.              };
  324.           };
  325.           return true;                         // Have handled.
  326.           break;
  327.        };
  328.  
  329.     // user wants to Open new file in the current window.
  330.     case IDM_REPLACEFILE:
  331.        {
  332.           // space for the fullfile name in the dialog.
  333.           char fullfile[_MAX_PATH];
  334.  
  335.           // create the fullpath of the current file.
  336.           _fullpath(fullfile, file(),sizeof(fullfile));
  337.  
  338.           // space to store the parts of the current file.
  339.           char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
  340.  
  341.           // split the file into parts.
  342.           _splitpath(fullfile,drive,dir,fname,ext);
  343.  
  344.           // space to store desired file
  345.           char usepath[_MAX_PATH];
  346.  
  347.           // make a wild card file path.
  348.           _makepath(usepath,drive,dir,"*","");
  349.  
  350.           // settings for the dialog.
  351.           IFileDialog::Settings fsettings;
  352.  
  353.           // set files to chose from. all
  354.           fsettings.setFileName( usepath );
  355.  
  356.           // set the initial drive discovered.
  357.           fsettings.setInitialDrive(drive);
  358.  
  359.           // set the title of this dialog.
  360.           fsettings.setTitle(STR_TITLEREPLACE);
  361.  
  362.           // This is an open dialog, choose amoung existing files.
  363.           fsettings.setOpenDialog();
  364.  
  365.  
  366.           // returned OK, is it directroy name of file which is chosen.
  367.           Boolean is_dir , ok ;
  368.           IString chosen_file;
  369.  
  370.           do
  371.           {
  372.              // create the dialog.
  373.              IFileDialog dlg( IWindow::desktopWindow(), this,
  374.                 IFileDialog::defaultStyle() ,
  375.                 fsettings);
  376.              // constructor will return when dialog has run to completion.
  377.  
  378.              ok =  dlg.pressedOK();
  379.  
  380.              if ( ok ) chosen_file = dlg.fileName();
  381.  
  382.              is_dir =  dlg.pressedOK() && IsDir( dlg.fileName() ) ;
  383.  
  384.              if (is_dir) fsettings.setFileName( ( chosen_file + "\\*" ) );
  385.  
  386.           } while ( is_dir );
  387.  
  388.           // if the dialog ran ok.
  389.           if ( ok )
  390.           {
  391.  
  392.              if ( access(chosen_file,04) )             // is it accessable?
  393.              {
  394.                 // if file is not accesable, complain bitterly and leave.
  395.                 IMessageBox ( this )
  396.                 .show(ERR_NOTREAD,IMessageBox::information);
  397.              }
  398.              else
  399.              {
  400.                 mle.hide();                            // hide the client while
  401.                 mle.removeAll();                       // we remove all the
  402.                                                        // lines.
  403.                 // import all lines from
  404.                 mle.importFromFile( chosen_file,
  405.                      IMultiLineEdit::cfText );         // the selected file.
  406.  
  407.                 file_displayed = chosen_file;          // save current filename.
  408.                 mle.setCursorPosition ( 0 );           // set position=0,0
  409.  
  410.                 info.setText( chosen_file );           // set the filename
  411.                 info.setInactiveText( chosen_file );   // in the info area.
  412.                 mle.show();                            // show edit area again.
  413.              };
  414.           };
  415.  
  416.           // set the focus new edit area
  417.           mle.setFocus();
  418.           return true;                                 // yes, handled.
  419.           break;
  420.        };
  421.  
  422.     // copy to clipboard request.     CTRL+ins
  423.     case IDM_COPYTOCLIPBOARD :
  424.        {
  425.  
  426.  
  427.           // if no text selected, done
  428.           if ( ! mle.hasSelectedText() ) return true;
  429.  
  430.           // get the clipboard window.
  431.           IClipboard clipboard(event.window()->handle());
  432.  
  433.           // empty the clipboard.
  434.           clipboard.empty();
  435.  
  436.           // move in the selected event
  437.           clipboard.setText(mle.selectedText());
  438.           return true;  // we have handled.
  439.           break;
  440.        };
  441.  
  442.     // Handle  all items that display help but are not handled by help system.
  443.     case IDM_COPYRIGHT :
  444.     case IDM_GNUPUBLICLICENCE :
  445.     case IDM_PROGRAMAUTHOR :
  446.        // We require that the item number for these items must be ==
  447.        // the panel ID # this requirement is met in resource editor
  448.        // and ipf editor. We check that it has been met hare.
  449.        {                                               // show help page.
  450.           #if !( (  IDM_COPYRIGHT == Copyright ) && \
  451.                  (  IDM_GNUPUBLICLICENCE == GNU ) && \
  452.                  ( IDM_PROGRAMAUTHOR == Author)      )
  453.           #error Resource ID must be equal to panel ID for app help items.
  454.           #endif
  455.  
  456.           // display the help.
  457.           help.show(IResourceId( event.commandId() ));
  458.           return true;                                 // handled
  459.           break;
  460.        };
  461.  
  462.     // user wants search for text in the mle
  463.     case IDM_SEARCH :
  464.  
  465.        //     get search parameters from user.
  466.  
  467.        // run the search dialog.
  468.        search_dialog.GetToBeSearched();
  469.  
  470.        // deliberate FALLTHRU !!!!!!!
  471.  
  472.     // user wants to search for text string again.
  473.     case IDM_AGAIN :                                   // search for text again.
  474.        {
  475.           // get text to search for
  476.           IString search_string = search_dialog;
  477.  
  478.           // get exact case match parameter.
  479.           Boolean exact_case = search_dialog.Exact();
  480.  
  481.           // get direction of search.
  482.           Boolean forward_direction = search_dialog.DirectionForward();
  483.  
  484.           // search for the text.
  485.           FindMle(mle, forward_direction, exact_case, search_string);
  486.           break;
  487.        };
  488.  
  489.     // the unspecified case.
  490.     default:
  491.        {
  492.           // default do the default handler and return.
  493.           return ICommandHandler::command(event);
  494.        };
  495.    };
  496.    return false;                               // assume we have handled.
  497. };   //  Boolean ListFrame::command( ICommandEvent& event )
  498.  
  499. //
  500. // this handler called when the word wrap menu opened.
  501. // overrides from IMenuHandler. called when Word wrap submenu
  502. // is opened.
  503. Boolean ListFrame::menuShowing ( IMenuEvent& event,ISubmenu& submenu)
  504. {
  505.    // if word wrap menu called.
  506.    if (submenu.id() == IDM_WORDWRAP )
  507.    {
  508.       // is word wrap on?
  509.       Boolean wrap_on = mle.isWordWrap();
  510.  
  511.       // word wrap is of is opposite.
  512.       Boolean wrap_off = !wrap_on;
  513.  
  514.       // set items checked approapiately
  515.       submenu.checkItem(IDM_ON,wrap_on);
  516.       submenu.checkItem(IDM_OFF,wrap_off);
  517.    };
  518.    // pass on to default handler.
  519.    return IMenuHandler::menuShowing( event, submenu);
  520. };
  521.  
  522. // overrides IResizeHandler is called when main frame is resized.
  523. // bug bug bug
  524. // we should only save new size on SHIFT drag, but How do we
  525. // distinguish this case??
  526. // If you know the answer email paul.elliott@hrnowl.lonestar.org
  527.  
  528. Boolean ListFrame::windowResize(IResizeEvent& evt)
  529. {
  530.    SizeStore(resizer) << evt.newSize();   // Save new size.
  531.    return false;                          // we did not handle, only hooked.
  532. };
  533.  
  534. // overides IHelpHander.
  535. // get s called to find out context help for this window.
  536. // tells keys help what panel to use.
  537. Boolean ListFrame::keysHelpId(IEvent& evt)
  538. {
  539.    int panel = KeysHelp;                  // panel for Keys Help.
  540.    evt.setResult( panel );                // set the panel to use.
  541.    return true;                           // we have handled.
  542. };
  543.  
  544.