System message queue
The screen and user interaction is managed by the main thread. Other parts of calcurse (threads) wishing to use the screen or communicate with the user, must do it via the main thread. For this purpose the main input loop is extended with a message queue. A thread may insert a message in the queue. The main thread tests for messages before listening for user commands. If a message is present, it is displayed (in a popup window) for the user to acknowledge. Depending on the message other actions may be performed, e.g. the message could be turned into a "system appointment/event" and inserted among the usual appointments. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
2339d78cbd
commit
2112b1ca2e
@ -29,6 +29,7 @@ calcurse_SOURCES = \
|
|||||||
note.c \
|
note.c \
|
||||||
notify.c \
|
notify.c \
|
||||||
pcal.c \
|
pcal.c \
|
||||||
|
queue.c \
|
||||||
recur.c \
|
recur.c \
|
||||||
sha1.c \
|
sha1.c \
|
||||||
sigs.c \
|
sigs.c \
|
||||||
|
@ -619,6 +619,9 @@ int main(int argc, char **argv)
|
|||||||
io_set_lock();
|
io_set_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* System message queue. */
|
||||||
|
que_init();
|
||||||
|
|
||||||
/* Begin of interactive mode with ncurses interface. */
|
/* Begin of interactive mode with ncurses interface. */
|
||||||
sigs_init(); /* signal handling init */
|
sigs_init(); /* signal handling init */
|
||||||
initscr(); /* start the curses mode */
|
initscr(); /* start the curses mode */
|
||||||
@ -702,6 +705,14 @@ int main(int argc, char **argv)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
int key;
|
int key;
|
||||||
|
|
||||||
|
while (que_ued()) {
|
||||||
|
que_show();
|
||||||
|
que_save();
|
||||||
|
do_storage(0);
|
||||||
|
wins_update(FLAG_ALL);
|
||||||
|
que_rem();
|
||||||
|
}
|
||||||
|
|
||||||
if (resize) {
|
if (resize) {
|
||||||
resize = 0;
|
resize = 0;
|
||||||
wins_reset();
|
wins_reset();
|
||||||
@ -712,7 +723,10 @@ int main(int argc, char **argv)
|
|||||||
key_generic_reload();
|
key_generic_reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check input loop once every minute. */
|
||||||
|
wtimeout(win[KEY].p, 60000);
|
||||||
key = keys_get(win[KEY].p, &count, ®);
|
key = keys_get(win[KEY].p, &count, ®);
|
||||||
|
wtimeout(win[KEY].p, -1);
|
||||||
switch (key) {
|
switch (key) {
|
||||||
HANDLE_KEY(KEY_GENERIC_CHANGE_VIEW, key_generic_change_view);
|
HANDLE_KEY(KEY_GENERIC_CHANGE_VIEW, key_generic_change_view);
|
||||||
HANDLE_KEY(KEY_GENERIC_OTHER_CMD, key_generic_other_cmd);
|
HANDLE_KEY(KEY_GENERIC_OTHER_CMD, key_generic_other_cmd);
|
||||||
|
@ -1287,4 +1287,11 @@ void wins_erase_status_bar(void);
|
|||||||
void wins_other_status_page();
|
void wins_other_status_page();
|
||||||
void wins_reset_status_page(void);
|
void wins_reset_status_page(void);
|
||||||
|
|
||||||
|
/* queue.c */
|
||||||
|
void que_init(void);
|
||||||
|
int que_ued(void);
|
||||||
|
struct event *que_ins(char *, time_t, int);
|
||||||
|
void que_rem(void);
|
||||||
|
void que_show(void);
|
||||||
|
void que_save(void);
|
||||||
#endif /* CALCURSE_H */
|
#endif /* CALCURSE_H */
|
||||||
|
90
src/queue.c
Normal file
90
src/queue.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "calcurse.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A queue for calcurse system messages.
|
||||||
|
*/
|
||||||
|
llist_t sysqueue;
|
||||||
|
|
||||||
|
void que_init(void)
|
||||||
|
{
|
||||||
|
LLIST_INIT(&sysqueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test for queued system events.
|
||||||
|
*/
|
||||||
|
int que_ued(void)
|
||||||
|
{
|
||||||
|
return sysqueue.head ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a system event at the tail of the queue.
|
||||||
|
*/
|
||||||
|
struct event *que_ins(char *mesg, time_t time, int id)
|
||||||
|
{
|
||||||
|
struct event *ev;
|
||||||
|
|
||||||
|
ev = mem_malloc(sizeof(struct event));
|
||||||
|
ev->mesg = mem_strdup(mesg);
|
||||||
|
ev->day = time;
|
||||||
|
ev->id = id;
|
||||||
|
ev->note = NULL;
|
||||||
|
LLIST_ADD(&sysqueue, ev);
|
||||||
|
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the system event at the head of the queue.
|
||||||
|
*/
|
||||||
|
struct event *que_get(void)
|
||||||
|
{
|
||||||
|
return sysqueue.head ? sysqueue.head->data : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the system event at the head of the queue.
|
||||||
|
*/
|
||||||
|
void que_rem(void)
|
||||||
|
{
|
||||||
|
struct event *ev;
|
||||||
|
|
||||||
|
if (!sysqueue.head)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
ev = sysqueue.head->data;
|
||||||
|
mem_free(ev->mesg);
|
||||||
|
mem_free(ev);
|
||||||
|
LLIST_REMOVE(&sysqueue, sysqueue.head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display the system event at the head of the queue in a popup window.
|
||||||
|
*/
|
||||||
|
void que_show(void)
|
||||||
|
{
|
||||||
|
struct event *ev;
|
||||||
|
char *date;
|
||||||
|
|
||||||
|
if (!que_ued())
|
||||||
|
return;
|
||||||
|
ev = que_get();
|
||||||
|
date = date_sec2date_str(ev->day, "%F %T");
|
||||||
|
item_in_popup(date, "", ev->mesg, _("System event"));
|
||||||
|
mem_free(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the system event at the head of the queue as an appointment.
|
||||||
|
*/
|
||||||
|
void que_save(void)
|
||||||
|
{
|
||||||
|
struct event *ev;
|
||||||
|
|
||||||
|
if (!que_ued())
|
||||||
|
return;
|
||||||
|
ev = que_get();
|
||||||
|
apoint_new(ev->mesg, NULL, ev->day, 0, APOINT_NULL);
|
||||||
|
io_set_modified();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user