home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 125.lha / MenuText / menutext.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  8KB  |  241 lines

  1. /*
  2.  *  This program will create new text for a specified menu item.
  3.  *  The new text will reside in a node linked on to the UserData
  4.  *  field of the window it resides in.
  5.  *
  6.  *  Problem: the new text will never be de-allocated unless by
  7.  *  this program (ie it stays around and waits for the window to
  8.  *  close). Or by another program that looks at the window->UserData
  9.  *  field. Use the RESTORE program I've included with this one to
  10.  *  unlink the new menuitems before closing the window.
  11.  *
  12.  *  ((c)) 1987, John Russell. Unlimited distribution, but donations to
  13.  *  starving programmers welcome.
  14.  *
  15.  */
  16.  
  17. #include "intuition/intuition.h"
  18. #include "stdio.h"
  19. #include "exec/memory.h"
  20.  
  21. char *name = "John Russell";
  22. char *address = "5 Alderdice Place";
  23. char *province = "St. John's, Newfoundland, Canada";
  24. char *postal_code = "A1B 2P8";
  25. char *phone = "(709) 726-7847";
  26.  
  27. void copy();
  28. char *gets();   /* I couldn't seem to get this to "clip" properly */
  29.  
  30. struct IntuitionBase *IntuitionBase;
  31.  
  32. struct node {
  33.     struct node *next;      /* link to next node */
  34.     char text[46];          /* buffer for menu text */
  35.     char *old_text;         /* save location for program's pointer */
  36.     short old_item_width;   /* save location for hitbox width */
  37.     struct MenuItem *altered;   /* pointer to menuitem we alter */
  38. } *node,*ptr,*findnode();
  39.  
  40. main(argc, argv)
  41. int argc;
  42. char *argv[];
  43. {
  44.     struct Window *window;
  45.     struct Screen *screen;
  46.     struct MenuItem *item;
  47.     struct Menu *menu,*main_menu;
  48.     int x,text;
  49.     short width;
  50.     char line_buf[100]; /* buffer for gets() to handle too-long strings */
  51.  
  52.     text = argc-1; /* *argv[text] == text to assign */
  53.  
  54.     if ((IntuitionBase=(struct IntuitionBase *)
  55.         OpenLibrary("intuition.library",0L))==NULL) {
  56.             puts("Where is Intuition gone???\n");
  57.             exit(0);
  58.     }
  59.  
  60. /* print instructions if wrong number of arguments */
  61.  
  62.     if ((argc > 6) || (argc < 5)) {
  63.         puts("Usage: menutext <window> <menunum> <itemnum>\n\
  64.        [ <subitemnum> ] <new_text | \"-ask\">");
  65.         puts("\nEG - menutext FooBar 1 4 testing\n\
  66.      menutext VT100 2 1 3 high_speed\n\
  67.      menutext Notepad 1 1 -ask");
  68.         exit(0);
  69.     }
  70.  
  71.     Forbid();
  72.  
  73.     screen = IntuitionBase->FirstScreen; /* address of Workbench screen structure */
  74.  
  75.     while (screen) {     /* do all screens */
  76.  
  77.         window = screen->FirstWindow;
  78.  
  79.         while (window) {    /* do all windows */
  80.  
  81.             if (compare(argv[1],window->Title)==0) {  /* search for name */
  82.  
  83.                 x=atoi(argv[2]);  /* menu # */
  84.                 menu = window->MenuStrip;
  85.                 main_menu = menu; /* main menu of window for SetMenuStrip */
  86.  
  87.                 while (--x > 0) {  /* scan menu list */
  88.                     if ((menu = menu->NextMenu) == NULL)
  89.                         goto quit;
  90.                 }
  91.  
  92.                 x = atoi(argv[3]);  /* item # */
  93.                 item = menu->FirstItem;
  94. submenu:
  95.                 while (--x > 0) {  /* scan item list */
  96.                     if ((item = item->NextItem) == NULL)
  97.                         goto quit;
  98.                 }
  99.  
  100.                 if (argc==6) { /* descend into sub-menu? */
  101.                     argc=0;
  102.                     item=item->SubItem;
  103.                     x=atoi(argv[4]); /* sub-item # */
  104.                     goto submenu;
  105.                 }
  106.  
  107.                 ClearMenuStrip(window); /* disable menu structure */
  108.  
  109. /*
  110.  *  First check to see if this menu item has already been redefined, by
  111.  *  scanning the list from window->UserData. If it has, do no node creation
  112.  *  or re-linking, just copy the text over the node's old text.
  113.  *
  114.  *  If this is the first time the menu item has received new text, create
  115.  *  a new node, record which menu item is being altered, and preserve a
  116.  *  pointer to the original text used by the program, so we can undo all
  117.  *  of this later. Also record how wide the original hitbox was for future
  118.  *  reference.
  119.  *
  120.  *  A new hitbox width is created if a new, longer string is put into the
  121.  *  menu. If a keyboard shortcut exists for that item, the hitbox is widened
  122.  *  to take that into account.
  123.  *
  124.  */
  125.  
  126.                 if ( (node = findnode(window,item)) == NULL) {
  127.  
  128.                     node = (struct node *)
  129.                         AllocMem(sizeof(struct node),MEMF_CHIP|MEMF_CLEAR);
  130.                     node->next = window->UserData;  /* insert in first place */
  131.                     window->UserData = node;  /* link into window structure */
  132.                     node->altered = item;
  133.                     node->old_text = item->ItemFill->IText; /* save old text */
  134.                     node->old_item_width = item->Width; /* save old width */
  135.                     item->ItemFill->IText = node->text; /* change menu itself */
  136.  
  137.                 }
  138.  
  139.                 if (compare(argv[text],"-ask")) {
  140.                     copy(argv[text],node->text);    /* special strncpy() */
  141.                 }
  142.                 else {
  143.                     printf("Enter new menu text: ");
  144.                     gets(line_buf,45);  /* "45" ignored? seems that way */
  145.                     copy(line_buf,node->text);
  146.                 }
  147.  
  148. /* alter width if necessary, so you don't have long menutexts with very */
  149. /* short complemented or boxed areas. font-size is fixed at 8 because */
  150. /* the "TextAttr" structure is not in the Intuition manual, and the RKM */
  151. /* is not handy. */
  152.  
  153.                 width = ((length(node->text)) * 8) +
  154.                         (item->Flags & COMMSEQ ? COMMWIDTH : 0);
  155.  
  156.                 if (width > node->old_item_width) {
  157.                     item->Width = width;    /* don't shorten, just lengthen */
  158.                 }
  159.  
  160. /* debugging info left in. This program, although it works fine, can be */
  161. /* (and will be) revised extensively. */
  162.  
  163.                 ptr = window->UserData;
  164.  
  165.                 printf("Replacing menutext \"%s\" with \"%s\"\n\n",
  166.                     node->old_text,node->text);
  167.  
  168.                 printf("Current changed definitions:\n");
  169.  
  170.                 while (ptr) {
  171.                     printf("\tOld text: %s\n\tNew text: %s\n\n",
  172.                         ptr->old_text,ptr->text);
  173.                     ptr = ptr->next;
  174.                 }
  175.  
  176.                 SetMenuStrip(window,main_menu); /* give it back */
  177.             }
  178.         window = window->NextWindow;
  179.         }
  180.     screen = screen->NextScreen;
  181.     }
  182.  
  183.     quit:
  184.     Permit();
  185.     CloseLibrary(IntuitionBase);
  186.  
  187. }
  188.  
  189. compare(string1,string2) /* if spaces in windowname, only check first word */
  190. char *string1,*string2;
  191. {
  192.     while ((*string1 != '\0') && (*string1 != ' ')) {
  193.         if (*string1++ != *string2++) /* space and null both end conditions */
  194.             return(1);
  195.     }
  196.     return(0);  /* return weird values like strcmp() */
  197. }
  198.  
  199. void copy(string1,string2)  /* modified strncpy */
  200. char *string1,*string2;
  201. {
  202.     int count = 44;   /* (44 + space + null) will fill available buffer */
  203.  
  204.     while ((*string1 != '\0') && count) {
  205.         *string2++ = *string1++;
  206.         count--;
  207.     }
  208.     *string2++ = ' ';   /* always end string with space + null */
  209.     *string2++ = '\0';  /* otherwise menus with shortcuts are messy */
  210. }
  211.  
  212. struct node *findnode(window,item) /* does item already have attached node? */
  213. struct Window *window;
  214. struct MenuItem *item;
  215. {
  216.     struct node *ptr;
  217.  
  218.     ptr = window->UserData;
  219.  
  220.     while (ptr) {
  221.         if (ptr->altered == item) /* if desired item already redefined */
  222.             return(ptr);  /* this is the node to use */
  223.  
  224.         ptr = ptr->next;
  225.     }
  226.  
  227.     return(NULL);   /* search failed, send message to create and link node */
  228. }
  229.  
  230. length(string)  /* I hate (and don't really trust) std C string functions */
  231. char *string;
  232. {
  233.     int x=0;
  234.  
  235.     while (*string++)
  236.         x++;
  237.  
  238.     return(x);
  239. }
  240.  
  241.