home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Developer Kits / Arrange Developer Kit / Examples / Select Subnotes / SelectSubnotes.cp < prev    next >
Encoding:
Text File  |  1994-07-15  |  12.9 KB  |  423 lines  |  [TEXT/MPS ]

  1. #include "ArrangeCallbacks.h"
  2. #include "PluginLibrary.h"
  3.  
  4. #include <Dialogs.h>
  5. #include <Events.h> // for shiftKey constant
  6.  
  7. // SelectSubnotes.cp - based on GenericPlugin.cp as of 7/15/94
  8.  
  9.  
  10. #define ModuleRsrcID 0xFFFF8800
  11.  
  12. #define baseCmdCode 0x12000000 // replace this with a value obtained from
  13.                                          // Common Knowledge.
  14.  
  15. #define aboutCmdCode    (baseCmdCode + 0)
  16. #define selSubnotesCode (baseCmdCode + 1)
  17.  
  18.  
  19. class Plugin
  20.     {
  21. public:
  22.     Plugin(const ArrangeCallbackTbl* theCalls);
  23.     ~Plugin();
  24.     
  25.     arHookResult ClickNotify( arClickLocation loc, Point where, Short modifiers,
  26.                                       Short clickCount, arNoteID note, arFieldID field,
  27.                                       arPathID path );
  28.     arHookResult KeyNotify  ( Short theChar, Short key, Short modifiers );
  29.     arHookResult MenuNotify ( Integer commandCode, Integer commandParam,
  30.                                       Short modifiers );
  31.     arHookResult FieldNotify( arNoteID note, arFieldID field, arFieldAction action,
  32.                                       const char* choiceText );
  33.     void         TopicNotify( arTopicID newTopic, arWindowID newWindow,
  34.                                       arTopicAction action );
  35.     void             TickNotify (  );
  36.     arHookResult FileNotify ( arFileAction action );
  37.     arHookResult QuitNotify (  );
  38.     void         ATMNotify  (  );
  39.     
  40. private:
  41.     const ArrangeCallbackTbl* calls; // callback table
  42.     
  43.     void DoSelectSubnotes(Boolean doAdd);
  44.     }; // Plugin
  45.  
  46.  
  47. /*************************************************************************/
  48. /**************************** Main entry point ***************************/
  49. /*************************************************************************/
  50.  
  51. /* Root entry point for the module - must be the first function in the
  52.  * file, so that the linker will place it first in the code segment.
  53.  * This is the routine which Arrange calls at application startup time
  54.  * (and again at quit time).
  55.  * 
  56.  * Most plug-ins will not need to modify this routine or the Hook functions
  57.  * immediately following.  All customization can be done in the "Plugin"
  58.  * section (below).
  59.  */
  60. extern "C" Integer OurModuleRoot( ModuleParamBlock *pb, ModuleRootAction action,
  61.                                              Integer /*p1*/ )
  62.     {
  63.     /* Extract the callback table from our parameter block, and coerce it
  64.      * to the extended Arrange table.
  65.      */
  66.     ArrangeCallbackTbl* calls = (ArrangeCallbackTbl*)(pb->calls);
  67.     
  68.     switch (action)
  69.         {
  70.         case mrLoad:
  71.             {
  72.             // Allocate memory and create a new Plugin object.
  73.             void* storage = calls->mem->AllocMem( sizeof(Plugin),
  74.                                                               amFreeStore | amErrIfNoMem );
  75.             pb->moduleRefcon = uInteger(new(storage) Plugin(calls));
  76.             return 1;
  77.             }
  78.         
  79.         case mrUnload:
  80.             {
  81.             /* Dispose of the Plugin object and release the memory
  82.              * it occupies.
  83.              */
  84.             delete (Plugin*)(pb->moduleRefcon);
  85.             calls->mem->DeallocMem((void*)(pb->moduleRefcon), amFreeStore);
  86.             return 0;
  87.             }
  88.         
  89.         case mrFindEntry:
  90.         default:
  91.             {
  92.             /* This module contains no extended entry points, so we always
  93.              * return 0 for the mrFindEntry message.  Most plug-ins will not
  94.              * use extended entry points.
  95.              */
  96.             return 0;
  97.             }
  98.         
  99.         } // switch (action)
  100.     
  101.     } // OurModuleRoot
  102.  
  103.  
  104. /* These hook functions simply pass control to the appropriate function
  105.  * in the Plugin object.
  106.  */
  107. static arHookResult OurClickHook( ModuleParamBlock* pb, arClickLocation loc,
  108.                                              Point where, pShort modifiers, pShort clickCount,
  109.                                              arNoteID note, arFieldID field,
  110.                                              arPathID path ENDP )
  111.     {
  112.     return ((Plugin*)(pb->moduleRefcon))->ClickNotify( loc, where, modifiers,
  113.                                                                         clickCount, note, field,
  114.                                                                         path );
  115.     }
  116.  
  117.  
  118. static arHookResult OurKeyHook( ModuleParamBlock* pb, pShort theChar, pShort key,
  119.                                           pShort modifiers ENDP )
  120.     {
  121.     return ((Plugin*)(pb->moduleRefcon))->KeyNotify(theChar, key, modifiers);
  122.     }
  123.  
  124.  
  125. static arHookResult OurMenuHook( ModuleParamBlock* pb, Integer commandCode,
  126.                                             Integer commandParam, pShort modifiers ENDP )
  127.     {
  128.     return ((Plugin*)(pb->moduleRefcon))->MenuNotify( commandCode, commandParam,
  129.                                                                      modifiers );
  130.     }
  131.  
  132.  
  133. static arHookResult OurFieldHook( ModuleParamBlock* pb, arNoteID note,
  134.                                              arFieldID field, arFieldAction action,
  135.                                              const char* choiceText ENDP )
  136.     {
  137.     return ((Plugin*)(pb->moduleRefcon))->FieldNotify( note, field, action,
  138.                                                                         choiceText );
  139.     }
  140.  
  141.  
  142. static void OurTopicHook( ModuleParamBlock* pb, arTopicID newTopic,
  143.                                   arWindowID newWindow, arTopicAction action ENDP )
  144.     {
  145.     ((Plugin*)(pb->moduleRefcon))->TopicNotify(newTopic, newWindow, action);
  146.     }
  147.  
  148.  
  149. static void OurTickHook(ModuleParamBlock* pb ENDP)
  150.     {
  151.     ((Plugin*)(pb->moduleRefcon))->TickNotify();
  152.     }
  153.  
  154.  
  155. static arHookResult OurFileHook(ModuleParamBlock* pb, arFileAction action ENDP)
  156.     {
  157.     return ((Plugin*)(pb->moduleRefcon))->FileNotify(action);
  158.     }
  159.  
  160.  
  161. static arHookResult OurQuitHook(ModuleParamBlock* pb ENDP)
  162.     {
  163.     return ((Plugin*)(pb->moduleRefcon))->QuitNotify();
  164.     }
  165.  
  166.  
  167. static void OurATMHook(ModuleParamBlock* pb ENDP)
  168.     {
  169.     ((Plugin*)(pb->moduleRefcon))->ATMNotify();
  170.     }
  171.  
  172.  
  173. /*************************************************************************/
  174. /********************************* Plugin ********************************/
  175. /*************************************************************************/
  176.  
  177. /* Construct a Plugin object.  This is called once, from the OurModuleRoot
  178.  * function, when the module is initialized (i.e. at application startup time).
  179.  */
  180. Plugin::Plugin(const ArrangeCallbackTbl* theCalls)
  181.     {
  182.     // Record the callback table for future use.
  183.     calls = theCalls;
  184.     
  185.     /* These commands, if un-commented-out, register this plugin to be called
  186.      * by Arrange when various events occur.  For example, if you un-comment-out
  187.      * the call to SetClickHook, then Plugin::ClickNotify will be called
  188.      * whenever the user clicks in any of the locations described in the
  189.      * arClickLocation enum.
  190.      */
  191.     // calls->ui->SetClickHook(OurClickHook, 0, true);
  192.     // calls->ui->SetKeyHook  (OurKeyHook,   0, true, charFilter, keyFilter, modFilter);
  193.     // calls->ui->SetMenuHook (OurMenuHook,  0, true, whichCommand);
  194.     // calls->ui->SetFieldHook(OurFieldHook, 0, true, whichField);
  195.     // calls->ui->SetTopicHook(OurTopicHook, 0, true);
  196.     // calls->ui->SetTickHook (OurTickHook,  0, true);
  197.     // calls->ui->SetFileHook (OurFileHook,  0, true);
  198.     // calls->ui->SetQuitHook (OurQuitHook,  0, true);
  199.     calls->ui->SetATMHook  (OurATMHook,   0, true);
  200.     
  201.     // Add an item to the About Plugins menu for this plugin.
  202.     calls->ui->AddMenuItem(mPluginAbout, "About Select Subnotes", 0, aboutCmdCode, 0);
  203.     
  204.     // Register ourselves to be called when our About command is chosen.
  205.     calls->ui->SetMenuHook(OurMenuHook, 0, true, aboutCmdCode);
  206.     
  207.     // Create, and register for, a new command in the Select submenu.
  208.     calls->ui->AddMenuItem(mSelect, "Select Subnotes", 0, selSubnotesCode, 0);
  209.     calls->ui->SetMenuHook(OurMenuHook, 0, true, selSubnotesCode);
  210.     } // Plugin constructor
  211.  
  212.  
  213. /* Dispose of a Plugin object.  This is called when Arrange terminates.  You
  214.  * should free up any data structures which you allocation in the Plugin
  215.  * constructor (above).
  216.  */
  217. Plugin::~Plugin()
  218.     {
  219.     } // ~Plugin
  220.  
  221.  
  222. /* This function is called whenever the user clicks in an "interesting place"
  223.  * in a document window.  It should return true if we handle the click, false
  224.  * (the normal case) when the click should be passed along to other plug-ins
  225.  * or to Arrange's normal event processing.  See the documentation for
  226.  * SetClickHook for more details.
  227.  */
  228. arHookResult Plugin::ClickNotify( arClickLocation /*loc*/, Point /*where*/,
  229.                                              Short /*modifiers*/, Short /*clickCount*/,
  230.                                              arNoteID /*note*/, arFieldID /*field*/,
  231.                                              arPathID /*path*/ )
  232.     {
  233.     return false; // Let Arrange handle the event
  234.     } // ClickNotify
  235.  
  236.  
  237. /* This function is called whenever the user types a key which matches the
  238.  * filters we pass to SetKeyHook in Plugin's constructor.  It should return
  239.  * true if we handle the event, false (the normal case) when the event
  240.  * should be passed along to other plug-ins or to Arrange's normal event
  241.  * processing.  See the documentation for SetKeyHook for more details.
  242.  */
  243. arHookResult Plugin::KeyNotify( Short /*theChar*/, Short /*key*/,
  244.                                           Short /*modifiers*/)
  245.     {
  246.     return false; // Let Arrange handle the event
  247.     } // KeyNotify
  248.  
  249.  
  250. /* This function is called whenever the user chooses a menu item for which
  251.  * we have registered (via the SetMenuHook function).  It should return true
  252.  * if we handle the command, false (the normal case) when the command should
  253.  * be passed along to other plug-ins or to Arrange's normal event processing.
  254.  * See the documentation for SetMenuHook for more details.
  255.  */
  256. arHookResult Plugin::MenuNotify( Integer commandCode, Integer /*commandParam*/,
  257.                                             Short modifiers )
  258.     {
  259.     /* If this is our About menu item, display our about-box dialog and return
  260.      * true to indicate we handled the command.
  261.      */
  262.     if (commandCode == aboutCmdCode)
  263.         {
  264.         Alert(ModuleRsrcID, nil);
  265.         return true;
  266.         }
  267.     else if (commandCode == selSubnotesCode)
  268.         {
  269.         DoSelectSubnotes((modifiers & shiftKey) != 0);
  270.         return true;
  271.         }
  272.     else
  273.         return false; // Let Arrange handle the event
  274.     
  275.     } // MenuNotify
  276.  
  277.  
  278. /* If we register to recieve events for a field by calling SetFieldHook, this
  279.  * function will be called for any events in that field.  It should return
  280.  * false in almost all cases.  See the documentation for SetFieldHook for
  281.  * more details.
  282.  */
  283. arHookResult Plugin::FieldNotify( arNoteID /*note*/, arFieldID /*field*/,
  284.                                              arFieldAction /*action*/,
  285.                                              const char* /*choiceText*/ )
  286.     {
  287.     return false;
  288.     } // FieldNotify
  289.  
  290.  
  291. /* This function is called whenever the user switches windows or changes
  292.  * the current folder/topic/view in the front window.  See the documentation
  293.  * for SetTopicHook for more details.
  294.  */
  295. void Plugin::TopicNotify( arTopicID /*newTopic*/, arWindowID /*newWindow*/,
  296.                                   arTopicAction /*action*/ )
  297.     {
  298.     } // TopicNotify
  299.  
  300.  
  301. /* This function is called periodically, whenever Arrange recieves a null
  302.  * event from the Event Manager.
  303.  */
  304. void Plugin::TickNotify()
  305.     {
  306.     } // TickNotify
  307.  
  308.  
  309. /* This function is called whenever various file-level events occur.  It
  310.  * should return true in almost all cases.  See the documentation for
  311.  * SetFileHook for more details.
  312.  */
  313. arHookResult Plugin::FileNotify(arFileAction /*action*/)
  314.     {
  315.     return true;
  316.     } // FileNotify
  317.  
  318.  
  319. /* This function is called if the user voluntarily quits Arrange.  It should
  320.  * return true to allow the user to quit, false to prevent it.  See the
  321.  * documentation for SetQuitHook for more details.
  322.  */
  323. arHookResult Plugin::QuitNotify()
  324.     {
  325.     return true;
  326.     } // QuitNotify
  327.  
  328.  
  329. /* This function is called whenever the user clicks in the menu bar or types
  330.  * a command key, just before processing the event.  It should do any fixing
  331.  * up of menus which might be necessary based on the current state of affairs.
  332.  * See the documentation for SetATMHook for more details.
  333.  */
  334. void Plugin::ATMNotify()
  335.     {
  336.     /* Enable or disable the Select Subnotes command depending on whether there
  337.      * is a selection.
  338.      */
  339.     arNoteID selNote;
  340.     arFieldID selField;
  341.     Integer selStart,selEnd;
  342.     Boolean hasSel = (calls->sel->GetSelection( &selNote, &selField,
  343.                                                               &selStart, &selEnd ) != stNone);
  344.     
  345.     calls->ui->SetMenuItem( mSelect, selSubnotesCode, 0, nil, hasSel,
  346.                                     0, 0 );
  347.     } // ATMNotify
  348.  
  349.  
  350. /* If doAdd is true, then add to the selection all subnotes of all notes
  351.  * in the selection.  Otherwise replace the current selection by the subnotes
  352.  * of all notes in the selection.
  353.  */
  354. void Plugin::DoSelectSubnotes(Boolean doAdd)
  355.     {
  356.     // Determine whether there is a selection and how many notes it contains.
  357.     Integer selCount;
  358.     
  359.     arNoteID  selNote;
  360.     arFieldID selField;
  361.     Integer   selStart;
  362.     Integer   selEnd;
  363.     switch (calls->sel->GetSelection(&selNote, &selField, &selStart, &selEnd))
  364.         {
  365.         case stNote:
  366.         case stField:
  367.         case stText:
  368.         case stFieldContents:
  369.             selCount = 1;
  370.             break;
  371.         
  372.         case stMultipleNotes:
  373.         case stMultipleFields:
  374.             selCount = selStart;
  375.             break;
  376.         
  377.         default:
  378.             return;
  379.         
  380.         } // switch (GetSelection result)
  381.     
  382.     // Get a list of the IDs of the selected notes.
  383.     arNoteID* selIDs = (arNoteID*) calls->mem->AllocMem( selCount * sizeof(arNoteID),
  384.                                                                           amFreeStore );
  385.     if (selIDs == nil)
  386.         return;
  387.     
  388.     arNoteID parentNote;
  389.     for (int i=0; i<selCount; i++)
  390.         {
  391.         calls->sel->GetSelEntry(i, &selNote, &selField, &parentNote);
  392.         if (selField == nil)
  393.             selIDs[i] = parentNote;
  394.         else
  395.             selIDs[i] = selNote;
  396.         }
  397.     
  398.     // If doAdd is false, then drop the old selection.
  399.     if (!doAdd)
  400.         if (!calls->sel->FlushSelection(true))
  401.             {
  402.             calls->mem->DeallocMem(selIDs, amFreeStore);
  403.             return;
  404.             }
  405.     
  406.     // Add to the selection all subnotes of each note in selIDs.
  407.     arFieldID subnotesField = calls->sysObj->GetBuiltInObject(boSubnotesField);
  408.     for (i=0; i<selCount; i++)
  409.         {
  410.         arListID curSubnotes = calls->data->GetFieldList(selIDs[i], subnotesField);
  411.         Integer subnoteCount = calls->list->GetListLen(curSubnotes);
  412.         
  413.         for (int j=0; j<subnoteCount; j++)
  414.             calls->sel->SelectObject( selIDs[i], subnotesField,
  415.                                               calls->list->GetListEntry(curSubnotes,j),
  416.                                               false );
  417.         
  418.         calls->list->DisposeList(curSubnotes);
  419.         }
  420.     
  421.     calls->mem->DeallocMem(selIDs, amFreeStore);
  422.     } // DoSelectSubnotes
  423.