home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
listpm3.zip
/
source
/
list.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-11
|
26KB
|
749 lines
/*
listPM list files under Presentation Manager. Uses Open Class Libarary.
Copyright (C) 1996 Paul Elliott
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Paul Elliott
3987 South Gessner #224
Houston Tx 77063
Paul.Elliott@Hrnowl.LoneStar.Org
*/
#include "listpm.h" // constants for resourse libarary.
// do not edit listpm.h, but use URE to modify.
#include "list.hpp" // List window defined.
#include "glbsize.hpp" // How to store ISize externally.
#include "glbfont.hpp" // How to store IFont Externally.
#include "glbwrap.hpp" // How to save word wrap options.
#include "listthrd.hpp" // List threads defined
#include "OneOf.hpp" // define one of a kind of object at runtime.
#include "IsDir.hpp" // is file a directory?
#include <iapp.hpp>
// manipulate files.
#include <iostream.h>
#include <iomanip.h>
#include <fstream.h>
// Global statics interfacing external storage.
// we want One of these objects, but they must be initializied
// after application argc argv are set.
static OneOf<SizeStore> resizer; // source of ISize
static OneOf<ExternalFont> font_source; // source of IFont s
static OneOf<ExternalWrap> wrap_source; // source of wrap booleans.
// main window consturctor.
// mostly constructed via ctor.
ListFrame::ListFrame( const IString file) :
file_displayed(file), //save title
// frame window from resource id & style
IFrameWindow( WIN_UICLLISTER ,
IFrameWindow::defaultStyle() | // default style
IFrameWindow::shellPosition | // wps positions
IFrameWindow::accelerator | // accelerator
IFrameWindow::border | // and border
IFrameWindow::menuBar | // and menu
IFrameWindow::minimizedIcon | // icon for
// minimization
IFrameWindow::sizingBorder | // border sizing
IFrameWindow::systemMenu | // system menu
IFrameWindow::titleBar ), // with title bar
acc ( WIN_UICLLISTER , this), // accelerator
info(this), // info area
// multiline edit field
mle ( MLE_TEXT ,this , this, IRectangle(),
(IMultiLineEdit::defaultStyle() // default style
| IMultiLineEdit::readOnly // readonly
| IMultiLineEdit::verticalScroll // scroll vert
| IMultiLineEdit::horizontalScroll ) ), // edit client
title( this, STR_TITLE ), // title bar
help(ID_HELPTABLE,this), // attach help win
search_dialog( *this , help ), // search dialog.
win_thread(*this,IDM_SEARCHNOT,mle,info) // window
// threader.
{ // code for constructor
ICommandHandler::handleEventsFor(this); // attach command handler.
IMenuHandler::handleEventsFor(this); // attach menu handler.
IResizeHandler::handleEventsFor(this); // attach resize handler.
SizeStore& l_resizer = resizer; // get stoed window size
if (l_resizer.sizeExternal() ) // if an ISize is external
{
// get external size
ISize external_size( l_resizer );
ISize current_size = external_size;
// set window to that size
sizeTo(current_size);
// code to insure that the window is positioned on the desk
// top if possible.
// get size of desktop.
ISize desk_size = IWindow::desktopWindow()->size();
// get position currently proposed.
IPoint current_position = position();
// assume current position good.
IPoint new_position = current_position;
if ( // if positioning is possible!
// right of window is off screen
( current_position.x() + current_size.width() >
desk_size.width() ) &&
// the whole window will fit on the screen
( current_size.width() <= desk_size.width() )
)
{
// degree of freedom in positioning.
int x_slop = desk_size.width() - current_size.width();
// a plausible pull back from against the right wall.
int x_pullback = desk_size.width() / 10;
if ( x_pullback > x_slop) x_pullback = x_slop;
// reanomize the pullback.
x_pullback *= float(rand()) / float(RAND_MAX) ;
// new position is against right wall pulled back by random amount.
new_position.setX( x_slop - x_pullback );
};
// this code is same as above except for doing y co-ordinate.
if (
// bottom of window is off screen
( current_position.y() + current_size.height() >
desk_size.height() ) &&
// the whole window will fit on the screen
( current_size.height() <= desk_size.height() )
)
{
int y_slop = desk_size.height() - current_size.height();
int y_pullback = desk_size.height() / 10;
if ( y_pullback > y_slop) y_pullback = y_slop;
y_pullback *= float(rand()) / float(RAND_MAX) ;
new_position.setY( y_slop - y_pullback );
};
// if we have decided to move the window, move it.
if ( new_position != current_position) moveTo( new_position );
};
// if font is stored.
ExternalFont& l_font_source = font_source;
if ( l_font_source.FontExistsExternally() )
{
// then set the stored font.
mle.setFont( l_font_source );
};
Boolean word_wrap = false; // assume no word wrap
// if WW option stored.
ExternalWrap& l_wrap_source = wrap_source;
if ( l_wrap_source.wrapExternal() )
{
word_wrap = l_wrap_source; // get WW option.
};
mle.enableWordWrap(word_wrap); // set WW option into
// edit client.
info.setText(file); // set info displayed
// in info area
info.setInactiveText(file); // ditto, inactive
setClient( &mle ); // set edit window as client
help.addLibraries("listpm.hlp"); // library to use for help
help.setTitle(STR_EXENAME); // title of help library.
IHelpHandler::handleEventsFor(this); // help handler.
// if requested file is accessable
if (file != "") if ( access(file,04) )
{
// if file is not accesable, complain bitterly and leave.
mle.setFocus();
show();
IMessageBox ( this )
.show(ERR_NOTREAD,IMessageBox::information);
}
else
{
// if accessable, load into client window.
import( file);
};
mle.setCursorPosition ( 0 ); // set cursor at 0,0
mle.setFocus(); // give edit area focus, and
show(); // show.
};
// optional call back to user before running thread.
// to search for text.
void ListWindowThread::begin()
{
OurWindow().disable();
mle.disableUpdate(); // freeze updates on screen
info.setFocus();
saved_text = info.text();
info.setText(
IApplication::current().userResourceLibrary().loadString(STR_SEARCH)
+ ": " + search_string);
if ( exact ) // depends on exact case.
looked_for = search_string;
else
looked_for = IString::upperCase(search_string);
// if not exact case then always work with upcased strings.
// for both target text and examined text.
if(forward)
{
direction_sign = direction_mult =1;
dir_search = I0String::indexOf; // forward search fn
start_pos = 0; // starting pos for fn.
limit = mle.numberOfLines() - 1 ; // last line to look at.
}
else
{
direction_sign = -1;
direction_mult = 0;
dir_search = I0String::lastIndexOf; // reverse search fn.
start_pos = UINT_MAX - 1; // starting pos for fn.
limit = 0; // last line to look at.
};
// the current line we are on.
current_line_no = mle.cursorLinePosition();
// save the current position.
current_pos = mle.cursorPosition();
// set the cursor to the begining of this line.
mle.setCursorLinePosition( current_line_no );
// mark beginning of this line.
current_bol = mle.cursorPosition();
// put cursor position back where it was.
mle.setCursorPosition(current_pos);
};
// code to run on other thread. When searching for text.
void ListWindowThread::thread()
{
// offset of our cursor in this line.
offset_within_current_line = current_pos - current_bol;
// get text of current line.
current_line = mle.text(current_line_no);
// the fragment of line we are looking at.
if ( forward )
{
// offset of the fragment within the current line
offset = offset_within_current_line;
// get the relevant fragment of current line = the end.
line =
current_line.subString( offset_within_current_line );
}
else
{
// fragment starts at begin
offset = 0;
// get the relevant fragment of current line = the beginning.
line =
current_line.subString( 0 , offset_within_current_line );
};
// if !exact case work with upcased line.
if ( ! exact) line = I0String::upperCase(line);
// the current line number. for loop.
line_no = current_line_no;
// search for text.
while ( ! line.includes( looked_for ) )
{
// after first look at whole line.
offset = 0;
if (line_no == limit) return;
// increment line number.
line_no += direction_sign;
// get new line.
line = mle.text(line_no);
// if not exact case, work with upcased string.
if ( ! exact ) line = I0String::upperCase(line);
};
};
// optional call back to user after running thread. after searching for text.
void ListWindowThread::finish()
{
mle.enableUpdate(); // unfreeze updates.
if ( line.includes( looked_for ) )
{
// go to begining of found line
mle.setCursorLinePosition( line_no );
// first position of the found string.
IPair::Coord first = mle.cursorPosition() + offset +
(line.*dir_search)(looked_for , start_pos );
// end of the found string.
IPair::Coord last = first + search_string.length() - 1;
// postion past the found string in the direction of travel.
mle.setCursorPosition ( first + direction_mult *
( search_string.length() - 1 ) );
// select the found string.
// cursor will be positined at second parameter of the IRange.
if ( forward )
mle.selectRange( IRange(first,last) );
else
mle.selectRange( IRange(last,first) );
};
info.setText(saved_text);
OurWindow().enable();
mle.setFocus();
return;
};
// Do an importFromFile after determining
// type of the file.
unsigned long ListFrame::import( const char * file)
{
char buf[2048], cr ;
{
ifstream in( file, ios::binary );
if (in)
{
in.get(buf,sizeof(buf));
int count=in.gcount();
if ( count == 0 ) cr=0;
else cr = buf[ count - 1 ];
};
};
IMultiLineEdit::EOLFormat format =
( cr == '\r' ) ? IMultiLineEdit::cfText
: IMultiLineEdit::noTran;
// import the data.
return mle.importFromFile( file , format );
};
// command handler for main window.
// this code overrides ICommandHandler, gets called
// when command event caused by user from menu, accelerator.
Boolean ListFrame::command( ICommandEvent& event )
{
// classify the request.
switch ( event.commandId() )
{
// change font request
// user wants to change font.
case IDM_FONT:
{
// get current font
IFont font = mle.font();
// and store in the settings
IFontDialog::Settings fsettings( &font );
// set the title.
fsettings.setTitle(STR_FONTTITLE);
// create dialog to get the new font.
IFontDialog dlg(IWindow::desktopWindow(),this,
IFontDialog::defaultStyle() |
IFontDialog::resetButton,
fsettings);
// when the constructor returns, dialog has run
if(dlg.pressedOK() ) // if user said ok.
{
mle.setFont(font); // store new font
// ask user if he want to store this new font as the new default.
// create message box.
IMessageBox msg(this);
if (
msg.show(STR_DEFAULTFONT,
IMessageBox::queryIcon |
IMessageBox::yesNoButton ) ==
IMessageBox::yes
)
{
// store the new font.
ExternalFont(font_source) << font;
};
};
return true; // we have handled.
};
// word wrap on request.
case IDM_ON:
{
// set word wrap if not already.
if( ! mle.isWordWrap() ) mle.enableWordWrap();
// record word wrapping;
ExternalWrap(wrap_source) << true;
return true; // we have handled.
};
// word wrap off request.
case IDM_OFF:
{
// if on turn it off
if( mle.isWordWrap() ) mle.disableWordWrap();
// record no word wrapping;
ExternalWrap(wrap_source) << false;
return true;
};
// open new file on new window request.
// user wants to open a new file.
case IDM_OPENNEW :
{
char fullfile[_MAX_PATH]; // space for full path name.
// get full path of our current file
_fullpath(fullfile,file(),sizeof(fullfile));
// fields to break path into
char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
// break fullpath into fields
_splitpath(fullfile,drive,dir,fname,ext);
char usepath[_MAX_PATH]; // space for path to use.
// create path to use, with wild card filename.
_makepath(usepath,drive,dir,"*","");
// declare settings.
IFileDialog::Settings fsettings;
// set the indicated file name to search for
fsettings.setFileName( usepath );
// set the ititial drive as has been discovered.
fsettings.setInitialDrive(drive);
// set title of the get file name dialog.
fsettings.setTitle(STR_TITLENEW);
// dialog is to get an existing file.
fsettings.setOpenDialog();
// declare the dialog on the current frame, with the settings.
IFileDialog dlg( IWindow::desktopWindow(), this,
IFileDialog::defaultStyle(),
fsettings);
// The above call will return when the above modal dialog
// has already run.
// set the focus back to our edit ring.
mle.setFocus();
// if the dialog ran successfully.
if ( dlg.pressedOK() )
{
// for each file selected by the dialog.
for(int i=0; i< dlg.selectedFileCount() ; i++)
{
// start a whole new thread to handle the new frame.
// the new ListThreadFn will be stored in a managed pointer
// and will be destroyed when the thread exits!
IThread list ( new ListThreadFn ( dlg.fileName(i) ) );
};
};
return true; // Have handled.
break;
};
// user wants to Open new file in the current window.
case IDM_REPLACEFILE:
{
// space for the fullfile name in the dialog.
char fullfile[_MAX_PATH];
// create the fullpath of the current file.
_fullpath(fullfile, file(),sizeof(fullfile));
// space to store the parts of the current file.
char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
// split the file into parts.
_splitpath(fullfile,drive,dir,fname,ext);
// space to store desired file
char usepath[_MAX_PATH];
// make a wild card file path.
_makepath(usepath,drive,dir,"*","");
// settings for the dialog.
IFileDialog::Settings fsettings;
// set files to chose from. all
fsettings.setFileName( usepath );
// set the initial drive discovered.
fsettings.setInitialDrive(drive);
// set the title of this dialog.
fsettings.setTitle(STR_TITLEREPLACE);
// This is an open dialog, choose amoung existing files.
fsettings.setOpenDialog();
// returned OK, is it directroy name of file which is chosen.
Boolean is_dir , ok ;
IString chosen_file;
do
{
// create the dialog.
IFileDialog dlg( IWindow::desktopWindow(), this,
IFileDialog::defaultStyle() ,
fsettings);
// constructor will return when dialog has run to completion.
ok = dlg.pressedOK();
if ( ok ) chosen_file = dlg.fileName();
is_dir = dlg.pressedOK() && IsDir( dlg.fileName() ) ;
if (is_dir) fsettings.setFileName( ( chosen_file + "\\*" ) );
} while ( is_dir );
// if the dialog ran ok.
if ( ok )
{
if ( access(chosen_file,04) ) // is it accessable?
{
// if file is not accesable, complain bitterly and leave.
IMessageBox ( this )
.show(ERR_NOTREAD,IMessageBox::information);
}
else
{
mle.hide(); // hide the client while
mle.removeAll(); // we remove all the
// lines.
// import all lines from
import( chosen_file ); // the selected file.
file_displayed = chosen_file; // save current filename.
mle.setCursorPosition ( 0 ); // set position=0,0
info.setText( chosen_file ); // set the filename
info.setInactiveText( chosen_file ); // in the info area.
mle.show(); // show edit area again.
};
};
// set the focus new edit area
mle.setFocus();
return true; // yes, handled.
break;
};
// copy to clipboard request. CTRL+ins
case IDM_COPYTOCLIPBOARD :
{
// if no text selected, done
if ( ! mle.hasSelectedText() ) return true;
// get the clipboard window.
IClipboard clipboard(event.window()->handle());
// empty the clipboard.
clipboard.empty();
// move in the selected event
clipboard.setText(mle.selectedText());
return true; // we have handled.
break;
};
// Handle all items that display help but are not handled by help system.
case IDM_COPYRIGHT :
case IDM_GNUPUBLICLICENCE :
case IDM_PROGRAMAUTHOR :
// We require that the item number for these items must be ==
// the panel ID # this requirement is met in resource editor
// and ipf editor. We check that it has been met hare.
{ // show help page.
#if !( ( IDM_COPYRIGHT == Copyright ) && \
( IDM_GNUPUBLICLICENCE == GNU ) && \
( IDM_PROGRAMAUTHOR == Author) )
#error Resource ID must be equal to panel ID for app help items.
#endif
// display the help.
help.show(IResourceId( event.commandId() ));
return true; // handled
break;
};
// user wants search for text in the mle
case IDM_SEARCH :
// get search parameters from user.
// run the search dialog.
search_dialog.GetToBeSearched();
// deliberate FALLTHRU !!!!!!!
// user wants to search for text string again.
case IDM_AGAIN : // search for text again.
{
// get text to search for
IString search_string = search_dialog;
// get exact case match parameter.
Boolean exact = search_dialog.Exact();
// get direction of search.
Boolean forward = search_dialog.DirectionForward();
// search for the text.
win_thread.init_and_start(search_string, exact, forward);
break;
};
// the unspecified case.
default:
{
// default do the default handler and return.
return ICommandHandler::command(event);
};
};
return false; // assume we have handled.
}; // Boolean ListFrame::command( ICommandEvent& event )
//
// this handler called when the word wrap menu opened.
// overrides from IMenuHandler. called when Word wrap submenu
// is opened.
Boolean ListFrame::menuShowing ( IMenuEvent& event,ISubmenu& submenu)
{
// if word wrap menu called.
if (submenu.id() == IDM_WORDWRAP )
{
// is word wrap on?
Boolean wrap_on = mle.isWordWrap();
// word wrap is of is opposite.
Boolean wrap_off = !wrap_on;
// set items checked approapiately
submenu.checkItem(IDM_ON,wrap_on);
submenu.checkItem(IDM_OFF,wrap_off);
};
// pass on to default handler.
return IMenuHandler::menuShowing( event, submenu);
};
// overrides IResizeHandler is called when main frame is resized.
// bug bug bug
// we should only save new size on SHIFT drag, but How do we
// distinguish this case??
// If you know the answer email paul.elliott@hrnowl.lonestar.org
Boolean ListFrame::windowResize(IResizeEvent& evt)
{
SizeStore(resizer) << evt.newSize(); // Save new size.
return false; // we did not handle, only hooked.
};
// overides IHelpHander.
// get s called to find out context help for this window.
// tells keys help what panel to use.
Boolean ListFrame::keysHelpId(IEvent& evt)
{
int panel = KeysHelp; // panel for Keys Help.
evt.setResult( panel ); // set the panel to use.
return true; // we have handled.
};