home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / text / golded / data / tools / edsource / main.c next >
C/C++ Source or Header  |  1995-02-27  |  13KB  |  461 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.   ED v0.94 - GoldED quick starter, ©1994 Dietmar Eilert. Dice:
  4.  
  5.   dcc main.c sprintf.a -// -proto -mRR -mi -pr -2.0 -o ram:ED
  6.  
  7.   ------------------------------------------------------------------------------
  8. */
  9.  
  10. /// "includes"
  11.  
  12. #include <amiga20/exec/exec.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <stdarg.h>
  18. #include <amiga20/intuition/intuition.h>
  19. #include <amiga20/dos/dos.h>
  20. #include <amiga20/dos/dosextens.h>
  21. #include <amiga20/dos/rdargs.h>
  22. #include <amiga20/dos/dostags.h>
  23. #include <amiga20/workbench/startup.h>
  24. #include <amiga20/workbench/workbench.h>
  25. #include <amiga20/rexx/errors.h>
  26. #include <amiga20/rexx/rxslib.h>
  27.  
  28. #include <amiga20/clib/alib_protos.h>
  29. #include <amiga20/clib/dos_protos.h>
  30. #include <amiga20/clib/exec_protos.h>
  31. #include <amiga20/clib/icon_protos.h>
  32. #include <amiga20/clib/intuition_protos.h>
  33. #include <amiga20/clib/utility_protos.h>
  34. #include <amiga20/clib/rexxsyslib_protos.h>
  35. #include <amiga20/clib/wb_protos.h>
  36.  
  37. #ifdef PRAGMAS
  38.  
  39. #include "Pragmas/exec.h"
  40. #include "Pragmas/disk.h"
  41. #include "Pragmas/diskfont.h"
  42. #include "Pragmas/dynamic.h"
  43. #include "Pragmas/gadtools.h"
  44. #include "Pragmas/keymap.h"
  45. #include "Pragmas/graphics.h"
  46. #include "Pragmas/icon.h"
  47. #include "Pragmas/input.h"
  48. #include "Pragmas/intuition.h"
  49. #include "Pragmas/layers.h"
  50. #include "Pragmas/locale.h"
  51. #include "Pragmas/misc.h"
  52. #include "Pragmas/timer.h"
  53. #include "Pragmas/wb.h"
  54. #include "Pragmas/xpkmaster.h"
  55. #include "Pragmas/amigaguide.h"
  56. #include "Pragmas/reqtools.h"
  57.  
  58. #endif
  59.  
  60. #define Prototype        extern
  61. #define MAX_LEN          120
  62. #define ARGBUFFER_SIZE   10500
  63. #define ARGBUFFER_LIMIT  10000
  64.  
  65. ///
  66. /// "prototypes"
  67.  
  68. Prototype void   main(ULONG, char **);
  69. Prototype int    wbmain(struct WBStartup *);
  70. Prototype void   Action(char *, char *, char *, BOOL, BOOL, ULONG *);
  71. Prototype char  *StartGED(char *, char *, BOOL);
  72. Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *);
  73. Prototype char  *LookForGED(void);
  74. Prototype char  *myprintf(char *, char*, ...);
  75. Prototype char  *xsprintf(char *, APTR);
  76.  
  77. extern struct Library *IconBase;
  78. extern struct Library *DOSBase;
  79. extern struct Library *SysBase;
  80. extern struct Library *IntuitionBase;
  81.  
  82. ///
  83. /// "entry points"
  84.  
  85. /* --------------------------------------- main --------------------------------
  86.  
  87.  CLI entry point. Parse command line - create a string <argBuffer> containing
  88.  provided file names (file names are made absolute). This string has to be
  89.  FreeVec()'ed later on. Additionally, command line options are checked. They
  90.  won't have any effect if we manage to pass our list of files to a GoldED
  91.  process since we than have to accept that editor's configuration. However,
  92.  these options will be considered if we launch a new GoldED process.
  93.  
  94.  Point d'entrée CLI. Analyse de la ligne de commande - crée une chaîne
  95.  <argBuffer> contenant les noms de fichiers fournis (les noms des fichiers
  96.  sont rendus absolus). Cette chaîne doit ensuite être FreeVec()'é. De plus,
  97.  les options de la ligne de commande sont vérifiées. Elles n'auront pas d'
  98.  effets si nous arrivons à passer notre liste de fichier à un processus
  99.  GoldED car nous devons dans ce cas accepter la configuration de l'éditeur.
  100.  Bien sûr, ces options seront prises en compte si nous lançons un nouveau
  101.  processus de GoldED.
  102.  
  103. */
  104.  
  105. void
  106. main(argc, argv)
  107.  
  108. ULONG argc;
  109. char *argv[];
  110. {
  111.     char *argBuffer;
  112.  
  113.     if (argBuffer = AllocVec(ARGBUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
  114.  
  115.         struct RDArgs *rdArgs;
  116.         ULONG  args[] = { 0, 0, 0, 0, 0, 0, 0 };
  117.  
  118.         if (rdArgs = ReadArgs("C=CONFIG/K,S=SCREEN/K,Y=STICKY/S,F=FILE/M,HIDE/S,-STICKY/S,L=LINE/N", args, NULL)) {
  119.  
  120.             if (args[3]) {
  121.  
  122.                 char **nextFile, path[MAX_LEN + 1];
  123.  
  124.                 for (nextFile = (char **)args[3]; *nextFile; ++nextFile) {
  125.  
  126.                     strcpy(path, *nextFile);
  127.  
  128.                     if (strchr(path, ':')) {
  129.  
  130.                         BPTR lock;
  131.  
  132.                         if (lock = Lock(path, ACCESS_READ)) {
  133.  
  134.                             NameFromLock(lock, path, MAX_LEN);
  135.                             UnLock(lock);
  136.                         }
  137.                     }
  138.                     else {
  139.  
  140.                         GetCurrentDirName(path,  MAX_LEN);
  141.                         AddPart(path, *nextFile, MAX_LEN);
  142.                     }
  143.  
  144.                     strcat(argBuffer, xsprintf("\42%s\42", path));
  145.  
  146.                     if (strlen(argBuffer) > ARGBUFFER_LIMIT)
  147.                         break;
  148.                 }
  149.             }
  150.  
  151.             Action(argBuffer, (char *)args[0], (char *)args[1], (BOOL)args[2], (BOOL)args[4] || (BOOL)args[5], (ULONG *)args[6]);
  152.             FreeArgs(rdArgs);
  153.         }
  154.         else
  155.             exit(20);
  156.     }
  157.     exit(0);
  158. }
  159.  
  160. /* ------------------------------------ wbmain ---------------------------------
  161.  
  162.   Workbench  entry  point.  Read  tooltypes  of ED icon to decide wether user
  163.   prefers   a   special   configuration/public  screen.  Tooltypes  are  only
  164.   considered if we don't find a running GoldED task, i.e. if we don't have to
  165.   acccept a running environment.
  166.  
  167.   Point d'entrée Workbench. Lecture des types d'outil de l'icône ED pour dé-
  168.   cider si l'utilisateur préfère une configuration/écran public spécifique.
  169.   Les types d'outil sont seulement considérés si nous ne trouvons pas de
  170.   tâche GoldED, c.à.d. si nous n'avons pas à accepter un environnement existant.
  171.  
  172. */
  173.  
  174. int
  175. wbmain(struct WBStartup *wbs)
  176. {
  177.     char *argBuffer;
  178.  
  179.     if (argBuffer = AllocVec(ARGBUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
  180.  
  181.         struct DiskObject *diskObject;
  182.         char   *config, *screen, progName[MAX_LEN + 1];
  183.         BOOL   hide;
  184.  
  185.         screen = NULL;
  186.         config = NULL;
  187.         hide   = FALSE;
  188.  
  189.         NameFromLock(GetProgramDir(), progName, MAX_LEN);
  190.  
  191.         AddPart(progName, wbs->sm_ArgList[0].wa_Name, MAX_LEN);
  192.  
  193.         if (diskObject = GetDiskObject(progName)) {
  194.  
  195.             config   = FindToolType(diskObject->do_ToolTypes, "CONFIG");
  196.             screen   = FindToolType(diskObject->do_ToolTypes, "SCREEN");
  197.  
  198.             if (FindToolType(diskObject->do_ToolTypes, "HIDE"))
  199.                 hide = TRUE;
  200.         }
  201.  
  202.         if (--wbs->sm_NumArgs) {
  203.  
  204.             char   file[MAX_LEN + 1];
  205.             struct WBArg *wbArg = wbs->sm_ArgList;
  206.  
  207.             while ((wbs->sm_NumArgs)--) {
  208.  
  209.                 ++wbArg;
  210.  
  211.                 NameFromLock( wbArg->wa_Lock, file, MAX_LEN);
  212.                 AddPart(file, wbArg->wa_Name, MAX_LEN);
  213.  
  214.                 strcat(argBuffer, xsprintf("\42%s\42", file));
  215.  
  216.                 if (strlen(argBuffer) > ARGBUFFER_LIMIT)
  217.                     break;
  218.             }
  219.         }
  220.  
  221.         Action(argBuffer, config, screen, FALSE, hide, NULL);
  222.  
  223.         if (diskObject)
  224.             FreeDiskObject(diskObject);
  225.     }
  226.     exit(0);
  227. }
  228.  
  229. ///
  230. /// "main routine"
  231.  
  232. /* ------------------------------------ Action ---------------------------------
  233.  
  234.   Run  GoldED  if no running instance of GED is found (note: running GED will
  235.   open  a  first  window, i.e. no need to open a further one unless files are
  236.   speciefied).  Send LOCK ARexx messages to running GoldED. Wait for positive
  237.   reply,  pass our list of <files> to that editor, unlock editor (use delayed
  238.   unlock  unless  <sticky>  is specified). Suggestions for improvements: Make
  239.   the  whole  thing aynchrounous. Send LOCK messages to all running instances
  240.   of GoldED, then wait for first reply (or timeout).
  241.  
  242.   Démarre  GoldED s'il n'y aucun GED en mémoire (note: le démarrage de GED
  243.   ouvrira une première fenêtre (c.à.d. nous aurons à en ouvrir d'autres si
  244.   des fichiers sont spécifiés). Envoie ensuite les messages ARexx LOCK pour
  245.   démarrer GoldED. Attend une réponse positive, envoie notre liste de fichiers
  246.   à cet éditeur, déverrouille l'éditeur (utilise un unlock décalé, sauf si
  247.   <sticky>  est spécifié). Suggestions d'amélioration: rendez tout cela
  248.   asynchrone. Envoyez des messages LOCK à toutes les tâches de GoldED, et
  249.   attendez la première réponse (ou timeout).
  250.  
  251. */
  252.  
  253. void
  254. Action(files, config, screen, sticky, hide, line)
  255.  
  256. char  *files, *config, *screen;
  257. ULONG *line;
  258. BOOL  sticky, hide;
  259. {
  260.     const char *version = "$VER: ED 0.94 (24.3.94)";
  261.  
  262.     BOOL  loadGED;
  263.     ULONG *result;
  264.     char  *host;
  265.  
  266.     loadGED = !(host = LookForGED());
  267.  
  268.     if (loadGED)
  269.         host = StartGED(config, screen, hide);
  270.  
  271.     if (host && (*files || !(hide || loadGED))) {
  272.  
  273.         struct MsgPort *replyPort;
  274.  
  275.         if (replyPort = CreateMsgPort()) {
  276.  
  277.             if (result = SendRexxCommand(host, "LOCK CURRENT", replyPort)) {
  278.  
  279.                 if (*result == RC_OK) {
  280.  
  281.                     if (*files)
  282.                         strins(files, "OPEN SMART QUIET ");
  283.                     else
  284.                         strcpy(files, "MORE SMART");
  285.  
  286.                     SendRexxCommand(host, files, replyPort);
  287.  
  288.                     if (line)
  289.                         SendRexxCommand(host, xsprintf("GOTO LINE=%ld UNFOLD=TRUE", (APTR)*line), replyPort);
  290.  
  291.                     SendRexxCommand(host, sticky ? "UNLOCK STICKY" : "UNLOCK DELAY", replyPort);
  292.                 }
  293.             }
  294.             DeleteMsgPort(replyPort);
  295.         }
  296.     }
  297.     FreeVec(files);
  298. }
  299.  
  300. ///
  301. /// "misc"
  302.  
  303.  
  304. /* ----------------------------------- LookForGED ----------------------------
  305.  
  306.  Look for running GoldED task (check GOLDED.1 to GOLDED.9)
  307.  
  308.  Recherche d'une tâche GoldED (vérifie GOLDED.1 à GOLDED.9)
  309.  
  310. */
  311.  
  312. char *
  313. LookForGED()
  314. {
  315.     static char host[] = "GOLDED.1";
  316.     UWORD  try;
  317.  
  318.     for (try = '1'; try <= '9'; try++) {
  319.  
  320.         host[7] = try;
  321.  
  322.         if (FindPort(host))
  323.             return(host);
  324.     } 
  325.  
  326.     return(NULL);
  327. }
  328.  
  329. /* ------------------------------------- StartGED -----------------------------
  330.  
  331.   Launch  a  new  GoldED  task.  Return  pointer  to  host  name  (or  NULL).
  332.   Screen/config  keywords  are  considered  if a new GoldED process has to be
  333.   launched, i.e. if we aren't bound to an existing environment.
  334.  
  335.   Démarrer une nouvelle tâche GoldED.  Retourne un pointeur sur le nom de l'
  336.   hôte (ou  NULL). Les mots-clé écran/config sont considérés si un nouveau
  337.   processus doit être lancé, c.à.d nous ne sommes pas liés à un environnement
  338.   existant.
  339.  
  340. */
  341.  
  342. char *
  343. StartGED(config, screen, hide)
  344.  
  345. char *config, *screen;
  346. BOOL hide;
  347. {
  348.     const char *host = "GOLDED.1";
  349.  
  350.     char command[MAX_LEN + 1];
  351.  
  352.     strcpy(command, "GoldED:GoldED ");
  353.  
  354.     if (hide)
  355.         strcat(command, "HIDE ");
  356.  
  357.     if (config)
  358.         strcat(command, xsprintf("CONFIG=\42%s\42", config));
  359.  
  360.     if (screen)
  361.         strcat(command, xsprintf("SCREEN=%s", screen));
  362.  
  363.     if (!SystemTags(command, SYS_Asynch, TRUE, SYS_Input, NULL, SYS_Output, NULL, NP_StackSize, 8192, TAG_DONE)) {
  364.  
  365.         UWORD  try;
  366.  
  367.         for (try = 50; try; try--, Delay(10))
  368.             if (FindPort(host))
  369.                 return(host);
  370.     }
  371.  
  372.     return(FALSE);
  373. }
  374.  
  375. /* --------------------------------- xsprintf ----------------------------------
  376.  
  377.  sprintf frontend (returns pointer to static buffer)
  378.  
  379.  façade sprintf (retourne le pointeur sur un tampon statique)
  380.  
  381. */
  382.  
  383. char *
  384. xsprintf(template, data)
  385.  
  386. char *template;
  387. APTR  data;
  388. {
  389.     static char buffer[MAX_LEN + 1];
  390.  
  391.     return(myprintf(buffer, template, data));
  392. }
  393.  
  394.  
  395. ///
  396. /// "ARexx"
  397.  
  398. /* ---------------------------------- SendRexxCommand -------------------------
  399.  
  400.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  401.  
  402.  Envoie un message ARexx et attend une réponse. Retourne un pointeur
  403.  résultat ou NULL.
  404.  
  405. */
  406.  
  407. ULONG *
  408. SendRexxCommand(port, cmd, replyPort)
  409.  
  410. char   *cmd,   *port;
  411. struct MsgPort *replyPort;
  412. {
  413.     struct MsgPort *rexxport;
  414.  
  415.     Forbid();
  416.  
  417.     if (rexxport = FindPort(port)) {
  418.  
  419.         struct RexxMsg *rexxMsg, *answer;
  420.  
  421.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  422.  
  423.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  424.  
  425.                 static ULONG result;
  426.  
  427.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  428.  
  429.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  430.  
  431.                 do {
  432.                     
  433.                     WaitPort(replyPort);
  434.  
  435.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  436.                         result = answer->rm_Result1;
  437.  
  438.                 } while (!answer);
  439.  
  440.                 Permit();
  441.  
  442.                 if (answer->rm_Result1 == RC_OK) 
  443.                     if (answer->rm_Result2)
  444.                         DeleteArgstring((char *)answer->rm_Result2);
  445.  
  446.                 DeleteArgstring((char *)ARG0(answer));
  447.  
  448.                 DeleteRexxMsg(answer);
  449.  
  450.                 return(&result);
  451.             }
  452.         }
  453.     }
  454.  
  455.     Permit();
  456.  
  457.     return(NULL);
  458. }
  459.  
  460. ///
  461.