Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/tbarcfg/src/tbarcfg.c

    rf87ff8e re63e74a  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    108108        sif_node_t *nentry;
    109109        const char *ntype;
     110        const char *separator;
    110111        const char *caption;
    111112        const char *cmd;
     113        const char *terminal = NULL;
    112114        errno_t rc;
    113115
     
    142144                }
    143145
    144                 caption = sif_node_get_attr(nentry, "caption");
    145                 if (caption == NULL) {
     146                separator = sif_node_get_attr(nentry, "separator");
     147                if (separator != NULL && str_cmp(separator, "y") != 0) {
    146148                        rc = EIO;
    147149                        goto error;
    148150                }
    149151
    150                 cmd = sif_node_get_attr(nentry, "cmd");
    151                 if (cmd == NULL) {
    152                         rc = EIO;
    153                         goto error;
     152                if (separator == NULL) {
     153                        caption = sif_node_get_attr(nentry, "caption");
     154                        if (caption == NULL) {
     155                                rc = EIO;
     156                                goto error;
     157                        }
     158
     159                        cmd = sif_node_get_attr(nentry, "cmd");
     160                        if (cmd == NULL) {
     161                                rc = EIO;
     162                                goto error;
     163                        }
     164
     165                        terminal = sif_node_get_attr(nentry, "terminal");
     166                        if (terminal == NULL)
     167                                terminal = "n";
     168
     169                        rc = smenu_entry_new(tbcfg, nentry, caption, cmd,
     170                            str_cmp(terminal, "y") == 0, NULL);
     171                        if (rc != EOK)
     172                                goto error;
     173                } else {
     174                        rc = smenu_entry_sep_new(tbcfg, nentry, NULL);
     175                        if (rc != EOK)
     176                                goto error;
    154177                }
    155 
    156                 rc = smenu_entry_new(tbcfg, nentry, caption, cmd);
    157                 if (rc != EOK)
    158                         goto error;
    159178
    160179                nentry = sif_node_next_child(nentry);
     
    221240}
    222241
     242/** Get last start menu entry.
     243 *
     244 * @param tbcfg Taskbar configuration
     245 * @return Previous entry or @c NULL if the menu is empty
     246 */
     247smenu_entry_t *tbarcfg_smenu_last(tbarcfg_t *tbcfg)
     248{
     249        link_t *link;
     250
     251        link = list_last(&tbcfg->entries);
     252        if (link == NULL)
     253                return NULL;
     254
     255        return list_get_instance(link, smenu_entry_t, lentries);
     256}
     257
     258/** Get previous start menu entry.
     259 *
     260 * @param cur Current entry
     261 * @return Previous entry or @c NULL if @a cur is the last entry
     262 */
     263smenu_entry_t *tbarcfg_smenu_prev(smenu_entry_t *cur)
     264{
     265        link_t *link;
     266
     267        link = list_prev(&cur->lentries, &cur->smenu->entries);
     268        if (link == NULL)
     269                return NULL;
     270
     271        return list_get_instance(link, smenu_entry_t, lentries);
     272}
     273
    223274/** Get start menu entry caption.
    224275 *
     
    228279const char *smenu_entry_get_caption(smenu_entry_t *entry)
    229280{
     281        assert(!entry->separator);
    230282        return entry->caption;
    231283}
     
    233285/** Get start menu entry command.
    234286 *
    235  * @param entr Start menu entry
     287 * @param entry Start menu entry
    236288 * @return Command to run
    237289 */
    238290const char *smenu_entry_get_cmd(smenu_entry_t *entry)
    239291{
     292        assert(!entry->separator);
    240293        return entry->cmd;
     294}
     295
     296/** Get start menu entry start in terminal flag.
     297 *
     298 * @param entry Start menu entry
     299 * @return Start in terminal flag
     300 */
     301bool smenu_entry_get_terminal(smenu_entry_t *entry)
     302{
     303        assert(!entry->separator);
     304        return entry->terminal;
     305}
     306
     307/** Get start menu entry separator flag.
     308 *
     309 * @param entry Start menu entry
     310 * @return Separator flag
     311 */
     312bool smenu_entry_get_separator(smenu_entry_t *entry)
     313{
     314        return entry->separator;
    241315}
    242316
     
    253327{
    254328        char *dcap;
     329
     330        assert(!entry->separator);
    255331
    256332        dcap = str_dup(caption);
     
    276352        char *dcmd;
    277353
     354        assert(!entry->separator);
     355
    278356        dcmd = str_dup(cmd);
    279357        if (dcmd == NULL)
     
    285363}
    286364
     365/** Set start menu entry start in terminal flag.
     366 *
     367 * Note: To make the change visible to others and persistent,
     368 * you must call @c smenu_entry_save()
     369 *
     370 * @param entry Start menu entry
     371 * @param terminal Start in terminal flag
     372 */
     373void smenu_entry_set_terminal(smenu_entry_t *entry, bool terminal)
     374{
     375        assert(!entry->separator);
     376        entry->terminal = terminal;
     377}
     378
     379/** Save start menu entry using transaction.
     380 *
     381 * @param entry Start menu entry
     382 * @param trans Transaction
     383 */
     384static errno_t smenu_entry_save_trans(smenu_entry_t *entry, sif_trans_t *trans)
     385{
     386        errno_t rc;
     387
     388        if (entry->separator) {
     389                rc = sif_node_set_attr(trans, entry->nentry, "separator", "y");
     390                if (rc != EOK)
     391                        goto error;
     392        } else {
     393                sif_node_unset_attr(trans, entry->nentry, "separator");
     394
     395                rc = sif_node_set_attr(trans, entry->nentry, "cmd", entry->cmd);
     396                if (rc != EOK)
     397                        goto error;
     398
     399                rc = sif_node_set_attr(trans, entry->nentry, "caption",
     400                    entry->caption);
     401                if (rc != EOK)
     402                        goto error;
     403
     404                rc = sif_node_set_attr(trans, entry->nentry, "terminal",
     405                    entry->terminal ? "y" : "n");
     406                if (rc != EOK)
     407                        goto error;
     408        }
     409
     410        return EOK;
     411error:
     412        return rc;
     413}
     414
    287415/** Save any changes to start menu entry.
    288416 *
     
    298426                goto error;
    299427
    300         rc = sif_node_set_attr(trans, entry->nentry, "cmd", entry->cmd);
    301         if (rc != EOK)
    302                 goto error;
    303 
    304         rc = sif_node_set_attr(trans, entry->nentry, "caption", entry->caption);
     428        rc = smenu_entry_save_trans(entry, trans);
    305429        if (rc != EOK)
    306430                goto error;
     
    325449 * @param caption Caption
    326450 * @param cmd Command to run
     451 * @param terminal Start in terminal
     452 * @param rentry Place to store pointer to new entry or @c NULL
    327453 */
    328454errno_t smenu_entry_new(tbarcfg_t *smenu, sif_node_t *nentry,
    329     const char *caption, const char *cmd)
     455    const char *caption, const char *cmd, bool terminal, smenu_entry_t **rentry)
    330456{
    331457        smenu_entry_t *entry;
     
    352478        }
    353479
     480        entry->terminal = terminal;
     481
    354482        entry->smenu = smenu;
    355483        list_append(&entry->lentries, &smenu->entries);
     484        if (rentry != NULL)
     485                *rentry = entry;
    356486        return EOK;
    357487error:
     
    367497}
    368498
     499/** Allocate a start menu separator entry and append it to the start menu
     500 * (internal).
     501 *
     502 * This only creates the entry in memory, but does not update the repository.
     503 *
     504 * @param smenu Start menu
     505 * @param nentry Backing SIF node
     506 * @param rentry Place to store pointer to new entry or @c NULL
     507 */
     508errno_t smenu_entry_sep_new(tbarcfg_t *smenu, sif_node_t *nentry,
     509    smenu_entry_t **rentry)
     510{
     511        smenu_entry_t *entry;
     512        errno_t rc;
     513
     514        entry = calloc(1, sizeof(smenu_entry_t));
     515        if (entry == NULL) {
     516                rc = ENOMEM;
     517                goto error;
     518        }
     519
     520        entry->nentry = nentry;
     521        entry->separator = true;
     522
     523        entry->smenu = smenu;
     524        list_append(&entry->lentries, &smenu->entries);
     525        if (rentry != NULL)
     526                *rentry = entry;
     527
     528        return EOK;
     529error:
     530        return rc;
     531}
     532
    369533/** Delete start menu entry.
    370534 *
     
    377541{
    378542        list_remove(&entry->lentries);
    379         free(entry->caption);
    380         free(entry->cmd);
     543        if (entry->caption != NULL)
     544                free(entry->caption);
     545        if (entry->cmd != NULL)
     546                free(entry->cmd);
    381547        free(entry);
    382548}
     
    388554 * @param caption Caption
    389555 * @param cmd Command to run
     556 * @param terminal Start in terminal
     557 * @param rentry Place to store pointer to new entry or @c NULL
    390558 */
    391559errno_t smenu_entry_create(tbarcfg_t *smenu, const char *caption,
    392     const char *cmd)
     560    const char *cmd, bool terminal, smenu_entry_t **rentry)
    393561{
    394562        sif_node_t *nentry;
     563        smenu_entry_t *entry;
    395564        errno_t rc;
    396565        sif_trans_t *trans = NULL;
     
    413582                goto error;
    414583
    415         rc = smenu_entry_new(smenu, nentry, caption, cmd);
     584        rc = sif_node_set_attr(trans, nentry, "terminal", terminal ? "y" : "n");
     585        if (rc != EOK)
     586                goto error;
     587
     588        rc = smenu_entry_new(smenu, nentry, caption, cmd, terminal, &entry);
    416589        if (rc != EOK)
    417590                goto error;
     
    421594                goto error;
    422595
     596        if (rentry != NULL)
     597                *rentry = entry;
    423598        return EOK;
    424599error:
     
    428603}
    429604
    430 /** Destroy start menu entry..
    431  *
    432  * @param entry Start menu entry
    433  * @return EOK on success or an error code
    434  */
    435 errno_t smenu_entry_destroy(smenu_entry_t *entry)
    436 {
     605/** Create new start menu separator entry.
     606 *
     607 * @param smenu Start menu
     608 * @param nentry Backing SIF node
     609 * @param rentry Place to store pointer to new entry or @c NULL
     610 */
     611errno_t smenu_entry_sep_create(tbarcfg_t *smenu, smenu_entry_t **rentry)
     612{
     613        sif_node_t *nentry;
     614        smenu_entry_t *entry;
    437615        errno_t rc;
    438616        sif_trans_t *trans = NULL;
    439617
    440         rc = sif_trans_begin(entry->smenu->repo, &trans);
    441         if (rc != EOK)
    442                 goto error;
    443 
    444         sif_node_destroy(trans, entry->nentry);
     618        rc = sif_trans_begin(smenu->repo, &trans);
     619        if (rc != EOK)
     620                goto error;
     621
     622        rc = sif_node_append_child(trans, smenu->nentries, "entry",
     623            &nentry);
     624        if (rc != EOK)
     625                goto error;
     626
     627        rc = sif_node_set_attr(trans, nentry, "separator", "y");
     628        if (rc != EOK)
     629                goto error;
     630
     631        rc = smenu_entry_sep_new(smenu, nentry, &entry);
     632        if (rc != EOK)
     633                goto error;
    445634
    446635        rc = sif_trans_end(trans);
     
    448637                goto error;
    449638
    450         smenu_entry_delete(entry);
     639        if (rentry != NULL)
     640                *rentry = entry;
    451641        return EOK;
    452642error:
     
    456646}
    457647
     648/** Destroy start menu entry.
     649 *
     650 * @param entry Start menu entry
     651 * @return EOK on success or an error code
     652 */
     653errno_t smenu_entry_destroy(smenu_entry_t *entry)
     654{
     655        errno_t rc;
     656        sif_trans_t *trans = NULL;
     657
     658        rc = sif_trans_begin(entry->smenu->repo, &trans);
     659        if (rc != EOK)
     660                goto error;
     661
     662        sif_node_destroy(trans, entry->nentry);
     663
     664        rc = sif_trans_end(trans);
     665        if (rc != EOK)
     666                goto error;
     667
     668        smenu_entry_delete(entry);
     669        return EOK;
     670error:
     671        if (trans != NULL)
     672                sif_trans_abort(trans);
     673        return rc;
     674}
     675
     676/** Move start menu entry up.
     677 *
     678 * @param entry Start menu entry
     679 * @return EOK on success or an error code
     680 */
     681errno_t smenu_entry_move_up(smenu_entry_t *entry)
     682{
     683        errno_t rc;
     684        sif_trans_t *trans = NULL;
     685        sif_node_t *nnode = NULL;
     686        sif_node_t *old_node;
     687        smenu_entry_t *prev;
     688
     689        rc = sif_trans_begin(entry->smenu->repo, &trans);
     690        if (rc != EOK)
     691                goto error;
     692
     693        prev = tbarcfg_smenu_prev(entry);
     694        if (prev == NULL) {
     695                /* Entry is already at first position, nothing to do. */
     696                return EOK;
     697        }
     698
     699        rc = sif_node_insert_before(trans, prev->nentry, "entry", &nnode);
     700        if (rc != EOK)
     701                goto error;
     702
     703        old_node = entry->nentry;
     704        entry->nentry = nnode;
     705
     706        rc = smenu_entry_save_trans(entry, trans);
     707        if (rc != EOK) {
     708                entry->nentry = old_node;
     709                goto error;
     710        }
     711
     712        sif_node_destroy(trans, old_node);
     713
     714        rc = sif_trans_end(trans);
     715        if (rc != EOK) {
     716                entry->nentry = old_node;
     717                goto error;
     718        }
     719
     720        list_remove(&entry->lentries);
     721        list_insert_before(&entry->lentries, &prev->lentries);
     722        return EOK;
     723error:
     724        if (nnode != NULL)
     725                sif_node_destroy(trans, nnode);
     726        if (trans != NULL)
     727                sif_trans_abort(trans);
     728        return rc;
     729}
     730
     731/** Move start menu entry down.
     732 *
     733 * @param entry Start menu entry
     734 * @return EOK on success or an error code
     735 */
     736errno_t smenu_entry_move_down(smenu_entry_t *entry)
     737{
     738        errno_t rc;
     739        sif_trans_t *trans = NULL;
     740        sif_node_t *nnode = NULL;
     741        sif_node_t *old_node;
     742        smenu_entry_t *next;
     743
     744        rc = sif_trans_begin(entry->smenu->repo, &trans);
     745        if (rc != EOK)
     746                goto error;
     747
     748        next = tbarcfg_smenu_next(entry);
     749        if (next == NULL) {
     750                /* Entry is already at last position, nothing to do. */
     751                return EOK;
     752        }
     753
     754        rc = sif_node_insert_after(trans, next->nentry, "entry", &nnode);
     755        if (rc != EOK)
     756                goto error;
     757
     758        old_node = entry->nentry;
     759        entry->nentry = nnode;
     760
     761        rc = smenu_entry_save_trans(entry, trans);
     762        if (rc != EOK) {
     763                entry->nentry = old_node;
     764                goto error;
     765        }
     766
     767        sif_node_destroy(trans, old_node);
     768
     769        rc = sif_trans_end(trans);
     770        if (rc != EOK) {
     771                entry->nentry = old_node;
     772                goto error;
     773        }
     774
     775        list_remove(&entry->lentries);
     776        list_insert_after(&entry->lentries, &next->lentries);
     777        return EOK;
     778error:
     779        if (nnode != NULL)
     780                sif_node_destroy(trans, nnode);
     781        if (trans != NULL)
     782                sif_trans_abort(trans);
     783        return rc;
     784}
     785
    458786/** @}
    459787 */
Note: See TracChangeset for help on using the changeset viewer.