* move marchlist into its own file
[citadel.git] / webcit / marchlist.c
1 #include "webcit.h"
2 #include "webserver.h"
3 #include "roomops.h"
4
5 /*
6  * Free a session's march list
7  */
8 void free_march_list(wcsession *wcf)
9 {
10         struct march *mptr;
11
12         while (wcf->march != NULL) {
13                 mptr = wcf->march->next;
14                 free(wcf->march);
15                 wcf->march = mptr;
16         }
17
18 }
19
20
21
22 /*
23  * remove a room from the march list
24  */
25 void remove_march(const StrBuf *aaa)
26 {
27         struct march *mptr, *mptr2;
28
29         if (WC->march == NULL)
30                 return;
31
32         if (!strcasecmp(WC->march->march_name, ChrPtr(aaa))) {
33                 mptr = WC->march->next;
34                 free(WC->march);
35                 WC->march = mptr;
36                 return;
37         }
38         mptr2 = WC->march;
39         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
40                 if (!strcasecmp(mptr->march_name, ChrPtr(aaa))) {
41                         mptr2->next = mptr->next;
42                         free(mptr);
43                         mptr = mptr2;
44                 } else {
45                         mptr2 = mptr;
46                 }
47         }
48 }
49
50
51
52 /**
53  * \brief Locate the room on the march list which we most want to go to.  
54  * Each room
55  * is measured given a "weight" of preference based on various factors.
56  * \param desired_floor the room number on the citadel server
57  * \return the roomname
58  */
59 char *pop_march(int desired_floor)
60 {
61         static char TheRoom[128];
62         int TheFloor = 0;
63         int TheOrder = 32767;
64         int TheWeight = 0;
65         int weight;
66         struct march *mptr = NULL;
67
68         strcpy(TheRoom, "_BASEROOM_");
69         if (WC->march == NULL)
70                 return (TheRoom);
71
72         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
73                 weight = 0;
74                 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
75                         weight = weight + 10000;
76                 if (mptr->march_floor == desired_floor)
77                         weight = weight + 5000;
78
79                 weight = weight + ((128 - (mptr->march_floor)) * 128);
80                 weight = weight + (128 - (mptr->march_order));
81
82                 if (weight > TheWeight) {
83                         TheWeight = weight;
84                         strcpy(TheRoom, mptr->march_name);
85                         TheFloor = mptr->march_floor;
86                         TheOrder = mptr->march_order;
87                 }
88         }
89         return (TheRoom);
90 }
91
92
93
94 /*
95  * Goto next room having unread messages.
96  *
97  * We want to skip over rooms that the user has already been to, and take the
98  * user back to the lobby when done.  The room we end up in is placed in
99  * newroom - which is set to 0 (the lobby) initially.
100  * We start the search in the current room rather than the beginning to prevent
101  * two or more concurrent users from dragging each other back to the same room.
102  */
103 void gotonext(void)
104 {
105         char buf[256];
106         struct march *mptr = NULL;
107         struct march *mptr2 = NULL;
108         char room_name[128];
109         StrBuf *next_room;
110         int ELoop = 0;
111
112         /*
113          * First check to see if the march-mode list is already allocated.
114          * If it is, pop the first room off the list and go there.
115          */
116         if (havebstr("startmsg")) {
117                  readloop(readnew);
118                  return;
119         }
120
121         if (WC->march == NULL) {
122                 serv_puts("LKRN");
123                 serv_getln(buf, sizeof buf);
124                 if (buf[0] == '1')
125                         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
126                                 if (IsEmptyStr(buf)) {
127                                         if (ELoop > 10000)
128                                                 return;
129                                         if (ELoop % 100 == 0)
130                                                 sleeeeeeeeeep(1);
131                                         ELoop ++;
132                                         continue;                                       
133                                 }
134                                 extract_token(room_name, buf, 0, '|', sizeof room_name);
135                                 if (strcasecmp(room_name, ChrPtr(WC->wc_roomname))) {
136                                         mptr = (struct march *) malloc(sizeof(struct march));
137                                         mptr->next = NULL;
138                                         safestrncpy(mptr->march_name, room_name, sizeof mptr->march_name);
139                                         mptr->march_floor = extract_int(buf, 2);
140                                         mptr->march_order = extract_int(buf, 3);
141                                         if (WC->march == NULL) 
142                                                 WC->march = mptr;
143                                         else 
144                                                 mptr2->next = mptr;
145                                         mptr2 = mptr;
146                                 }
147                                 buf[0] = '\0';
148                         }
149                 /*
150                  * add _BASEROOM_ to the end of the march list, so the user will end up
151                  * in the system base room (usually the Lobby>) at the end of the loop
152                  */
153                 mptr = (struct march *) malloc(sizeof(struct march));
154                 mptr->next = NULL;
155                 mptr->march_order = 0;
156                 mptr->march_floor = 0;
157                 strcpy(mptr->march_name, "_BASEROOM_");
158                 if (WC->march == NULL) {
159                         WC->march = mptr;
160                 } else {
161                         mptr2 = WC->march;
162                         while (mptr2->next != NULL)
163                                 mptr2 = mptr2->next;
164                         mptr2->next = mptr;
165                 }
166                 /*
167                  * ...and remove the room we're currently in, so a <G>oto doesn't make us
168                  * walk around in circles
169                  */
170                 remove_march(WC->wc_roomname);
171         }
172         if (WC->march != NULL) {
173                 next_room = NewStrBufPlain(pop_march(-1), -1);/*TODO: migrate march to strbuf */
174         } else {
175                 next_room = NewStrBufPlain(HKEY("_BASEROOM_"));
176         }
177
178
179         smart_goto(next_room);
180         FreeStrBuf(&next_room);
181 }
182
183 /*
184  * un-goto the previous room
185  */
186 void ungoto(void)
187 {
188         StrBuf *Buf;
189
190         if (havebstr("startmsg")) {
191                 readloop(readnew);
192                 return;
193         }
194
195         if (!strcmp(WC->ugname, "")) {
196                 smart_goto(WC->wc_roomname);
197                 return;
198         }
199         serv_printf("GOTO %s", WC->ugname);
200         Buf = NewStrBuf();
201         StrBuf_ServGetln(Buf);
202         if (GetServerStatus(Buf, NULL) != 2) {
203                 smart_goto(WC->wc_roomname);
204                 FreeStrBuf(&Buf);
205                 return;
206         }
207         if (WC->uglsn >= 0L) {
208                 serv_printf("SLRP %ld", WC->uglsn);
209                 StrBuf_ServGetln(Buf);
210         }
211         FlushStrBuf(Buf);
212         StrBufAppendBufPlain(Buf, WC->ugname, -1, 0);
213         strcpy(WC->ugname, "");
214         smart_goto(Buf);
215         FreeStrBuf(&Buf);
216 }
217
218
219
220 void _gotonext(void) {
221         slrp_highest();
222         gotonext();
223 }
224
225
226 void dotskip(void) {
227         smart_goto(sbstr("room"));
228 }
229
230
231
232
233 void 
234 InitModule_MARCHLIST
235 (void)
236 {
237
238         WebcitAddUrlHandler(HKEY("gotonext"), _gotonext, NEED_URL);
239         WebcitAddUrlHandler(HKEY("skip"), gotonext, NEED_URL);
240         WebcitAddUrlHandler(HKEY("ungoto"), ungoto, NEED_URL);
241 }