home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 500-599 / ff589.lza / Term / TermSrc.lha / MacroPanel.c < prev    next >
C/C++ Source or Header  |  1991-11-03  |  14KB  |  489 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
  4.  *
  5.  *    Name .....: MacroPanel.c
  6.  *    Created ..: Monday 21-Jan-91 20:12
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    21-Jan-91       Olsen           Created this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15. #include "TermGlobal.h"
  16.  
  17. enum    {    GAD_F1,GAD_F2,GAD_F3,GAD_F4,GAD_F5,GAD_F6,GAD_F7,GAD_F8,GAD_F9,
  18.         GAD_F10,GAD_QUALIFIER,GAD_USE,GAD_LOAD,GAD_SAVE,GAD_CANCEL };
  19.  
  20. enum    {    MEN_USEMACROS=1,MEN_LOADMACROS,MEN_SAVEMACROS,MEN_QUALIFIER,
  21.         MEN_CANCELMACROS,MEN_QUITPANEL };
  22.  
  23. STATIC struct NewMenu MacroMenu[] =
  24. {
  25.     { NM_TITLE, "Project",         0 , 0, 0, (APTR)0},
  26.     {  NM_ITEM, "Load Macros",    "L", 0, 0, (APTR)MEN_LOADMACROS},
  27.     {  NM_ITEM, "Save Macros",    "S", 0, 0, (APTR)MEN_SAVEMACROS},
  28.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  29.     {  NM_ITEM, "Modifier",        "M", 0, 0, (APTR)MEN_QUALIFIER},
  30.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  31.     {  NM_ITEM, "Use",        "U", 0, 0, (APTR)MEN_USEMACROS},
  32.     {  NM_ITEM, "Cancel",        "C", 0, 0, (APTR)MEN_CANCELMACROS},
  33.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  34.     {  NM_ITEM, "Quit",        "Q", 0, 0, (APTR)MEN_QUITPANEL},
  35.     { NM_END, 0,             0 , 0, 0, (APTR)0}
  36. };
  37.  
  38. #define WIDTH    535
  39. #define HEIGHT    173
  40.  
  41. STATIC STRPTR ModifierString[5] =
  42. {
  43.     (STRPTR)"None",
  44.     (STRPTR)"Shift",
  45.     (STRPTR)"Alternate",
  46.     (STRPTR)"Control",
  47.     NULL
  48. };
  49.  
  50. STATIC struct Gadget *
  51. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  52. {
  53.     struct Gadget        *Gadget;
  54.     struct NewGadget     NewGadget;
  55.     UWORD             Counter = 0,Offset;
  56.  
  57.     memset(&NewGadget,0,sizeof(struct NewGadget));
  58.  
  59.     if(Gadget = CreateContext(GadgetList))
  60.     {
  61.         NewGadget . ng_Width        = 484;
  62.         NewGadget . ng_Height        = 12;
  63.         NewGadget . ng_GadgetText    = "F 1";
  64.         NewGadget . ng_TextAttr        = &DefaultFont;
  65.         NewGadget . ng_VisualInfo    = VisualInfo;
  66.         NewGadget . ng_GadgetID        = Counter;
  67.         NewGadget . ng_LeftEdge        = (strlen(NewGadget . ng_GadgetText) + 2) * 8 + 1;
  68.         NewGadget . ng_TopEdge        = 1 + TopEdge;
  69.  
  70.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  71.             GTST_MaxChars,    256,
  72.             GTST_EditHook,    &CommandHook,
  73.         TAG_DONE);
  74.  
  75.         NewGadget . ng_GadgetText    = "F 2";
  76.         NewGadget . ng_GadgetID        = Counter;
  77.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  78.  
  79.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  80.             GTST_MaxChars,    256,
  81.             GTST_EditHook,    &CommandHook,
  82.         TAG_DONE);
  83.  
  84.         NewGadget . ng_GadgetText    = "F 3";
  85.         NewGadget . ng_GadgetID        = Counter;
  86.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  87.  
  88.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  89.             GTST_MaxChars,    256,
  90.             GTST_EditHook,    &CommandHook,
  91.         TAG_DONE);
  92.  
  93.         NewGadget . ng_GadgetText    = "F 4";
  94.         NewGadget . ng_GadgetID        = Counter;
  95.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  96.  
  97.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  98.             GTST_MaxChars,    256,
  99.             GTST_EditHook,    &CommandHook,
  100.         TAG_DONE);
  101.  
  102.         NewGadget . ng_GadgetText    = "F 5";
  103.         NewGadget . ng_GadgetID        = Counter;
  104.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  105.  
  106.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  107.             GTST_MaxChars,    256,
  108.             GTST_EditHook,    &CommandHook,
  109.         TAG_DONE);
  110.  
  111.         NewGadget . ng_GadgetText    = "F 6";
  112.         NewGadget . ng_GadgetID        = Counter;
  113.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  114.  
  115.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  116.             GTST_MaxChars,    256,
  117.             GTST_EditHook,    &CommandHook,
  118.         TAG_DONE);
  119.  
  120.         NewGadget . ng_GadgetText    = "F 7";
  121.         NewGadget . ng_GadgetID        = Counter;
  122.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  123.  
  124.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  125.             GTST_MaxChars,    256,
  126.             GTST_EditHook,    &CommandHook,
  127.         TAG_DONE);
  128.  
  129.         NewGadget . ng_GadgetText    = "F 8";
  130.         NewGadget . ng_GadgetID        = Counter;
  131.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  132.  
  133.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  134.             GTST_MaxChars,    256,
  135.             GTST_EditHook,    &CommandHook,
  136.         TAG_DONE);
  137.  
  138.         NewGadget . ng_GadgetText    = "F 9";
  139.         NewGadget . ng_GadgetID        = Counter;
  140.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  141.  
  142.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  143.             GTST_MaxChars,    256,
  144.             GTST_EditHook,    &CommandHook,
  145.         TAG_DONE);
  146.  
  147.         NewGadget . ng_GadgetText    = "F10";
  148.         NewGadget . ng_GadgetID        = Counter;
  149.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  150.  
  151.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  152.             GTST_MaxChars,    256,
  153.             GTST_EditHook,    &CommandHook,
  154.         TAG_DONE);
  155.  
  156.         NewGadget . ng_GadgetText    = "Key _Modifier";
  157.         NewGadget . ng_Width        = 100;
  158.         NewGadget . ng_GadgetID        = Counter;
  159.         NewGadget . ng_LeftEdge        = (WIDTH - NewGadget . ng_Width) >> 1;
  160.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  161.  
  162.         GadgetArray[Counter++] = Gadget = CreateGadget(CYCLE_KIND,Gadget,&NewGadget,
  163.             GT_Underscore,    '_',
  164.             GTCY_Labels,    ModifierString,
  165.             GTCY_Active,    0,
  166.         TAG_DONE);
  167.  
  168.         NewGadget . ng_Width        = 52;
  169.         NewGadget . ng_Height        = 12;
  170.         NewGadget . ng_GadgetText    = "_Use";
  171.         NewGadget . ng_GadgetID        = Counter;
  172.         NewGadget . ng_Flags        = 0;
  173.         NewGadget . ng_LeftEdge        = 10;
  174.         NewGadget . ng_TopEdge        = HEIGHT - 3 - NewGadget . ng_Height;
  175.  
  176.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  177.             GT_Underscore,    '_',
  178.         TAG_DONE);
  179.  
  180.         Offset = (WIDTH + NewGadget . ng_Width) / 4 + 8;
  181.  
  182.         NewGadget . ng_GadgetText    = "_Load";
  183.         NewGadget . ng_GadgetID        = Counter;
  184.         NewGadget . ng_LeftEdge        = NewGadget . ng_LeftEdge + Offset;
  185.  
  186.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  187.             GT_Underscore,    '_',
  188.         TAG_DONE);
  189.  
  190.         NewGadget . ng_GadgetText    = "_Save";
  191.         NewGadget . ng_GadgetID        = Counter;
  192.         NewGadget . ng_LeftEdge        = NewGadget . ng_LeftEdge + Offset;
  193.  
  194.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  195.             GT_Underscore,    '_',
  196.         TAG_DONE);
  197.  
  198.         NewGadget . ng_GadgetText    = "_Cancel";
  199.         NewGadget . ng_GadgetID        = Counter;
  200.         NewGadget . ng_LeftEdge        = NewGadget . ng_LeftEdge + Offset;
  201.  
  202.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  203.             GT_Underscore,    '_',
  204.         TAG_DONE);
  205.     }
  206.  
  207.     return(Gadget);
  208. }
  209.  
  210. VOID
  211. MacroPanel(struct MacroKeys *MacroKeys)
  212. {
  213.     struct Window        *PanelWindow;
  214.     struct Menu        *PanelMenu;
  215.     struct Gadget        *GadgetList = NULL;
  216.     struct Gadget        *GadgetArray[GAD_CANCEL + 1];
  217.     LONG             i;
  218.  
  219.     struct MacroKeys    *Keys;
  220.  
  221.     if(Keys = (struct MacroKeys *)AllocVec(sizeof(struct MacroKeys),MEMF_PUBLIC|MEMF_CLEAR))
  222.     {
  223.         CopyMem(MacroKeys,Keys,sizeof(struct MacroKeys));
  224.  
  225.         if(CreateAllGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
  226.         {
  227.             if(PanelMenu = CreateMenus(MacroMenu,
  228.                 GTMN_FrontPen, 0,
  229.             TAG_DONE))
  230.             {
  231.                 if(LayoutMenus(PanelMenu,VisualInfo,
  232.                     GTMN_TextAttr,&DefaultFont,
  233.                 TAG_DONE))
  234.                 {
  235.                     if(PanelWindow = OpenWindowTags(NULL,
  236.                         WA_Left,    (Screen -> Width - WIDTH) >> 1,
  237.                         WA_Top,        (Screen -> Height - HEIGHT) >> 1,
  238.                         WA_Width,    WIDTH,
  239.                         WA_Height,    HEIGHT,
  240.  
  241.                         WA_Activate,    TRUE,
  242.                         WA_DragBar,    TRUE,
  243.                         WA_DepthGadget,    TRUE,
  244.                         WA_CloseGadget,    TRUE,
  245.                         WA_RMBTrap,    TRUE,
  246.                         WA_DepthGadget,    TRUE,
  247.                         WA_CustomScreen,Screen,
  248.  
  249.                         WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_CLOSEWINDOW | SLIDERIDCMP | CHECKBOXIDCMP | LISTVIEWIDCMP | IDCMP_MENUPICK | IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW,
  250.  
  251.                         WA_Title,    "Macro Preferences",
  252.                     TAG_DONE))
  253.                     {
  254.                         struct IntuiMessage    *Massage;
  255.                         ULONG             Class,Code;
  256.                         struct Gadget        *Gadget;
  257.                         BYTE             Terminated = FALSE;
  258.  
  259.                         UBYTE             DummyBuffer[256],*DummyChar;
  260.  
  261.                         struct FileRequest    *FileRequest;
  262.  
  263.                         LONG             Modifier = 0,Value;
  264.  
  265.                         PushWindow(PanelWindow);
  266.  
  267.                         AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  268.                         RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  269.                         GT_RefreshWindow(PanelWindow,NULL);
  270.  
  271.                         SetMenuStrip(PanelWindow,PanelMenu);
  272.  
  273.                         PanelWindow -> Flags &= ~WFLG_RMBTRAP;
  274.  
  275.                         for(i = 0 ; i < 10 ; i++)
  276.                         {
  277.                             GT_SetGadgetAttrs(GadgetArray[GAD_F1 + i],PanelWindow,NULL,
  278.                                 GTST_String,Keys -> Keys[Modifier][i],
  279.                             TAG_DONE);
  280.                         }
  281.  
  282.                         ActivateGadget(GadgetArray[GAD_F1],PanelWindow,NULL);
  283.  
  284.                         ActiveGadget = GadgetArray[GAD_F1];
  285.  
  286.                         while(!Terminated)
  287.                         {
  288.                             WaitPort(PanelWindow -> UserPort);
  289.  
  290.                             while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  291.                             {
  292.                                 Class    = Massage -> Class;
  293.                                 Code    = Massage -> Code;
  294.                                 Gadget    = (struct Gadget *)Massage -> IAddress;
  295.  
  296.                                 GT_ReplyIMsg(Massage);
  297.  
  298.                                 if(Class == IDCMP_ACTIVEWINDOW && ActiveGadget)
  299.                                     ActivateGadget(ActiveGadget,PanelWindow,NULL);
  300.  
  301.                                 if(Class == IDCMP_RAWKEY)
  302.                                 {
  303.                                     if(Code == IECODE_UP_PREFIX|103 && CommandWindow == PanelWindow)
  304.                                         ActivateGadget(CommandGadget,PanelWindow,NULL);
  305.                                 }
  306.  
  307.                                 if(Class == IDCMP_GADGETDOWN)
  308.                                 {
  309.                                     if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  310.                                         ActiveGadget = Gadget;
  311.                                 }
  312.  
  313.                                 if(Class == IDCMP_MENUPICK)
  314.                                 {
  315.                                     struct MenuItem *MenuItem;
  316.  
  317.                                     while(Code != MENUNULL)
  318.                                     {
  319.                                         MenuItem = ItemAddress(PanelMenu,Code);
  320.  
  321.                                         switch((ULONG)MENU_USERDATA(MenuItem))
  322.                                         {
  323.                                             case MEN_QUITPANEL:    Class = IDCMP_CLOSEWINDOW;
  324.                                                         break;
  325.  
  326.                                             case MEN_USEMACROS:    Class = IDCMP_GADGETUP;
  327.                                                         Gadget = GadgetArray[GAD_USE];
  328.                                                         break;
  329.  
  330.                                             case MEN_LOADMACROS:    Class = IDCMP_GADGETUP;
  331.                                                         Gadget = GadgetArray[GAD_LOAD];
  332.                                                         break;
  333.  
  334.                                             case MEN_SAVEMACROS:    Class = IDCMP_GADGETUP;
  335.                                                         Gadget = GadgetArray[GAD_SAVE];
  336.                                                         break;
  337.  
  338.                                             case MEN_QUALIFIER:    if(Modifier == 3)
  339.                                                             Value = 0;
  340.                                                         else
  341.                                                             Value = Modifier + 1;
  342.  
  343.                                                         GT_SetGadgetAttrs(GadgetArray[GAD_QUALIFIER],PanelWindow,NULL,
  344.                                                             GTCY_Active,Value,
  345.                                                         TAG_DONE);
  346.  
  347.                                                         Class = IDCMP_GADGETUP;
  348.                                                         Gadget = GadgetArray[GAD_QUALIFIER];
  349.                                                         Code = Value;
  350.  
  351.                                                         goto GadCheck;
  352.  
  353.                                             case MEN_CANCELMACROS:    Class = IDCMP_GADGETUP;
  354.                                                         Gadget = GadgetArray[GAD_CANCEL];
  355.                                                         break;
  356.  
  357.                                             default:        break;
  358.                                         }
  359.  
  360.                                         Code = MenuItem -> NextSelect;
  361.                                     }
  362.  
  363.                                     if(ActiveGadget)
  364.                                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  365.                                 }
  366.  
  367.                                 if(Class == IDCMP_CLOSEWINDOW)
  368.                                     Terminated = TRUE;
  369.  
  370. GadCheck:                            if(Class == IDCMP_GADGETUP)
  371.                                 {
  372.                                     switch(Gadget -> GadgetID)
  373.                                     {
  374.                                         case GAD_QUALIFIER:    for(i = 0 ; i < 10 ; i++)
  375.                                                         strcpy(Keys -> Keys[Modifier][i],((struct StringInfo *)GadgetArray[i] -> SpecialInfo) -> Buffer);
  376.  
  377.                                                     Modifier = Code;
  378.  
  379.                                                     for(i = 0 ; i < 10 ; i++)
  380.                                                     {
  381.                                                         GT_SetGadgetAttrs(GadgetArray[GAD_F1 + i],PanelWindow,NULL,
  382.                                                             GTST_String,Keys -> Keys[Modifier][i],
  383.                                                         TAG_DONE);
  384.                                                     }
  385.  
  386.                                                     break;
  387.  
  388.                                         case GAD_USE:        Terminated = TRUE;
  389.  
  390.                                                     for(i = 0 ; i < 10 ; i++)
  391.                                                         strcpy(Keys -> Keys[Modifier][i],((struct StringInfo *)GadgetArray[i] -> SpecialInfo) -> Buffer);
  392.  
  393.                                                     CopyMem(Keys,MacroKeys,sizeof(struct MacroKeys));
  394.  
  395.                                                     break;
  396.  
  397.                                         case GAD_LOAD:        strcpy(DummyBuffer,LastMacros);
  398.  
  399.                                                     DummyChar = PathPart(DummyBuffer);
  400.  
  401.                                                     *DummyChar = 0;
  402.  
  403.                                                     SetWait(PanelWindow);
  404.  
  405.                                                     PanelWindow -> Flags |= WFLG_RMBTRAP;
  406.  
  407.                                                     if(FileRequest = GetFile("Load Macro Keys",DummyBuffer,FilePart(LastMacros),DummyBuffer,"#?.term",FALSE,FALSE,FALSE,"Load"))
  408.                                                     {
  409.                                                         if(!LoadMacros(DummyBuffer,Keys))
  410.                                                             MyEasyRequest(Window,"Couldn't load macro keys\n\"%s\"!","Continue",DummyBuffer);
  411.                                                         else
  412.                                                         {
  413.                                                             strcpy(Config . MacroFile,DummyBuffer);
  414.  
  415.                                                             strcpy(LastMacros,DummyBuffer);
  416.  
  417.                                                             for(i = 0 ; i < 10 ; i++)
  418.                                                             {
  419.                                                                 GT_SetGadgetAttrs(GadgetArray[GAD_F1 + i],PanelWindow,NULL,
  420.                                                                     GTST_String,Keys -> Keys[Modifier][i],
  421.                                                                 TAG_DONE);
  422.                                                             }
  423.                                                         }
  424.                                                     }
  425.  
  426.                                                     ClearPointer(PanelWindow);
  427.                                                     PanelWindow -> Flags &= ~WFLG_RMBTRAP;
  428.  
  429.                                                     break;
  430.  
  431.                                         case GAD_SAVE:        strcpy(DummyBuffer,LastMacros);
  432.  
  433.                                                     DummyChar = PathPart(DummyBuffer);
  434.  
  435.                                                     *DummyChar = 0;
  436.  
  437.                                                     SetWait(PanelWindow);
  438.                                                     PanelWindow -> Flags |= WFLG_RMBTRAP;
  439.  
  440.                                                     for(i = 0 ; i < 10 ; i++)
  441.                                                         strcpy(Keys -> Keys[Modifier][i],((struct StringInfo *)GadgetArray[i] -> SpecialInfo) -> Buffer);
  442.  
  443.                                                     if(FileRequest = GetFile("Save Macro Keys",DummyBuffer,FilePart(LastMacros),DummyBuffer,"#?.term",TRUE,FALSE,FALSE,"Save"))
  444.                                                     {
  445.                                                         if(!WriteIFFData(DummyBuffer,Keys,sizeof(struct MacroKeys),'KEYS'))
  446.                                                             MyEasyRequest(Window,"Couldn't save macro keys\n\"%s\"!","Continue",DummyBuffer);
  447.                                                         else
  448.                                                             strcpy(LastMacros,DummyBuffer);
  449.                                                     }
  450.  
  451.                                                     ClearPointer(PanelWindow);
  452.                                                     PanelWindow -> Flags &= ~WFLG_RMBTRAP;
  453.  
  454.                                                     break;
  455.  
  456.                                         case GAD_CANCEL:    Terminated = TRUE;
  457.  
  458.                                                     CopyMem(Keys,MacroKeys,sizeof(struct MacroKeys));
  459.  
  460.                                                     break;
  461.  
  462.                                         default:        break;
  463.                                     }
  464.                                 }
  465.                             }
  466.                         }
  467.  
  468.                         PanelWindow -> Flags |= WFLG_RMBTRAP;
  469.  
  470.                         ClearMenuStrip(PanelWindow);
  471.  
  472.                         RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  473.  
  474.                         PopWindow();
  475.  
  476.                         CloseWindow(PanelWindow);
  477.                     }
  478.                 }
  479.  
  480.                 FreeMenus(PanelMenu);
  481.             }
  482.         }
  483.  
  484.         FreeGadgets(GadgetList);
  485.  
  486.         FreeVec(Keys);
  487.     }
  488. }
  489.