Work Place Shell Programming - Part 1

From EDM2
Jump to: navigation, search
Work Place Shell Programming
Part: 1 / 2 / 3 / 4

Written by Chris Palchak

Purpose

The purpose of this series of articles is to teach the reader how to integrate an application with the OS/2 Work Place Shell. As this writer always looks for ways to avoid using API calls, the settings pages are written in C++ using the IBM Visual Age for C++ compiler and Open Class Library. Hopefully, those readers who are unfamiliar with C++ will be inspired to learn the language once they see the brevity of the settings page programs.

Overview

There are two parts to a Work Place Shell (WPS) program. The first is a System Object Model (SOM) Interface Definition Language (IDL) source file. The second part, is the code you write in C, C++, or some other supported language. This first article will show the reader how to:

  • Create the SOM IDL module,
  • Compile the IDL code,
  • Make the C++ DLL,
  • Register the new WPS class,
  • Create objects of the new class

The second article in this series will show the reader the code that needs to be added to the generated C++ program.

The third article in this series will show the reader how to access this class from another C++ program.

The fourth article in this series will cover a second WPS class.

SOM IDL

IBM's SOM is the basis for all WPS objects. To create custom WPS objects, you must use the SOM IDL. This may seem intimidating at first, but note that there are only two categories of statements in the SOM IDL:

  1. Attribute (or data) definition statements
  2. Interface (function) declaration statements

Once these statements are prepared, you simply generate stub program files and fill in the functions with your own code. For the purposes of this article, the generated stub files will be C++ programs. The following command will read a SOM IDL file and generate a stub C++ program along with the necessary header files:

sc.exe -s"xc;xh;xih;def" -S128000 chfile.idl.

In this case, chfile.idl is the SOM IDL file. The class described in this file is ChartFile. This is a class that inherits from WPDataFile and contains stock quotes. This is the first of two WPS classes that will be developed over the course of these articles. The other class that will be developed is ChartFolder. ChartFolder inherits from WPFolder and is used to store ChartFile objects.

ChFile.idl listing:

  #ifndef CHFILE_IDL
  #define CHFILE_IDL
  #include <wpdataf.idl>
  interface M_ChartFile;

  interface ChartFile : WPDataFile
  {
     #ifdef __SOMIDL__

     // Access methods for ChartFile's data

        void   setStockSymbol(in string s);
        void   setExchange(in string s);
        void   setLastDD(in short dd);
        void   setLastMM(in short mm);
        void   setLastYYYY(in short yyyy);
        void   setReversalBoxes(in short boxes);
        void   setBoxSize(in float bSize);
        void   setDaysInLongAvg(in short nDays);
        void   setDaysInShortAvg(in short nDays);
        void   setBarDataSaved(in short trueFalse);
        void   setPfDataSaved(in short trueFalse);
        void   setStockDataSaved(in short trueFalse);

        string getStockSymbol();
        string getExchange();
        short  getLastDD();
        short  getLastMM();
        short  getLastYYYY();
        short  getReversalBoxes();
        float  getBoxSize();
        short  getDaysInLongAvg();
        short  getDaysInShortAvg();

     // indicators: 0 = not saved, 1 = saved

        short  getBarDataSaved();
        short  getPfDataSaved();
        short  getStockDataSaved();

     //------------------------------------------------------
     // This method that reallocates memory for ChartFile's
     // strings is necessary because string is defined as
     // "char *" in \ibmcpp\include\som\somcorba.h.
     //------------------------------------------------------

        string reallocateString(in string oldString,
                                in string newValue);

        implementation
        {
            externalstem   = ChFile;
            local;
            externalprefix = ChFileX_;
            majorversion   = 1;
            minorversion   = 1;
            filestem       = ChFile;
            metaclass      = M_ChartFile;

      //-----------------------------------------------------
      // Class method (function) overrides
      //-----------------------------------------------------
      // add my settings pages
            wpAddSettingsPages: override;

      // restore state when object is awaken
            wpRestoreState:     override;

      // save state during shut down or idle times
            wpSaveState:        override;

      // called when object is created
            wpSetup:            override;

      // called when object is opened
            wpOpen:             override;

      // allocate memory for this object
            wpInitData:         override;

      // free allocated memory
            wpUnInitData:       override;

      // add my items to the pop-up menu
            wpModifyPopupMenu:  override;

      // process user selection of my menu items
            wpMenuItemSelected: override;

      //-----------------------------------------------------
      // Instance data (Exists separately for each
      // ChartFile object). These are NOT declared with the
      // SOM IDL "attribute" statement so that the get
      // and set functions can be named manually.
      //-----------------------------------------------------

      //  Stock Settings Page

            string stockSymbol;
            string exchange;
            short  lastDD;
            short  lastMM;
            short  lastYYYY;

       // Point & Figure settings

            short  reversalBoxes;
            float  boxSize;

       // Bar Chart settings page

            short  daysInLongAvg;
            short  daysInShortAvg;

       // State Indicators 0 = not saved, 1 = saved

            short  barDataSaved;
            short  pfDataSaved;
            short  stockDataSaved;

      //-----------------------------------------------------
      // Passthru Statements:
      // These statements are passed without change to the
      // generated "chfile.xih" and "chfile.xh" files.
      //-----------------------------------------------------

      // These statements get written to ChFile.xih.
      // ChFile.xih is included in ChFile.cpp.

          passthru C_xih_before =  ""
         " /* PM and OS2 include directives */"
         "   #define INCL_WINWORKPLACE"
         "   #define INCL_WIN"
         "   #include <os2.h>"
         ""
         " /* WPS include directives */"
         "   #define INCL_WPCLASS"
         "   #define INCL_WPObject"
         "   #include <pmwp.h>"
         ""
         " /* C include directives */"
         "   #include <stdio.h>"
         "";

      // These statements get written to ChFile.xh.
      // ChFile.xh is included in C++ programs that
      // reference ChartFile objects.

          passthru C_xh_before =  ""
         " /* PM and OS2 include directives */"
         "   #define INCL_WINWORKPLACE"
         "   #define INCL_WIN"
         "   #include <os2.h>"
         ""
         " /* WPS include directives */"
         "   #define INCL_WPCLASS"
         "   #define INCL_WPObject"
         "   #include <pmwp.h>"
         ""
         " /* C include directives */"
         "   #include <stdio.h>"
         "";
        };

     #endif
  };

  //---------------------------------------------------------
  // Metaclass section:
  // ------------------
  // Describe the metaclass of ChartFile. The Meta Class
  // defines data that is common (global) to all ChartFile
  // objects. It also defines functions that operate on Meta
  // Class Data.
  //---------------------------------------------------------

  interface M_ChartFile

  // Comment for parent WPDataFile:

  {
    //
    // No new class methods
    //

  #ifdef __SOMIDL__
      implementation
      {
    // Class Modifiers
         externalstem = ChFile;
         local;
         externalprefix = ChFileX_;
         functionprefix = ChFileC_;
         majorversion = 1;
         minorversion = 1;
         filestem = ChFile;

    // non-instance (global) data

         unsigned long hChartFileIcon; // Object's icon handle


    // Class method Modifiers

    // allocate required memory
         wpclsInitData:         override;

    // free allocated memory
         wpclsUnInitData:       override;

    // must override to make icon stick
         wpclsQueryIcon:        override;

    // define the double-click view
         wpclsQueryDefaultView: override;
      };

  #endif /* __SOMIDL__ */

  };

  #endif

Building the DLL

The Module Definition File

The following file is generated by the SOM compiler. This file must be modified to include the custom functions declared for setting and getting ChartFile's data.

ChFile.def Listing

  ;  This file was generated by the SOM Compiler.
  ;  FileName: ChFile.def.
  ;  Generated using:
  ;      SOM Precompiler somipc: 2.29.1.7
  ;      SOM Emitter emitdef: 2.42
  LIBRARY ChFile INITINSTANCE
  DESCRIPTION 'ChartFile Class Library'
  PROTMODE
  DATA MULTIPLE NONSHARED LOADONCALL
  EXPORTS
     ChartFileCClassData
     ChartFileClassData
     ChartFileNewClass
     M_ChartFileCClassData
     M_ChartFileClassData
     M_ChartFileNewClass

This is the modified module definition file. Note that there is no need to use mangled function names for this DLL because the exported functions are not really C++ class members. This file has been named Export.def so that it does not get overlaid when a new ChFile.def gets generated.

Export.def Listing

  LIBRARY ChFile INITINSTANCE
  DESCRIPTION 'ChartFile Class Library'
  PROTMODE
  DATA MULTIPLE NONSHARED LOADONCALL
  EXPORTS
      ChartFileCClassData           @1
      ChartFileClassData            @2
      ChartFileNewClass             @3
      M_ChartFileCClassData         @4
      M_ChartFileClassData          @5
      M_ChartFileNewClass           @6
      ChFileX_setBoxSize            @7
      ChFileX_getBoxSize            @8
      ChFileX_getLastYYYY           @9
      ChFileX_setStockSymbol        @10
      ChFileX_setLastYYYY           @11
      ChFileX_setLastMM             @12
      ChFileX_setDaysInShortAvg     @13
      ChFileX_getReversalBoxes      @14
      ChFileX_setReversalBoxes      @15
      ChFileX_setExchange           @16
      ChFileX_setDaysInLongAvg      @17
      ChFileX_getLastDD             @18
      ChFileX_getExchange           @19
      ChFileX_getDaysInLongAvg      @20
      ChFileX_getLastMM             @21
      ChFileX_getStockSymbol        @22
      ChFileX_getDaysInShortAvg     @23
      ChFileX_setLastDD             @24

ChFile.mak Listing

  # ChFile.mak
  # Created by IBM WorkFrame/2 MakeMake at 21:59:45 on
  # 13 May 1997
  #
  # The actions included in this make file are:
  #  Compile::SOM Compiler
  #  Compile::C++ Compiler
  #  Lib::Import Lib (from def)
  #  Link::Linker
  #

  .SUFFIXES: .IDL .cpp .obj .rc .res .def

  .all: \
      .\ChFile.LIB \
      .\ChFile.dll

  .IDL.cpp:
      @echo " Compile::SOM Compiler "
      sc.exe -s"xc;xh;xih;def" -S128000 %s

  .cpp.obj:
      @echo " Compile::C++ Compiler "
      icc.exe /Ti /Gm /Gd /Ge- /C %s

  .\ChFile.LIB: \
      .\Export.def
      @echo " Lib::Import Lib (from def) "
      implib.exe ChFile.LIB export.def

  .\ChFile.dll: \
      .\ChFile.obj \
      .\Export.def \
      {$(LIB)}somtk.lib
      @echo " Link::Linker "
      icc.exe @<<
       /B" /de /noe"
       /FeChFile.dll
       ChFile.obj
       somtk.lib
       Export.def
  <<

  .\ChFile.cpp: \
      d:\som\ChFile\ChFile.IDL

  .\ChFile.obj: \
      .\ChFile.cpp \
      {D:\som\ChFile;$(INCLUDE);}ChFile.xih \

Registering ChartFile

The following REXX program will register the ChartFile class:

  /* REXX: Register */

  Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs';
  Call SysLoadFuncs;

     rc=SysRegisterObjectClass('ChartFile','chfile');

     If rc <> 1
        Then Do;
  Say "ChartFile: could not register ChartFile, rc="rc ".";
          Exit;
          End;

  Exit;

Creating instances ChartFile

Even though the SOM compiler creates a C++ class, you can NOT use the "new" operator to create WPS objects. The following REXX program will create a ChartFile object in the Charts directory on drive d:. Alternatively, WinCreateObject can be used to create new ChartFile objects.

  /* REXX: Create */

  Call RxFuncAdd'SysLoadFuncs','REXXUTIL','SysLoadFuncs';
  Call SysLoadFuncs;

  rc=SysCreateObject('ChartFile','Mitchell Energy&Dev Cl A',
                     'D:\Charts',,'replace');

  Exit;

Deregistering ChartFile

The following REXX program will deregister the ChartFile class:

  /* REXX: Deregister */

  Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs';
  Call SysLoadFuncs;

       rc=SysDeregisterObjectClass('ChartFile');

       If rc <> 1
          Then Do;
            Say  "ChartFile: could not deregister";
            End;

  Exit;

Debugging a WPS DLL

Be sure to read the following section in the Workplace Shell Programming Guide that comes with the OS/2 toolkit:

  • Using Workplace Shell Debugging Techniques

This is a subsection of the main section:

  • Debugging Workplace Shell Applications

This information is VERY useful. It shows how to bring up OS/2 with an OS/2 window instead of the WPS. It also shows how to start, stop, and, debug the WPS. Since a DLL can not be debugged directly, the programmer must debug PMSHELL.EXE (the WPS) and set a "Load" break point for the DLL in question.