home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Enlightenment / enl14.tgz / enl14.tar / enl14 / buttons.c < prev    next >
C/C++ Source or Header  |  1997-11-21  |  31KB  |  1,283 lines

  1. #include "enl.h"
  2.  
  3. void FreeStrip(Strip *item)
  4. {
  5.    int i;
  6.    
  7.    if (item->name) Efree(item->name);
  8.    if (item->strip) DelStripFromStrip(item,item->strip);
  9.    if (item->list)
  10.      {
  11.     for(i=0;i<item->num;i++)
  12.       {
  13.          if (item->list[i].item)
  14.            {
  15.           if (item->list[i].type==LIST_TYPE_BUTTON)
  16.             {
  17.                DelItem(((Button *)(item->list[i].item))->name,
  18.                    LIST_TYPE_BUTTON);
  19.                FreeButton((Button *)item->list[i].item);
  20.             }
  21.           else if (item->list[i].type==LIST_TYPE_STRIP)
  22.             {
  23.                DelItem(((Strip *)(item->list[i].item))->name,
  24.                    LIST_TYPE_STRIP);
  25.                FreeStrip((Strip *)item->list[i].item);
  26.             }
  27.            }
  28.       }
  29.     Efree(item->list);
  30.      }
  31.    Efree(item);
  32. }
  33.  
  34. Strip *CfgReadStrip()
  35. {
  36.    Strip *s;
  37.    char st[256],*w;
  38.    
  39.    s=Emalloc(sizeof(Strip));
  40.    if (!s) return NULL;
  41.    s->loc.handle_macro=COORD_MACRO_TOPLEFT;
  42.    s->loc.from_macro=COORD_MACRO_TOPLEFT;
  43.    s->loc.x_handle=0;
  44.    s->loc.y_handle=0;
  45.    s->loc.x_handle_at=0;
  46.    s->loc.y_handle_at=0;
  47.    s->loc.x_from=0;
  48.    s->loc.y_from=0;
  49.    s->loc.x_from_at=0;
  50.    s->loc.x_from_at=0;
  51.    s->loc.x=0;
  52.    s->loc.y=0;
  53.    s->name=NULL;
  54.    s->orientation=STRIP_ORIENTATION_VERTICAL;
  55.    s->justification=0;
  56.    s->strip=NULL;
  57.    s->strip_loc=STRIP_LOCATION_END;
  58.    s->num=0;
  59.    s->list=NULL;
  60.    s->X.x=0;
  61.    s->X.y=0;
  62.    s->X.width=0;
  63.    s->X.height=0;
  64.    while (CfgGetLine(NULL))
  65.      {
  66.     word(line,1,st);
  67.     if (!strcmp(st,"name"))
  68.       {
  69.          word(line,2,st);s->name=duplicate(st);
  70.       }
  71.     else if (!strcmp(st,"orientation"))
  72.       {
  73.          word(line,2,st);
  74.          if (!strcmp(st,"vertical"))
  75.            s->orientation=STRIP_ORIENTATION_VERTICAL;
  76.          else
  77.            s->orientation=STRIP_ORIENTATION_HORIZONTAL;
  78.       }
  79.     else if (!strcmp(st,"location"))
  80.       {
  81.          CfgParseLocLine(line,&s->loc);
  82.       }
  83.     else if (!strcmp(st,"strip"))
  84.       {
  85.          word(line,2,st);s->strip=(Strip *)FindItem(st,LIST_TYPE_STRIP);
  86.          word(line,3,st);
  87.          if (!strcmp(st,"end"))
  88.            s->strip_loc=STRIP_LOCATION_END;
  89.          else if (!strcmp(st,"start"))
  90.            s->strip_loc=STRIP_LOCATION_START;
  91.          AddStripToStrip(s,s->strip,s->strip_loc);
  92.       }
  93.     else if (!strcmp(st,"justification"))
  94.       {
  95.          word(line,2,st);
  96.          w=atchar(st,'%');
  97.          if (w) *w=0;
  98.          s->justification=atoi(st);
  99.       }
  100.     else if (!strcmp(st,"end"))
  101.       {
  102.          return s;
  103.       }
  104.      }
  105.    if (s->name) Efree(s->name);
  106.    Efree(s);
  107.    return NULL;
  108. }
  109.  
  110. void CfgLoadStrip()
  111. {
  112.    Strip *s;
  113.    
  114.    s=CfgReadStrip();
  115.    if (s) AddItem((void *)s,s->name,LIST_TYPE_STRIP);
  116. }
  117.  
  118. void FreeButton(Button *item)
  119. {
  120.    Strip *s;
  121.    
  122.    if (!item) return;
  123.    if (item->name) Efree(item->name);
  124.    if (item->strip)
  125.      {
  126.     s=item->strip;
  127.     DelButtonFromStrip(item,s);
  128.     DrawStrip(s);
  129.      }
  130.    if (item->actions) Efree(item->actions);
  131.    if (item->X.pmap) ImlibFreePixmap(imd,item->X.pmap);
  132.    if (item->X.mask) ImlibFreePixmap(imd,item->X.mask);
  133.    if (item->X.win) XDestroyWindow(disp,item->X.win);
  134.    Efree(item);
  135. }
  136.  
  137. Button *MakeButton(char *name, char *iclass, int x, int y, int width, int height)
  138. {
  139.    Button *b;
  140.    int mask;
  141.    XSetWindowAttributes att;
  142.    
  143.     if (!name) return NULL;
  144.     if (!iclass) return NULL;
  145.    b=Emalloc(sizeof(Button));
  146.    if (!b) return NULL;
  147.    b->loc.handle_macro=COORD_MACRO_TOPLEFT;
  148.    b->loc.from_macro=COORD_MACRO_TOPLEFT;
  149.    b->loc.x_handle=0;
  150.    b->loc.y_handle=0;
  151.    b->loc.x_handle_at=0;
  152.    b->loc.y_handle_at=0;
  153.    b->loc.x_from=0;
  154.    b->loc.y_from=0;
  155.    b->loc.x_from_at=0;
  156.    b->loc.x_from_at=0;
  157.    b->loc.x=x;
  158.    b->loc.y=y;
  159.    b->width.min=0;
  160.    b->width.max=0;
  161.    b->height.min=0;
  162.    b->height.max=0;
  163.    b->name=duplicate(name);
  164.    b->iclass=(ImageClass *)FindItem(iclass,LIST_TYPE_IMAGECLASS);
  165.    b->pstate=-1;
  166.    b->state=STATE_NORMAL;
  167.    b->strip=NULL;
  168.    b->strip_loc=STRIP_LOCATION_END;
  169.    b->num=0;
  170.    b->actions=NULL;
  171.    b->pX.x=-1;
  172.    b->pX.y=-1;
  173.    b->pX.width=-1;
  174.    b->pX.height=-1;
  175.    b->pX.pmap=0;
  176.    b->pX.mask=0;
  177.    b->X.x=10;
  178.    b->X.y=10;
  179.    b->X.width=20;
  180.    b->X.height=20;
  181.    b->X.pmap=0;
  182.    b->X.mask=0;
  183.     b->size.x=width;b->size.x_at=0;
  184.     b->size.y=height;b->size.y_at=0;
  185.     if (!width)
  186.       b->size.x=b->iclass->normal->im->rgb_width;
  187.     if (!height)
  188.       b->size.y=b->iclass->normal->im->rgb_height;
  189.    att.backing_store=NotUseful;/* NotUseful WhenMapped Always */
  190.    att.save_under=False;
  191.    att.override_redirect=True;
  192.    mask=CWOverrideRedirect|CWSaveUnder|CWBackingStore;
  193.    b->X.win=XCreateWindow(disp,DefaultRootWindow(disp),-10,-10,5,5,0,
  194.                                   imd->x.depth,InputOutput,imd->x.visual,mask,&att);
  195.    XSelectInput(disp,b->X.win,ButtonPressMask|ButtonReleaseMask|EnterWindowMask
  196.                      |LeaveWindowMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask);
  197.     AddItem((void *)b,b->name,LIST_TYPE_BUTTON);
  198.     CalcButton(b);
  199.     DrawButton(b);
  200.     return b;
  201. }
  202.  
  203. Button *CfgReadButton()
  204. {
  205.    Button *b;
  206.    int mask;
  207.    XSetWindowAttributes att;
  208.    char s[1024];
  209.    
  210.    b=Emalloc(sizeof(Button));
  211.    if (!b) return NULL;
  212.    b->loc.handle_macro=COORD_MACRO_TOPLEFT;
  213.    b->loc.from_macro=COORD_MACRO_TOPLEFT;
  214.    b->loc.x_handle=0;
  215.    b->loc.y_handle=0;
  216.    b->loc.x_handle_at=0;
  217.    b->loc.y_handle_at=0;
  218.    b->loc.x_from=0;
  219.    b->loc.y_from=0;
  220.    b->loc.x_from_at=0;
  221.    b->loc.x_from_at=0;
  222.    b->loc.x=0;
  223.    b->loc.y=0;
  224.    b->width.min=0;
  225.    b->width.max=0;
  226.    b->height.min=0;
  227.    b->height.max=0;
  228.    b->name=NULL;
  229.    b->iclass=NULL;
  230.    b->pstate=-1;
  231.    b->state=STATE_NORMAL;
  232.    b->strip=NULL;
  233.    b->strip_loc=STRIP_LOCATION_END;
  234.    b->num=0;
  235.    b->actions=NULL;
  236.    b->pX.x=-1;
  237.    b->pX.y=-1;
  238.    b->pX.width=-1;
  239.    b->pX.height=-1;
  240.    b->pX.pmap=0;
  241.    b->pX.mask=0;
  242.    b->X.x=10;
  243.    b->X.y=10;
  244.    b->X.width=20;
  245.    b->X.height=20;
  246.    b->X.pmap=0;
  247.    b->X.mask=0;
  248.     b->size.x=0;b->size.x_at=0;
  249.     b->size.y=0;b->size.y_at=0;
  250.    att.backing_store=NotUseful;/* NotUseful WhenMapped Always */
  251.    att.save_under=False;
  252.    att.override_redirect=True;
  253.    mask=CWOverrideRedirect|CWSaveUnder|CWBackingStore;
  254.    b->X.win=XCreateWindow(disp,DefaultRootWindow(disp),-10,-10,5,5,0,
  255.                                   imd->x.depth,InputOutput,imd->x.visual,mask,&att);
  256.    XSelectInput(disp,b->X.win,ButtonPressMask|ButtonReleaseMask|EnterWindowMask
  257.                      |LeaveWindowMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask);
  258.    while(CfgGetLine(NULL))
  259.      {
  260.          word(line,1,s);
  261.          if (!strcmp(s,"name"))
  262.           {
  263.               word(line,2,s);
  264.               b->name=duplicate(s);
  265.           }
  266.          else if (!strcmp(s,"image_class"))
  267.           {
  268.               word(line,2,s);
  269.               b->iclass=(ImageClass *)FindItem(s,LIST_TYPE_IMAGECLASS);
  270.               b->X.width=b->iclass->normal->im->rgb_width;
  271.               b->X.height=b->iclass->normal->im->rgb_height;
  272.           }
  273.          else if (!strcmp(s,"begin"))
  274.           {
  275.               word(line,2,s);
  276.               if (!strcmp(s,"geometry"))
  277.                  CfgReadGeometry(b);
  278.               if (!strcmp(s,"actions"))
  279.                  CfgReadActions(&b->actions,&b->num);
  280.           }
  281.          else if (!strcmp(s,"end"))
  282.           {
  283.               return b;
  284.           }
  285.      }
  286.    if (b->name) Efree(b->name);
  287.    if (b->strip) DelButtonFromStrip(b,b->strip);
  288.    Efree(b);
  289.    return NULL;
  290. }
  291.  
  292. void CfgLoadButton()
  293. {
  294.    Button *b;
  295.    
  296.    b=CfgReadButton();
  297.    if (b) AddItem((void *)b,b->name,LIST_TYPE_BUTTON);
  298. }
  299.  
  300. void CfgReadGeometry(Button *b)
  301. {
  302.    char s[256];
  303.    
  304.    while (CfgGetLine(NULL))
  305.      {
  306.     word(line,1,s);
  307.     if (!strcmp(s,"size"))
  308.       CfgParseSizeLine(line,&b->size);
  309.     else if (!strcmp(s,"location"))
  310.       CfgParseLocLine(line,&b->loc);
  311.     else if (!strcmp(s,"strip"))
  312.       {
  313.          word(line,2,s);b->strip=(Strip *)FindItem(s,LIST_TYPE_STRIP);
  314.          word(line,3,s);
  315.          if (!strcmp(s,"end"))
  316.            b->strip_loc=STRIP_LOCATION_END;
  317.          else if (!strcmp(s,"start"))
  318.            b->strip_loc=STRIP_LOCATION_START;
  319.          AddButtonToStrip(b,b->strip,b->strip_loc);
  320.       }
  321.     else if (!strcmp(s,"constrain"))
  322.       {
  323.          word(line,2,s);
  324.          if (!strcmp(s,"width"))
  325.            CfgParseConstrain(line,&b->width);
  326.          else if (!strcmp(s,"height"))
  327.            CfgParseConstrain(line,&b->height);
  328.       }
  329.     else if (!strcmp(s,"end"))
  330.       {
  331.          return;
  332.       }
  333.      }
  334. }
  335.  
  336. void CfgReadActions(ActionInit **a, int *num)
  337. {
  338.    char s[256];
  339.    int n;
  340.    ActionInit *aa;
  341.    
  342.    n=0;
  343.    *a=NULL;
  344.    while (CfgGetLine(NULL))
  345.      {
  346.          word(line,1,s);
  347.          if (!strcmp(s,"mouse"))
  348.           {
  349.               n++;
  350.               *a=Erealloc(*a,n*sizeof(ActionInit));
  351.               aa=*a;
  352.               CfgParseMouseAction(line,&aa[n-1]);
  353.           }
  354.          else if (!strcmp(s,"key"))
  355.           {
  356.               n++;
  357.               *a=Erealloc(*a,n*sizeof(ActionInit));
  358.               aa=*a;
  359.               CfgParseKeyAction(line,&aa[n-1]);
  360.           }
  361.          else if (!strcmp(s,"end"))
  362.           {
  363.               *num=n;
  364.               return;
  365.           }
  366.      }
  367. }
  368.  
  369. void AddButtonAction(Button *b, char *line)
  370. {
  371.    ActionInit *aa;
  372.    char s[256];
  373.    
  374.    if (!b) return;
  375.    if (!line) return;
  376.    word(line,1,s);
  377.    if (!strcmp(s,"mouse"))
  378.      {
  379.          b->num++;
  380.          b->actions=Erealloc(b->actions,b->num*sizeof(ActionInit));
  381.          aa=b->actions;
  382.          CfgParseMouseAction(line,&aa[b->num-1]);
  383.      }
  384.    else if (!strcmp(s,"key"))
  385.      {
  386.          b->num++;
  387.          b->actions=Erealloc(b->actions,b->num*sizeof(ActionInit));
  388.          aa=b->actions;
  389.          CfgParseKeyAction(line,&aa[b->num-1]);
  390.      }
  391. }
  392.  
  393. void AddButtonActionCallback(Button *b, char *line, void (*cb)())
  394. {
  395.    ActionInit *aa;
  396.    char s[256];
  397.    void (**ptr)();
  398.     
  399.    if (!b) return;
  400.    if (!line) return;
  401.    word(line,1,s);
  402.     aa=NULL;
  403.    if (!strcmp(s,"mouse"))
  404.      {
  405.          b->num++;
  406.          b->actions=Erealloc(b->actions,b->num*sizeof(ActionInit));
  407.          aa=b->actions;
  408.          CfgParseMouseAction(line,&aa[b->num-1]);
  409.      }
  410.    else if (!strcmp(s,"key"))
  411.      {
  412.          b->num++;
  413.          b->actions=Erealloc(b->actions,b->num*sizeof(ActionInit));
  414.          aa=b->actions;
  415.          CfgParseKeyAction(line,&aa[b->num-1]);
  416.      }
  417.     if (aa)
  418.      {
  419.          aa[b->num-1].action.id=ACTION_CALLBACK;
  420.          aa[b->num-1].action.params=(char *)malloc(sizeof(void (*)()));
  421.          ptr=((void (**)())aa[b->num-1].action.params);
  422.          *ptr=cb;
  423.      }
  424. }
  425.  
  426. void CfgParseMouseAction(char *lin, ActionInit *a)
  427. {
  428.    char s[256],ss[256],*w;
  429.    int cnt,i;
  430.    
  431.    a->event=0;
  432.    a->any=0;
  433.    a->anykey=0;
  434.    a->modifiers=0;
  435.    a->button=0;
  436.    a->key=0;
  437.    a->action.id=0;
  438.    a->action.params=NULL;
  439.    word(lin,2,s);
  440.    if      (!strcmp(s,"down"))  a->event=EVENT_MOUSE_DOWN;
  441.    else if (!strcmp(s,"up"))    a->event=EVENT_MOUSE_UP;
  442.    else if (!strcmp(s,"enter")) a->event=EVENT_MOUSE_ENTER;
  443.    else if (!strcmp(s,"leave")) a->event=EVENT_MOUSE_LEAVE;
  444.    word(lin,3,s);
  445.    cnt=1;
  446.    while ((w=atchar(s,'+'))!=NULL)
  447.      {
  448.          *w=' ';cnt++;
  449.      }
  450.    for(i=0;i<cnt;i++)
  451.      {
  452.          word(s,i+1,ss);
  453.          if      (!strcmp(ss,"shift")) a->modifiers|=ShiftMask;
  454.          else if (!strcmp(ss,"lock"))  a->modifiers|=LockMask;
  455.          else if (!strcmp(ss,"ctrl"))  a->modifiers|=ControlMask;
  456.          else if (!strcmp(ss,"alt"))   a->modifiers|=Mod1Mask;
  457.          else if (!strcmp(ss,"meta1")) a->modifiers|=Mod1Mask;
  458.          else if (!strcmp(ss,"meta2")) a->modifiers|=Mod2Mask;
  459.          else if (!strcmp(ss,"meta3")) a->modifiers|=Mod3Mask;
  460.          else if (!strcmp(ss,"meta4")) a->modifiers|=Mod4Mask;
  461.          else if (!strcmp(ss,"meta5")) a->modifiers|=Mod5Mask;
  462.          else if (!strcmp(ss,"any"))   a->any=1;
  463.      }
  464.    word(lin,4,s);
  465.    if (!strcmp(s,"any")) a->button=0;
  466.    else a->button=atoi(s);
  467.    word(lin,5,s);
  468.    if      (!strcmp(s,"exec"))                  a->action.id=ACTION_EXEC;
  469.    else if (!strcmp(s,"alert"))                 a->action.id=ACTION_ALERT;
  470.    else if (!strcmp(s,"rotate_strip"))          a->action.id=ACTION_ROTATE_STRIP;
  471.    else if (!strcmp(s,"move_strip"))            a->action.id=ACTION_MOVE_STRIP;
  472.    else if (!strcmp(s,"save_strip"))            a->action.id=ACTION_SAVE_STRIP;
  473.    else if (!strcmp(s,"justify_strip"))         a->action.id=ACTION_JUSTIFY_STRIP;
  474.    else if (!strcmp(s,"delete_strip"))          a->action.id=ACTION_DELETE_STRIP;
  475.    else if (!strcmp(s,"show_strip"))            a->action.id=ACTION_SHOW_STRIP;
  476.    else if (!strcmp(s,"hide_strip"))            a->action.id=ACTION_HIDE_STRIP;
  477.    else if (!strcmp(s,"show_strip_toggle"))     a->action.id=ACTION_SHOW_STRIP_TOGGLE;
  478.    else if (!strcmp(s,"disable_button"))        a->action.id=ACTION_DISABLE_BUTTON;
  479.    else if (!strcmp(s,"enable_button"))         a->action.id=ACTION_ENABLE_BUTTON;
  480.    else if (!strcmp(s,"disable_button_toggle")) a->action.id=ACTION_DISABLE_BUTTON_TOGGLE;
  481.    else if (!strcmp(s,"move_button"))           a->action.id=ACTION_MOVE_BUTTON;
  482.    else if (!strcmp(s,"save_button"))           a->action.id=ACTION_SAVE_BUTTON;
  483.    else if (!strcmp(s,"show_button"))           a->action.id=ACTION_SHOW_BUTTON;
  484.    else if (!strcmp(s,"hide_button"))           a->action.id=ACTION_HIDE_BUTTON;
  485.    else if (!strcmp(s,"delete_button"))         a->action.id=ACTION_DELETE_BUTTON;
  486.    else if (!strcmp(s,"show_button_toggle"))    a->action.id=ACTION_SHOW_BUTTON_TOGGLE;
  487.    else if (!strcmp(s,"locate_button"))         a->action.id=ACTION_LOCATE_BUTTON;
  488.    else if (!strcmp(s,"flip_strip"))            a->action.id=ACTION_FLIP_STRIP;
  489.    a->action.params=duplicate(atword(lin,6));
  490. }
  491.  
  492. void CfgParseKeyAction(char *lin, ActionInit *a)
  493. {
  494.    char s[256],ss[256],*w;
  495.    int cnt,i;
  496.     
  497.    a->event=0;
  498.    a->any=0;
  499.    a->anykey=0;
  500.    a->modifiers=0;
  501.    a->button=0;
  502.    a->key=0;
  503.    a->action.id=0;
  504.    a->action.params=NULL;
  505.    word(lin,2,s);
  506.    if      (!strcmp(s,"down"))  a->event=EVENT_KEY_DOWN;
  507.    else if (!strcmp(s,"up"))    a->event=EVENT_KEY_UP;
  508.    word(lin,3,s);
  509.    cnt=1;
  510.    while ((w=atchar(s,'+'))!=NULL)
  511.      {
  512.          *w=' ';cnt++;
  513.      }
  514.    for(i=0;i<cnt;i++)
  515.      {
  516.          word(s,i+1,ss);
  517.          if      (!strcmp(ss,"shift")) a->modifiers|=ShiftMask;
  518.          else if (!strcmp(ss,"lock"))  a->modifiers|=LockMask;
  519.          else if (!strcmp(ss,"ctrl"))  a->modifiers|=ControlMask;
  520.          else if (!strcmp(ss,"alt"))   a->modifiers|=Mod1Mask;
  521.          else if (!strcmp(ss,"meta1")) a->modifiers|=Mod1Mask;
  522.          else if (!strcmp(ss,"meta2")) a->modifiers|=Mod2Mask;
  523.          else if (!strcmp(ss,"meta3")) a->modifiers|=Mod3Mask;
  524.          else if (!strcmp(ss,"meta4")) a->modifiers|=Mod4Mask;
  525.          else if (!strcmp(ss,"meta5")) a->modifiers|=Mod5Mask;
  526.          else if (!strcmp(ss,"any"))   a->any=1;
  527.      }
  528.    word(lin,4,s);
  529.    if (!strcmp(s,"any")) a->anykey=1;
  530.    else a->key=XKeysymToKeycode(disp,XStringToKeysym(s));
  531.    word(lin,5,s);
  532.    if      (!strcmp(s,"exec"))                  a->action.id=ACTION_EXEC;
  533.    else if (!strcmp(s,"alert"))                 a->action.id=ACTION_ALERT;
  534.    else if (!strcmp(s,"rotate_strip"))          a->action.id=ACTION_ROTATE_STRIP;
  535.    else if (!strcmp(s,"move_strip"))            a->action.id=ACTION_MOVE_STRIP;
  536.    else if (!strcmp(s,"save_strip"))            a->action.id=ACTION_SAVE_STRIP;
  537.    else if (!strcmp(s,"justify_strip"))         a->action.id=ACTION_JUSTIFY_STRIP;
  538.    else if (!strcmp(s,"delete_strip"))          a->action.id=ACTION_DELETE_STRIP;
  539.    else if (!strcmp(s,"show_strip"))            a->action.id=ACTION_SHOW_STRIP;
  540.    else if (!strcmp(s,"hide_strip"))            a->action.id=ACTION_HIDE_STRIP;
  541.    else if (!strcmp(s,"show_strip_toggle"))     a->action.id=ACTION_SHOW_STRIP_TOGGLE;
  542.    else if (!strcmp(s,"disable_button"))        a->action.id=ACTION_DISABLE_BUTTON;
  543.    else if (!strcmp(s,"enable_button"))         a->action.id=ACTION_ENABLE_BUTTON;
  544.    else if (!strcmp(s,"disable_button_toggle")) a->action.id=ACTION_DISABLE_BUTTON_TOGGLE;
  545.    else if (!strcmp(s,"move_button"))           a->action.id=ACTION_MOVE_BUTTON;
  546.    else if (!strcmp(s,"save_button"))           a->action.id=ACTION_SAVE_BUTTON;
  547.    else if (!strcmp(s,"show_button"))           a->action.id=ACTION_SHOW_BUTTON;
  548.    else if (!strcmp(s,"hide_button"))           a->action.id=ACTION_HIDE_BUTTON;
  549.    else if (!strcmp(s,"delete_button"))         a->action.id=ACTION_DELETE_BUTTON;
  550.    else if (!strcmp(s,"show_button_toggle"))    a->action.id=ACTION_SHOW_BUTTON_TOGGLE;
  551.    else if (!strcmp(s,"locate_button"))         a->action.id=ACTION_LOCATE_BUTTON;
  552.    else if (!strcmp(s,"flip_strip"))            a->action.id=ACTION_FLIP_STRIP;
  553.    a->action.params=duplicate(atword(lin,6));
  554. }
  555.  
  556. void AddButtonToStrip(Button *b, Strip *s, int loc)
  557. {
  558.    int i;
  559.    
  560.    if ((!b)||(!s)) return;
  561.    b->strip=s;
  562.    b->strip_loc=loc;
  563.    s->num++;
  564.    s->list=Erealloc(s->list,s->num*(sizeof(Item)));
  565.    if (loc==STRIP_LOCATION_END)
  566.      {
  567.     s->list[s->num-1].item=(void *)b;
  568.     s->list[s->num-1].type=LIST_TYPE_BUTTON;
  569.      }
  570.    else
  571.      {
  572.     for (i=s->num-1;i>0;i--)
  573.       {
  574.          s->list[i].type=s->list[i-1].type;
  575.          s->list[i].item=s->list[i-1].item;
  576.       }
  577.     s->list[0].item=(void *)b;
  578.     s->list[0].type=LIST_TYPE_BUTTON;
  579.      }
  580. }
  581.  
  582. void DelButtonFromStrip(Button *b, Strip *s)
  583. {
  584.    int i;
  585.    
  586.    for(i=0;i<s->num;i++)
  587.      {
  588.     if ((s->list[i].item==(void *)b)&&(s->list[i].type==LIST_TYPE_BUTTON))
  589.       {
  590.          for(i++;i<s->num;i++)
  591.            {
  592.           s->list[i-1].type=s->list[i].type;
  593.           s->list[i-1].item=s->list[i].item;
  594.            }
  595.       }
  596.      }
  597.    s->num--;
  598.    s->list=Erealloc(s->list,s->num*(sizeof(Item)));
  599.    b->strip=NULL;
  600. }
  601.  
  602. void AddStripToStrip(Strip *b, Strip *s, int loc)
  603. {
  604.    int i;
  605.    
  606.    if ((!b)||(!s)) return;
  607.    b->strip=s;
  608.    b->strip_loc=loc;
  609.    s->num++;
  610.    s->list=Erealloc(s->list,s->num*(sizeof(Item)));
  611.    if (loc==STRIP_LOCATION_END)
  612.      {
  613.     s->list[s->num-1].item=(void *)b;
  614.     s->list[s->num-1].type=LIST_TYPE_STRIP;
  615.      }
  616.    else
  617.      {
  618.     for (i=s->num-1;i>0;i--)
  619.       {
  620.          s->list[i].type=s->list[i-1].type;
  621.          s->list[i].item=s->list[i-1].item;
  622.       }
  623.     s->list[0].item=(void *)b;
  624.     s->list[0].type=LIST_TYPE_STRIP;
  625.      }
  626. }
  627.  
  628. void DelStripFromStrip(Strip *b, Strip *s)
  629. {
  630.    int i;
  631.    
  632.    for(i=0;i<s->num;i++)
  633.      {
  634.     if ((s->list[i].item==(void *)b)&&(s->list[i].type==LIST_TYPE_STRIP))
  635.       {
  636.          for(i++;i<s->num;i++)
  637.            {
  638.           s->list[i-1].type=s->list[i].type;
  639.           s->list[i-1].item=s->list[i].item;
  640.            }
  641.       }
  642.      }
  643.    s->num--;
  644.    s->list=Erealloc(s->list,s->num*(sizeof(Item)));
  645.    b->strip=NULL;
  646. }
  647.  
  648. void CalculateSize(Size *size, ScrBit *X, Constrain *width, Constrain *height)
  649. {
  650.    int w,h,nw,nh;
  651.    
  652.    w=DisplayWidth(disp,DefaultScreen(disp));
  653.    h=DisplayHeight(disp,DefaultScreen(disp));
  654.    if (size->x<=0) nw=X->width;
  655.    else
  656.      {
  657.          if (size->x_at) nw=size->x*w/size->x_at;
  658.          else nw=size->x;
  659.      }
  660.    if (size->y<=0) nh=X->height;
  661.    else
  662.      {
  663.          if (size->y_at) nh=size->y*h/size->y_at;
  664.          else nh=size->y;
  665.      }
  666.    if (width->max)
  667.      {
  668.          if (nw>width->max) nw=width->max;
  669.      }
  670.    if (width->min)
  671.      {
  672.          if (nw<width->min) nw=width->min;
  673.      }
  674.    if (height->max)
  675.      {
  676.          if (nh>height->max) nh=height->max;
  677.      }
  678.    if (height->min)
  679.      {
  680.          if (nh<height->min) nh=height->min;
  681.      }
  682.    X->width=nw;
  683.    X->height=nh;
  684. }
  685.  
  686. void CalculateLoc(Coord *loc, int width, int height, ScrBit *X)
  687. {
  688.    int w,h,nx,ny,fx,fy,hx,hy;
  689.    
  690.    w=DisplayWidth(disp,DefaultScreen(disp));
  691.    h=DisplayHeight(disp,DefaultScreen(disp));
  692.  
  693.    fx=0;fy=0;hx=0;hy=0;
  694.    if (loc->handle_macro==COORD_MACRO_CUSTOM)
  695.      {
  696.          if (loc->x_handle_at) hx=loc->x_handle*width/loc->x_handle_at;
  697.          else hx=loc->x_handle;
  698.          if (loc->y_handle_at) hy=loc->x_handle*height/loc->y_handle_at;
  699.          else hy=loc->y_handle;
  700.      }
  701.    else if (loc->handle_macro==COORD_MACRO_TOPLEFT)
  702.      {
  703.          hx=0;hy=0;
  704.      }
  705.    else if (loc->handle_macro==COORD_MACRO_TOPRIGHT)
  706.      {
  707.          hx=width-1;hy=0;
  708.      }
  709.    else if (loc->handle_macro==COORD_MACRO_BOTTOMLEFT)
  710.      {
  711.          hx=0;hy=height-1;
  712.      }
  713.    else if (loc->handle_macro==COORD_MACRO_BOTTOMRIGHT)
  714.      {
  715.          hx=width-1;hy=height-1;
  716.      }
  717.    else if (loc->handle_macro==COORD_MACRO_MIDDLE)
  718.      {
  719.          hx=width>>1;hy=height>>1;
  720.      }
  721.    if (loc->from_macro==COORD_MACRO_CUSTOM)
  722.      {
  723.          if (loc->x_from_at) fx=loc->x_from*w/loc->x_from_at;
  724.          else fx=loc->x_from;
  725.          if (loc->y_from_at) fy=loc->y_from*h/loc->y_from_at;
  726.          else fy=loc->x_from;
  727.      }
  728.    else if (loc->from_macro==COORD_MACRO_TOPLEFT)
  729.      {
  730.          fx=0;fy=0;
  731.      }
  732.    else if (loc->from_macro==COORD_MACRO_TOPRIGHT)
  733.      {
  734.          fx=w-1;fy=0;
  735.      }
  736.    else if (loc->from_macro==COORD_MACRO_BOTTOMLEFT)
  737.      {
  738.          fx=0;fy=h-1;
  739.      }
  740.    else if (loc->from_macro==COORD_MACRO_BOTTOMRIGHT)
  741.      {
  742.          fx=w-1;fy=h-1;
  743.      }
  744.    else if (loc->from_macro==COORD_MACRO_MIDDLE)
  745.      {
  746.          fx=w>>1;fy=h>>1;
  747.      }
  748.    nx=fx-hx+loc->x;
  749.    ny=fy-hy+loc->y;
  750.    X->x=nx;X->y=ny;
  751. }
  752.  
  753. void CalcButton(Button *b)
  754. {
  755.    CalculateSize(&b->size,&b->X,&b->width,&b->height);
  756.    CalculateLoc(&b->loc,b->X.width,b->X.height,&b->X);
  757. }
  758.  
  759. void DrawButton(Button *b)
  760. {
  761.    int draw,move;
  762.    Image *im;
  763.    ImageEntry *ie;
  764.    
  765.    if (!b) return;
  766.    draw=0;move=0;
  767.    if      (b->state==STATE_NORMAL)   ie=b->iclass->normal;
  768.    else if (b->state==STATE_HILITED)  ie=b->iclass->hilited;
  769.    else if (b->state==STATE_CLICKED)  ie=b->iclass->clicked;
  770.    else if (b->state==STATE_DISABLED) ie=b->iclass->disabled;
  771.    else ie=b->iclass->normal;
  772.    im=ie->im;
  773.    if (b->size.x<=0) 
  774.      {
  775.     if (im) b->X.width=im->rgb_width;
  776.     else b->X.width=ie->width;
  777.      }
  778.    if (b->size.y<=0) 
  779.      {
  780.     if (im) b->X.height=im->rgb_height;
  781.     else b->X.height=ie->height;
  782.      }
  783.    if (b->pstate!=b->state) draw=1;
  784.    if (b->pX.width!=b->X.width) draw=1;
  785.    if (b->pX.height!=b->X.height) draw=1;
  786.    if (b->pX.x!=b->X.x) move=1;
  787.    if (b->pX.y!=b->X.y) move=1;
  788.    if (move) 
  789.      {
  790.     XMoveWindow(disp,b->X.win,b->X.x,b->X.y);
  791.      }
  792.    if (draw)
  793.      {
  794.     if (b->X.pmap) ImlibFreePixmap(imd,b->X.pmap);
  795.     if (b->X.mask) ImlibFreePixmap(imd,b->X.mask);
  796.     GetPixmaps(b->iclass,b->state,b->X.width,b->X.height,&b->X.pmap,&b->X.mask);
  797.     XResizeWindow(disp,b->X.win,b->X.width,b->X.height);
  798.     if (b->X.pmap)
  799.       XSetWindowBackgroundPixmap(disp,b->X.win,b->X.pmap);
  800.     if (b->X.mask) 
  801.       XShapeCombineMask(disp,b->X.win,ShapeBounding,0,0,b->X.mask,ShapeSet);
  802.     XClearWindow(disp,b->X.win);
  803.      }
  804.    if (move||draw) XSync(disp,False);
  805.    b->pstate=b->state;
  806.    b->pX.x=b->X.x;
  807.    b->pX.y=b->X.y;
  808.    b->pX.width=b->X.width;
  809.    b->pX.height=b->X.height;
  810. }
  811.  
  812. void ShowButton(Button *b)
  813. {
  814.    XMapWindow(disp,b->X.win);
  815.    XSync(disp,False);
  816. }
  817.  
  818. void HideButton(Button *b)
  819. {
  820.    XUnmapWindow(disp,b->X.win);
  821.    XSync(disp,False);
  822. }
  823.  
  824. void MoveButtonTo(Button *b, int x, int y)
  825. {
  826.    if (!b) return;
  827.    b->loc.x=x;
  828.    b->loc.y=y;
  829.    CalcButton(b);
  830.    DrawButton(b);
  831. }
  832.  
  833. void MoveButtonBy(Button *b, int x, int y)
  834. {
  835.    if (!b) return;
  836.    
  837.    b->loc.x+=x;
  838.    b->loc.y+=y;
  839.    CalcButton(b);
  840.    DrawButton(b);
  841. }
  842.  
  843. void ButtonHilite(Button *b, char onoff)
  844. {
  845.    if (!b) return;
  846.    if (b->state==STATE_DISABLED) return;
  847.    if (onoff)
  848.      {
  849.     if (b->state!=STATE_CLICKED)
  850.       b->state=STATE_HILITED;
  851.      }
  852.    else
  853.      {
  854.     if (b->state!=STATE_CLICKED)
  855.       b->state=STATE_NORMAL;
  856.      }
  857.    DrawButton(b);
  858. }
  859.  
  860. void ButtonClick(Button *b, char onoff)
  861. {
  862.    if (!b) return;
  863.    if (b->state==STATE_DISABLED) return;
  864.    if (onoff)
  865.     b->state=STATE_CLICKED;
  866.    else
  867.      {
  868.     if (b->state==STATE_NORMAL)
  869.       b->state=STATE_NORMAL;
  870.     else
  871.       b->state=STATE_HILITED;
  872.      }
  873.    DrawButton(b);
  874. }
  875.  
  876. void ButtonDisable(Button *b, char onoff)
  877. {
  878.    if (!b) return;
  879.    
  880.    if (onoff)
  881.      b->state=STATE_DISABLED;
  882.    else
  883.      b->state=STATE_NORMAL;
  884.    DrawButton(b);
  885. }
  886.  
  887. void SetButtonImageClass(Button *b, char *name)
  888. {
  889.    ImageClass *ic;
  890.    
  891.    if (!b) return;
  892.    if (!name) return;
  893.    ic=(ImageClass *)FindItem(name,LIST_TYPE_IMAGECLASS);
  894.    if (!ic) return;
  895.    b->iclass=ic;
  896.    CalcButton(b);
  897.    DrawButton(b);
  898. }
  899.  
  900. void SetButtonLocation(Button *b, Coord *loc)
  901. {
  902.    if ((!b)||(!loc)) return;
  903.    b->loc.handle_macro=loc->handle_macro;
  904.    b->loc.x_handle=loc->x_handle;
  905.    b->loc.y_handle=loc->y_handle;
  906.    b->loc.x_handle_at=loc->x_handle_at;
  907.    b->loc.y_handle_at=loc->y_handle_at;
  908.    b->loc.from_macro=loc->from_macro;
  909.    b->loc.x_from=loc->x_from;
  910.    b->loc.y_from=loc->y_from;
  911.    b->loc.x_from_at=loc->x_from_at;
  912.    b->loc.y_from_at=loc->y_from_at;
  913.    b->loc.x=loc->x;
  914.    b->loc.y=loc->y;
  915.    CalcButton(b);
  916.    DrawButton(b);
  917. }
  918.  
  919. void SetButtonSize(Button *b, Size *siz)
  920. {
  921.    if ((!b)||(!siz)) return;
  922.    b->size.x=siz->x;
  923.    b->size.x_at=siz->x_at;
  924.    b->size.y=siz->y;
  925.    b->size.y_at=siz->y_at;
  926.    CalcButton(b);
  927.    DrawButton(b);
  928. }
  929.  
  930. void SetButtonContraints(Button *b, Constrain *w, Constrain *h)
  931. {
  932.    if ((!b)||(!w)||(!h)) return;
  933.    b->width.min=w->min;
  934.    b->width.max=w->max;
  935.    b->height.min=h->min;
  936.    b->height.max=h->max;
  937.    CalcButton(b);
  938.    DrawButton(b);
  939. }
  940.  
  941. void DrawStrip(Strip *s)
  942. {
  943.    int i,x,y,w,h;
  944.    ScrBit *sb;
  945.    
  946.    if (!s->num) return;
  947.    sb=NULL;
  948.    for(i=0;i<s->num;i++)
  949.      {
  950.          if (s->list[i].type==LIST_TYPE_BUTTON)
  951.           {
  952.               CalculateSize(&((Button *)(s->list[i].item))->size,
  953.                                  &((Button *)(s->list[i].item))->X,
  954.                                  &((Button *)(s->list[i].item))->width,
  955.                                  &((Button *)(s->list[i].item))->height);
  956.           }
  957.          else if (s->list[i].type==LIST_TYPE_STRIP)
  958.           {
  959.               DrawStrip((Strip *)(s->list[i].item));
  960.           }
  961.      }
  962.    if (s->orientation==STRIP_ORIENTATION_VERTICAL)
  963.      { 
  964.          h=0;
  965.          if (s->list[0].type==LIST_TYPE_BUTTON) 
  966.             sb=&((Button *)(s->list[0].item))->X;
  967.          else if (s->list[0].type==LIST_TYPE_STRIP) 
  968.             sb=&((Strip *)(s->list[0].item))->X;
  969.          w=sb->width;
  970.          for(i=0;i<s->num;i++)
  971.           {
  972.               if (s->list[i].type==LIST_TYPE_BUTTON) 
  973.                  sb=&((Button *)(s->list[i].item))->X;
  974.               else if (s->list[i].type==LIST_TYPE_STRIP) 
  975.                  sb=&((Strip *)(s->list[i].item))->X;
  976.               h+=sb->height;
  977.               if (sb->width>w) w=sb->width;
  978.           }
  979.          s->X.width=w;s->X.height=h;
  980.          x=0;y=0;
  981.          if (!s->strip)
  982.           {
  983.               CalculateLoc(&s->loc,w,h,&s->X);
  984.               y=s->X.y;x=s->X.x;
  985.           }
  986.          else
  987.           {
  988.               y=s->X.y;
  989.               x=s->X.x;
  990.           }
  991.          for(i=0;i<s->num;i++)
  992.           {
  993.               if (s->list[i].type==LIST_TYPE_BUTTON) 
  994.                  sb=&((Button *)(s->list[i].item))->X;
  995.               else if (s->list[i].type==LIST_TYPE_STRIP) 
  996.                  sb=&((Strip *)(s->list[i].item))->X;
  997.               sb->x=x+(((w-sb->width)*s->justification)/100);
  998.               sb->y=y;y+=sb->height;
  999.           }
  1000.     }
  1001.    else
  1002.      {
  1003.          w=0;
  1004.          if (s->list[0].type==LIST_TYPE_BUTTON) 
  1005.             sb=&((Button *)(s->list[0].item))->X;
  1006.          else if (s->list[0].type==LIST_TYPE_STRIP) 
  1007.             sb=&((Strip *)(s->list[0].item))->X;
  1008.          h=sb->height;
  1009.          for(i=0;i<s->num;i++)
  1010.           {
  1011.               if (s->list[i].type==LIST_TYPE_BUTTON) 
  1012.                  sb=&((Button *)(s->list[i].item))->X;
  1013.               else if (s->list[i].type==LIST_TYPE_STRIP) 
  1014.                  sb=&((Strip *)(s->list[i].item))->X;
  1015.               w+=sb->width;
  1016.               if (sb->height>h) h=sb->height;
  1017.           }
  1018.          s->X.width=w;s->X.height=h;
  1019.          x=0;y=0;
  1020.          if (!s->strip)
  1021.           {
  1022.               CalculateLoc(&s->loc,w,h,&s->X);
  1023.               y=s->X.y;x=s->X.x;
  1024.           }
  1025.          else
  1026.           {
  1027.               y=s->X.y;
  1028.               x=s->X.x;
  1029.           }
  1030.          for(i=0;i<s->num;i++)
  1031.           {
  1032.               if (s->list[i].type==LIST_TYPE_BUTTON) 
  1033.                  sb=&((Button *)(s->list[i].item))->X;
  1034.               else if (s->list[i].type==LIST_TYPE_STRIP) 
  1035.                  sb=&((Strip *)(s->list[i].item))->X;
  1036.               sb->y=y+(((h-sb->height)*s->justification)/100);
  1037.               sb->x=x;x+=sb->width;
  1038.           }
  1039.      }
  1040.    for(i=0;i<s->num;i++) 
  1041.      {
  1042.          if (s->list[i].type==LIST_TYPE_BUTTON)
  1043.             DrawButton((Button *)s->list[i].item);
  1044.          else if (s->list[i].type==LIST_TYPE_STRIP)
  1045.             DrawStrip((Strip *)s->list[i].item);
  1046.      }
  1047. }
  1048.  
  1049. void HideStrip(Strip *s)
  1050. {
  1051.    int i;
  1052.    
  1053.    for(i=0;i<s->num;i++) 
  1054.      {
  1055.     if (s->list[i].type==LIST_TYPE_BUTTON)
  1056.       HideButton((Button *)s->list[i].item);
  1057.     else if (s->list[i].type==LIST_TYPE_STRIP)
  1058.       HideStrip((Strip *)s->list[i].item);
  1059.      }
  1060.    s->visible=0;
  1061. }
  1062.  
  1063. void ShowStrip(Strip *s)
  1064. {
  1065.    int i;
  1066.    
  1067.    for(i=0;i<s->num;i++) 
  1068.      {
  1069.     if (s->list[i].type==LIST_TYPE_BUTTON)
  1070.       ShowButton((Button *)s->list[i].item);
  1071.     else if (s->list[i].type==LIST_TYPE_STRIP)
  1072.       ShowStrip((Strip *)s->list[i].item);
  1073.      }
  1074.    s->visible=1;
  1075. }
  1076.  
  1077. void RotateStrip(Strip *s)
  1078. {
  1079.    int i;
  1080.    if (!s) return;
  1081.    
  1082.    if (s->orientation==STRIP_ORIENTATION_VERTICAL)
  1083.      s->orientation=STRIP_ORIENTATION_HORIZONTAL;
  1084.    else
  1085.      s->orientation=STRIP_ORIENTATION_VERTICAL;
  1086.    for(i=0;i<s->num;i++) 
  1087.      {
  1088.     if (s->list[i].type==LIST_TYPE_STRIP)
  1089.       {
  1090.          RotateStrip((Strip *)s->list[i].item);
  1091.       }
  1092.      }
  1093.    if (s->strip) DrawStrip(s->strip);
  1094.    else DrawStrip(s);
  1095. }
  1096.  
  1097. void FlipStrip(Strip *s)
  1098. {
  1099.    int i;
  1100.    Item it;
  1101.    
  1102.    if (!s) return;
  1103.    if (s->num<2) return;
  1104.    for(i=0;i<s->num>>1;i++)
  1105.      {
  1106.     it.type=s->list[i].type;
  1107.     it.item=s->list[i].item;
  1108.     s->list[i].type=s->list[s->num-i-1].type;
  1109.     s->list[i].item=s->list[s->num-i-1].item;
  1110.     s->list[s->num-i-1].type=it.type;
  1111.     s->list[s->num-i-1].item=it.item;
  1112.      }
  1113.    DrawStrip(s);
  1114. }
  1115.  
  1116. void SetStripJustification(Strip *s, int just)
  1117. {
  1118.    if (!s) return;
  1119.    s->justification=just;
  1120.    DrawStrip(s);
  1121. }
  1122.  
  1123. void MoveStripTo(Strip *s, int x, int y)
  1124. {
  1125.    if (!s) return;
  1126.    if (s->strip)
  1127.      {
  1128.     MoveStripTo(s->strip,x,y);
  1129.      }
  1130.    else
  1131.      {
  1132.     s->loc.x=x;
  1133.     s->loc.y=y;
  1134.     DrawStrip(s);
  1135.      }
  1136. }
  1137.  
  1138. void MoveStripBy(Strip *s, int x, int y)
  1139. {
  1140.    if (!s) return;
  1141.    if (s->strip)
  1142.      {
  1143.     MoveStripBy(s->strip,x,y);
  1144.      }
  1145.    else
  1146.      {
  1147.     s->loc.x+=x;
  1148.     s->loc.y+=y;
  1149.     DrawStrip(s);
  1150.      }
  1151. }
  1152.  
  1153. void SetStripLocation(Strip *s, Coord *loc)
  1154. {
  1155.    if ((!s)||(!loc)) return;
  1156.    s->loc.handle_macro=loc->handle_macro;
  1157.    s->loc.x_handle=loc->x_handle;
  1158.    s->loc.y_handle=loc->y_handle;
  1159.    s->loc.x_handle_at=loc->x_handle_at;
  1160.    s->loc.y_handle_at=loc->y_handle_at;
  1161.    s->loc.from_macro=loc->from_macro;
  1162.    s->loc.x_from=loc->x_from;
  1163.    s->loc.y_from=loc->y_from;
  1164.    s->loc.x_from_at=loc->x_from_at;
  1165.    s->loc.y_from_at=loc->y_from_at;
  1166.    s->loc.x=loc->x;
  1167.    s->loc.y=loc->y;
  1168.    DrawStrip(s);
  1169. }
  1170.  
  1171. void CfgParseLocLine(char *lin, Coord *loc)
  1172. {
  1173.    char s[256],*ww;
  1174.    int wd;
  1175.    
  1176.    wd=1;
  1177.    word(lin,wd++,s);
  1178.    if (strcmp(s,"location")) return;
  1179.    word(lin,wd++,s);
  1180.    if (strcmp(s,"handle")) return;
  1181.    word(lin,wd++,s);
  1182.    if (!strcmp(s,"topleft"))          loc->handle_macro=COORD_MACRO_TOPLEFT;
  1183.    else if (!strcmp(s,"topright"))    loc->handle_macro=COORD_MACRO_TOPRIGHT;
  1184.    else if (!strcmp(s,"bottomleft"))  loc->handle_macro=COORD_MACRO_BOTTOMLEFT;
  1185.    else if (!strcmp(s,"bottomright")) loc->handle_macro=COORD_MACRO_BOTTOMRIGHT;
  1186.    else if (!strcmp(s,"middle"))      loc->handle_macro=COORD_MACRO_MIDDLE;
  1187.    else
  1188.      {
  1189.     loc->handle_macro=COORD_MACRO_CUSTOM;
  1190.     ww=atchar(s,'@');
  1191.     if (ww) 
  1192.       {
  1193.          *ww=' ';
  1194.          sscanf(s,"%i",&loc->x_handle);
  1195.          sscanf(s,"%*i %i",&loc->x_handle_at);
  1196.       }
  1197.     else
  1198.       sscanf(s,"%i",&loc->x_handle);
  1199.     word(lin,wd++,s);
  1200.     ww=atchar(s,'@');
  1201.     if (ww) 
  1202.       {
  1203.          *ww=' ';
  1204.          sscanf(s,"%i",&loc->y_handle);
  1205.          sscanf(s,"%*i %i",&loc->y_handle_at);
  1206.       }
  1207.     else
  1208.       sscanf(s,"%i",&loc->y_handle);
  1209.      }
  1210.    word(lin,wd++,s);
  1211.    if (strcmp(s,"from")) return;
  1212.    word(lin,wd++,s);
  1213.    if (!strcmp(s,"topleft"))          loc->from_macro=COORD_MACRO_TOPLEFT;
  1214.    else if (!strcmp(s,"topright"))    loc->from_macro=COORD_MACRO_TOPRIGHT;
  1215.    else if (!strcmp(s,"bottomleft"))  loc->from_macro=COORD_MACRO_BOTTOMLEFT;
  1216.    else if (!strcmp(s,"bottomright")) loc->from_macro=COORD_MACRO_BOTTOMRIGHT;
  1217.    else if (!strcmp(s,"middle"))      loc->from_macro=COORD_MACRO_MIDDLE;
  1218.    else
  1219.      {
  1220.     loc->from_macro=COORD_MACRO_CUSTOM;
  1221.     ww=atchar(s,'@');
  1222.     if (ww) 
  1223.       {
  1224.          *ww=' ';
  1225.          sscanf(s,"%i",&loc->x_from);
  1226.          sscanf(s,"%*i %i",&loc->x_from_at);
  1227.       }
  1228.     else
  1229.       sscanf(s,"%i",&loc->x_from);
  1230.     word(lin,wd++,s);
  1231.     ww=atchar(s,'@');
  1232.     if (ww) 
  1233.       {
  1234.          *ww=' ';
  1235.          sscanf(s,"%i",&loc->y_from);
  1236.          sscanf(s,"%*i %i",&loc->y_from_at);
  1237.       }
  1238.     else
  1239.       sscanf(s,"%i",&loc->y_from);
  1240.      }
  1241.    word(lin,wd++,s);
  1242.    if (strcmp(s,"at")) return;
  1243.    word(lin,wd++,s);loc->x=atoi(s);
  1244.    word(lin,wd++,s);loc->y=atoi(s);
  1245. }
  1246.  
  1247. void CfgParseSizeLine(char *lin, Size *size)
  1248. {
  1249.    char s[256],*w,*ww;
  1250.    int wd;
  1251.    
  1252.    wd=1;
  1253.    s[0]=0;w=atword(lin,wd++);sscanf(w,"%s",s);
  1254.    if (strcmp(s,"size")) return;
  1255.      {
  1256.          s[0]=0;w=atword(lin,wd++);sscanf(w,"%s",s);
  1257.          ww=atchar(s,'@');
  1258.          if (ww) 
  1259.           {
  1260.               *ww=' ';
  1261.               sscanf(s,"%i",&size->x);
  1262.               sscanf(s,"%*i %i",&size->x_at);
  1263.           }
  1264.          else
  1265.             sscanf(s,"%i",&size->x);
  1266.          s[0]=0;w=atword(lin,wd++);sscanf(w,"%s",s);
  1267.          ww=atchar(s,'@');
  1268.          if (ww) 
  1269.           {
  1270.               *ww=' ';
  1271.               sscanf(s,"%i",&size->y);
  1272.               sscanf(s,"%*i %i",&size->y_at);
  1273.           }
  1274.          else
  1275.             sscanf(s,"%i",&size->y);
  1276.      }
  1277. }
  1278.  
  1279. void CfgParseConstrain(char *lin, Constrain *c)
  1280. {
  1281.    sscanf(lin,"%*s %*s %*s %i %*s %i",&c->min,&c->max);
  1282. }
  1283.