home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / programme / GoldED / developer / examples / quickstarter / ed.c next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  12.7 KB  |  575 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.   ED 3.4 - GoldED quick starter, ©1996 Dietmar Eilert.
  4.  
  5.   This is C source code of ED to give you an idea of how to address GoldED
  6.   from other applications. Feel free to change this code. Dice:
  7.  
  8.   dcc ed.c sprintf.a -// -proto -mRR -mi -pr -2.0 -o ram:ed
  9.  
  10.   ------------------------------------------------------------------------------
  11. */
  12.  
  13. /// "includes"
  14.  
  15. #include <exec/exec.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <stdarg.h>
  21. #include <intuition/intuition.h>
  22. #include <dos/dos.h>
  23. #include <dos/dosextens.h>
  24. #include <dos/rdargs.h>
  25. #include <dos/dostags.h>
  26. #include <workbench/startup.h>
  27. #include <workbench/workbench.h>
  28. #include <rexx/errors.h>
  29. #include <rexx/rxslib.h>
  30.  
  31. #include <clib/alib_protos.h>
  32. #include <clib/dos_protos.h>
  33. #include <clib/exec_protos.h>
  34. #include <clib/icon_protos.h>
  35. #include <clib/intuition_protos.h>
  36. #include <clib/utility_protos.h>
  37. #include <clib/rexxsyslib_protos.h>
  38. #include <clib/wb_protos.h>
  39.  
  40. #define Prototype        extern
  41. #define MAX_LEN          120
  42. #define MAX_LENPLUSONE   121
  43. #define ARGBUFFER_SIZE   8192
  44. #define ARGBUFFER_LIMIT  8000
  45.  
  46. ///
  47. /// "prototypes"
  48.  
  49. Prototype void    main(ULONG, UBYTE **);
  50. Prototype int     wbmain(struct WBStartup *);
  51. Prototype void    Action(UBYTE *, UBYTE *, BOOL, BOOL, ULONG *, UBYTE *, UBYTE *);
  52. Prototype UBYTE  *StartGED(UBYTE *, BOOL, UBYTE *, UBYTE *, UBYTE *);
  53. Prototype ULONG  *SendRexxCommand(UBYTE *, UBYTE *, struct MsgPort *);
  54. Prototype UBYTE  *LookForGED(UBYTE *);
  55. Prototype UBYTE  *myprintf(UBYTE *, UBYTE *, ...);
  56. Prototype UBYTE  *xstrcpy (UBYTE *, UBYTE *);
  57. Prototype UBYTE  *xsprintf(UBYTE *, APTR);
  58. Prototype BOOL    FindAssign(UBYTE *);
  59.  
  60. extern struct Library *IconBase;
  61. extern struct Library *DOSBase;
  62. extern struct Library *SysBase;
  63. extern struct Library *IntuitionBase;
  64.  
  65. // globals
  66.  
  67. UBYTE Version[] = "$VER: ED 3.4 (" __COMMODORE_DATE__ ")";
  68.  
  69. ///
  70. /// "entry points"
  71.  
  72. /* --------------------------------------- main --------------------------------
  73.  
  74.  CLI entry point. Parse command line - create a string <argBuffer> containing
  75.  provided  file  names  (file names are made absolute). This string has to be
  76.  FreeVec()'ed later on. Additionally, command line options are checked.
  77.  
  78. */
  79.  
  80. void
  81. main(argc, argv)
  82.  
  83. ULONG argc;
  84. UBYTE *argv[];
  85. {
  86.     UBYTE *argBuffer;
  87.     UWORD  error;
  88.  
  89.     error = 0;
  90.  
  91.     if (argBuffer = AllocVec(ARGBUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
  92.  
  93.         struct RDArgs *rdArgs;
  94.  
  95.         ULONG args[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  96.  
  97.         if (rdArgs = ReadArgs("FILETYPE/K,Y=STICKY/S,F=FILE/M,HIDE/S,-STICKY/S,L=LINE/N,A=AREXX/K,SESSION/K", args, NULL)) {
  98.  
  99.             if (args[2]) {                           // FILE/M
  100.  
  101.                 UBYTE **nextFile, path[MAX_LENPLUSONE];
  102.                 BPTR    lock;
  103.  
  104.                 for (nextFile = (UBYTE **)args[2]; *nextFile; ++nextFile) {
  105.  
  106.                     strcpy(path, *nextFile);
  107.  
  108.                     // expand file name
  109.  
  110.                     if (lock = Lock(path, ACCESS_READ)) {
  111.  
  112.                         NameFromLock(lock, path, MAX_LEN);
  113.  
  114.                         UnLock(lock);
  115.                     }
  116.                     else if (strchr(path, ':') == NULL) {
  117.  
  118.                         GetCurrentDirName(path, MAX_LEN);
  119.  
  120.                         AddPart(path, *nextFile, MAX_LEN);
  121.                     }
  122.  
  123.                     strcat(argBuffer, "\42");
  124.  
  125.                     strcat(argBuffer, path);
  126.  
  127.                     strcat(argBuffer, "\42 ");
  128.  
  129.                     // too many files ?
  130.  
  131.                     if (strlen(argBuffer) > ARGBUFFER_LIMIT)
  132.                         break;
  133.                 }
  134.             }
  135.  
  136.             Action(argBuffer, (UBYTE *)args[0], args[1] || args[4], (BOOL)args[3], (ULONG *)args[5], (UBYTE *)args[6], (UBYTE *)args[7]);
  137.  
  138.             FreeArgs(rdArgs);
  139.         }
  140.         else
  141.             error = 20;
  142.  
  143.         FreeVec(argBuffer);
  144.     }
  145.  
  146.     exit(error);
  147. }
  148.  
  149.  
  150. /* ------------------------------------ wbmain ---------------------------------
  151.  
  152.  Workbench entry point. Read tooltypes of text icon(s) to decide wether user
  153.  prefers a special configuration.
  154.  
  155. */
  156.  
  157. int
  158. wbmain(struct WBStartup *wbs)
  159. {
  160.     UBYTE *argBuffer;
  161.  
  162.     if (argBuffer = AllocVec(ARGBUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) {
  163.  
  164.         struct DiskObject *diskObject = NULL;
  165.  
  166.         UBYTE  *filetype;
  167.         UBYTE  *arexx;
  168.         UBYTE  *session;
  169.         BOOL    hide;
  170.  
  171.         filetype = NULL;
  172.         arexx    = NULL;
  173.         session  = NULL;
  174.  
  175.         hide = FALSE;
  176.  
  177.         if (--wbs->sm_NumArgs) {
  178.  
  179.             struct WBArg *wbArg = wbs->sm_ArgList;
  180.  
  181.             while ((wbs->sm_NumArgs)--) {
  182.  
  183.                 UBYTE file[MAX_LENPLUSONE];
  184.  
  185.                 ++wbArg;
  186.  
  187.                 NameFromLock(wbArg->wa_Lock, file, MAX_LEN);
  188.  
  189.                 AddPart(file, wbArg->wa_Name, MAX_LEN);
  190.  
  191.                 // options not yet read ?
  192.  
  193.                 if (diskObject == NULL) {
  194.  
  195.                     if (diskObject = GetDiskObject(file)) {
  196.  
  197.                         filetype = FindToolType(diskObject->do_ToolTypes, "FILETYPE");
  198.                         arexx    = FindToolType(diskObject->do_ToolTypes, "AREXX"   );
  199.                         session  = FindToolType(diskObject->do_ToolTypes, "SESSION" );
  200.  
  201.                         if (FindToolType(diskObject->do_ToolTypes, "HIDE"))
  202.  
  203.                             hide = TRUE;
  204.                     }
  205.                 }
  206.  
  207.                 strcat(argBuffer, "\42");
  208.  
  209.                 strcat(argBuffer, file);
  210.  
  211.                 strcat(argBuffer, "\42 ");
  212.  
  213.                 // too many files ?
  214.  
  215.                 if (strlen(argBuffer) > ARGBUFFER_LIMIT)
  216.                     break;
  217.             }
  218.         }
  219.  
  220.         Action(argBuffer, filetype, FALSE, hide, NULL, arexx, session);
  221.  
  222.         if (diskObject)
  223.  
  224.             FreeDiskObject(diskObject);
  225.  
  226.         FreeVec(argBuffer);
  227.     }
  228.  
  229.     exit(0);
  230. }
  231.  
  232. ///
  233. /// "main routine"
  234.  
  235. /* ------------------------------------ Action ---------------------------------
  236.  
  237.  Run GoldED if no running instance of GED is found (note: running GED will open
  238.  a first window, i.e. no need to open a further one unless files are specified).
  239.  Send LOCK message to running GoldED. Wait for positive reply, pass our list of
  240.  <files> to that editor, unlock editor (use delayed unlock if <sticky> is
  241.  specified). Files are passed to GoldED as startup options if STICKY is not
  242.  specifed and if there is no running GoldED instance.
  243.  
  244. */
  245.  
  246. void
  247. Action(files, filetype, sticky, hide, line, arexx, session)
  248.  
  249. UBYTE  *files, *filetype, *arexx, *session;
  250. ULONG  *line;
  251. BOOL    hide, sticky;
  252. {
  253.     UBYTE *host;
  254.  
  255.     if (host = LookForGED(arexx)) {                  // GoldED found ?
  256.  
  257.          struct MsgPort *replyPort;
  258.  
  259.          if (replyPort = CreateMsgPort()) {
  260.  
  261.             if (session)
  262.  
  263.                 SendRexxCommand(host, xsprintf("SESSION LOAD CONFIG=\42%s\42", session), replyPort);
  264.  
  265.             else if (*files) {
  266.  
  267.                 ULONG *result;
  268.  
  269.                 if (result = SendRexxCommand(host, "LOCK CURRENT RELEASE=4", replyPort)) {
  270.  
  271.                     if (*result == RC_OK) {
  272.  
  273.                         if (*files) {
  274.  
  275.                             if (filetype)
  276.  
  277.                                 strins(files, xsprintf("FILETYPE=\42%s\42 ", filetype));
  278.  
  279.                             strins(files, "OPEN SMART QUIET ");
  280.                         }
  281.                         else
  282.                             strcpy(files, "MORE SMART");
  283.  
  284.                         SendRexxCommand(host, files, replyPort);
  285.  
  286.                         if (line)
  287.                             SendRexxCommand(host, xsprintf("GOTO LINE=%ld UNFOLD=TRUE", (APTR)*line), replyPort);
  288.  
  289.                         SendRexxCommand(host, sticky ? "UNLOCK STICKY" : "UNLOCK", replyPort);
  290.                     }
  291.                 }
  292.             }
  293.             else {
  294.  
  295.                 // GoldED might be iconified - send wake-up-command (any command will do)
  296.  
  297.                 SendRexxCommand(host, "SCREEN FRONT", replyPort);
  298.             }
  299.         }
  300.  
  301.         DeleteMsgPort(replyPort);
  302.     }
  303.     else if (host = StartGED(arexx, hide, filetype, files, session)) {
  304.  
  305.         if (line) {
  306.  
  307.             struct MsgPort *replyPort;
  308.  
  309.             if (replyPort = CreateMsgPort()) {
  310.  
  311.                 SendRexxCommand(host, xsprintf("GOTO LINE=%ld UNFOLD=TRUE", (APTR)*line), replyPort);
  312.  
  313.                 DeleteMsgPort(replyPort);
  314.             }
  315.         }
  316.  
  317.         if (sticky) {
  318.  
  319.             struct MsgPort *replyPort;
  320.  
  321.             if (replyPort = CreateMsgPort()) {
  322.  
  323.                 if (SendRexxCommand(host, "LOCK CURRENT RELEASE=4", replyPort))
  324.  
  325.                     SendRexxCommand(host, sticky ? "UNLOCK STICKY" : "UNLOCK", replyPort);
  326.  
  327.                 DeleteMsgPort(replyPort);
  328.             }
  329.         }
  330.     }
  331. }
  332.  
  333. ///
  334. /// "misc"
  335.  
  336. /* -------------------------------- FindAssign ---------------------------------
  337.  
  338.  Check whether assign exists without annoying 'insert drive' requester
  339.  
  340. */
  341.  
  342. BOOL
  343. FindAssign(assign)
  344.  
  345. UBYTE *assign;
  346. {
  347.     BOOL success = (FindDosEntry(LockDosList(LDF_ASSIGNS | LDF_READ), assign, LDF_ASSIGNS) != NULL);
  348.  
  349.     UnLockDosList(LDF_ASSIGNS | LDF_READ);
  350.  
  351.     return(success);
  352. }
  353.  
  354.  
  355. /* ----------------------------------- LookForGED ----------------------------
  356.  
  357.  Look for running GoldED task.
  358.  
  359. */
  360.  
  361. UBYTE *
  362. LookForGED(host)
  363.  
  364. UBYTE *host;
  365. {
  366.     UBYTE *name;
  367.  
  368.     Forbid();
  369.  
  370.     if (host && FindPort(host))
  371.  
  372.         name = host;
  373.  
  374.     else {
  375.  
  376.         static UBYTE try[] = "GOLDED.1";
  377.  
  378.         for (name = NULL; try[7] != '9'; ++try[7]) {
  379.  
  380.             if (FindPort(try)) {
  381.  
  382.                 name = try;
  383.  
  384.                 break;
  385.             }
  386.         }
  387.     }
  388.  
  389.     Permit();
  390.  
  391.     return(name);
  392. }
  393.  
  394.  
  395. /* ------------------------------------- StartGED ------------------------------
  396.  
  397.  Launch a new GoldED task. Look for "GOLDED:" assign. Create assign if none is
  398.  found (assign[] is set by the GoldED installer script). Return pointer to host
  399.  name (or NULL).
  400.  
  401. */
  402.  
  403. UBYTE *
  404. StartGED(arexx, hide, filetype, files, session)
  405.  
  406. UBYTE *arexx;
  407. UBYTE *filetype;
  408. UBYTE *files;
  409. UBYTE *session;
  410. BOOL   hide;
  411. {
  412.     UBYTE assign [MAX_LENPLUSONE] = "$GOLDED";
  413.     UBYTE command[MAX_LENPLUSONE];
  414.  
  415.     struct MsgPort *port;
  416.     UBYTE          *host;
  417.     UBYTE          *cmd;
  418.  
  419.     port = NULL;
  420.  
  421.     if (FindAssign("GOLDED") == FALSE)
  422.  
  423.         AssignLock("GOLDED", Lock(assign, ACCESS_READ));
  424.  
  425.     cmd = (files) ? files : command;
  426.  
  427.     if (session)
  428.  
  429.         strcpy(cmd, xsprintf("SESSION=\42%s\42", session));
  430.  
  431.     if (filetype)
  432.  
  433.         strins(cmd, xsprintf("FILETYPE=\42%s\42 ", filetype));
  434.  
  435.     if (host = arexx)
  436.  
  437.         strins(cmd, xsprintf("AREXX=\42%s\42 ", arexx));
  438.  
  439.     if (host == NULL)
  440.  
  441.         host = "GOLDED.1";
  442.  
  443.     if (hide)
  444.  
  445.         strins(cmd, "HIDE ");
  446.  
  447.     strins(cmd, "GOLDED:GOLDED ");
  448.  
  449.     if (SystemTags(cmd, SYS_Asynch, TRUE, SYS_Input, NULL, SYS_Output, NULL, NP_StackSize, 8192, TAG_DONE) == 0) {
  450.  
  451.         UWORD try;
  452.  
  453.         for (try = 50; try--; Delay(10)) {
  454.  
  455.             Forbid();
  456.  
  457.             port = FindPort(host);
  458.  
  459.             Permit();
  460.  
  461.             if (port)
  462.                 break;
  463.         }
  464.     }
  465.  
  466.     if (port)
  467.         return(host);
  468.     else
  469.         return(NULL);
  470. }
  471.  
  472.  
  473. /* --------------------------------- xsprintf ----------------------------------
  474.  
  475.  sprintf frontend (returns pointer to static buffer)
  476.  
  477. */
  478.  
  479. UBYTE *
  480. xsprintf(template, data)
  481.  
  482. UBYTE *template;
  483. APTR  data;
  484. {
  485.     static UBYTE buffer[MAX_LENPLUSONE];
  486.  
  487.     return(myprintf(buffer, template, data));
  488. }
  489.  
  490.  
  491. /* ---------------------------------- xstrcpy ----------------------------------
  492.  
  493.  strcpy() frontend (handles NULL argument)
  494.  
  495. */
  496.  
  497. UBYTE *
  498. xstrcpy(dest, src)
  499.  
  500. UBYTE *dest, *src;
  501. {
  502.     if (src)
  503.         strcpy(dest, src);
  504.     else
  505.         *dest = 0;
  506.  
  507.     return(dest);
  508. }
  509.  
  510. ///
  511. /// "ARexx"
  512.  
  513. /* ---------------------------------- SendRexxCommand -------------------------
  514.  
  515.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  516.  
  517. */
  518.  
  519. ULONG *
  520. SendRexxCommand(port, cmd, replyPort)
  521.  
  522. struct MsgPort *replyPort;
  523. UBYTE          *cmd, *port;
  524. {
  525.     struct MsgPort *rexxport;
  526.  
  527.     Forbid();
  528.  
  529.     if (rexxport = FindPort(port)) {
  530.  
  531.         struct RexxMsg *rexxMsg, *answer;
  532.  
  533.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  534.  
  535.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  536.  
  537.                 static ULONG result;
  538.  
  539.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  540.  
  541.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  542.  
  543.                 do {
  544.                     
  545.                     WaitPort(replyPort);
  546.  
  547.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  548.                         result = answer->rm_Result1;
  549.  
  550.                 } while (!answer);
  551.  
  552.                 Permit();
  553.  
  554.                 if (answer->rm_Result1 == RC_OK) 
  555.  
  556.                     if (answer->rm_Result2)
  557.  
  558.                         DeleteArgstring((UBYTE *)answer->rm_Result2);
  559.  
  560.                 DeleteArgstring((UBYTE *)ARG0(answer));
  561.  
  562.                 DeleteRexxMsg(answer);
  563.  
  564.                 return(&result);
  565.             }
  566.         }
  567.     }
  568.  
  569.     Permit();
  570.  
  571.     return(NULL);
  572. }
  573.  
  574. ///
  575.