1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/chat.c,v 1.8 2011/05/16 16:21:56 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_CHAT_C_
22 
23 #include "tgifdefs.h"
24 #include "patchlvl.h"
25 #include "tidget.h"
26 
27 #include "button.e"
28 #include "chat.e"
29 #include "cmd.e"
30 #include "color.e"
31 #include "choose.e"
32 #include "dialog.e"
33 #include "file.e"
34 #include "font.e"
35 #include "http.e"
36 #include "ini.e"
37 #include "inmethod.e"
38 #include "msg.e"
39 #include "menu.e"
40 #include "rect.e"
41 #include "setup.e"
42 #include "strtbl.e"
43 #include "tdgtbtn.e"
44 #include "tdgtsedt.e"
45 #include "tdgtlist.e"
46 #include "tidget.e"
47 #include "util.e"
48 #include "xpixmap.e"
49 
50 #include "xbm/a1.xbm"
51 #include "xbm/bold1.xbm"
52 #include "xbm/italic1.xbm"
53 
54 #define CHAT_BTN_AUTO   0
55 #define CHAT_BTN_BOLD   1
56 #define CHAT_BTN_ITALIC 2
57 #define CHAT_BTN_SEND   3
58 #define CHAT_BTN_COLOR  4
59 
60 #define MAX_CHAT_BTNS 5
61 
62 #define ID_CHAT_BTN_AUTO   (100+CHAT_BTN_AUTO)
63 #define ID_CHAT_BTN_BOLD   (100+CHAT_BTN_BOLD)
64 #define ID_CHAT_BTN_ITALIC (100+CHAT_BTN_ITALIC)
65 #define ID_CHAT_BTN_SEND   (100+CHAT_BTN_SEND)
66 #define ID_CHAT_BTN_COLOR  (100+CHAT_BTN_COLOR)
67 #define ID_CHAT_LIST       105
68 #define ID_CHAT_EDIT       106
69 
70 typedef struct tagChatInfo {
71    SimpleWinInfo base_win_info, list_win_info, edit_win_info;
72    SimpleWinInfo btn_win_info[MAX_CHAT_BTNS];
73 
74    int just_clicked;
75 
76    char ini_fname[MAXPATHLENGTH];
77 
78    int font_height; /* font height used for all controls */
79    int font_width;
80    int gap; /* gaps between controls */
81    int btn_width; /* width of square buttons */
82    int num_lines; /* number of visible lines in the list control */
83 
84    TdgtList *list_ctl;
85    TdgtBtn *btn_ctl[MAX_CHAT_BTNS];
86    TdgtSmplEdit *edit_ctl;
87 } ChatInfo;
88 
89 ChatInfo gstChatInfo;
90 
91 char *cmdLineChatNickName=NULL;
92 
93 static Pixmap a1Pixmap=None;
94 static Pixmap bold1Pixmap=None;
95 static Pixmap italic1Pixmap=None;
96 
97 static char *gpszChatNickName=NULL;
98 
RedrawChatWindow()99 void RedrawChatWindow()
100 {
101    if (PRTGIF || noChatWindow || chatWindow == None) return;
102 
103    /* draw a frame around the window */
104    if (threeDLook) {
105       if (dialogboxUse3DBorder) {
106          struct BBRec bbox;
107 
108          SetBBRec(&bbox, 0, 0, gstChatInfo.base_win_info.w,
109                gstChatInfo.base_win_info.h);
110          TgDrawThreeDButton(mainDisplay, chatWindow, textMenuGC, &bbox,
111                TGBS_RAISED, 2, FALSE);
112       }
113    } else {
114       XDrawRectangle(mainDisplay, chatWindow, nameGC, 0, 0,
115             gstChatInfo.base_win_info.w-1, gstChatInfo.base_win_info.h-1);
116    }
117 }
118 
119 static
MoveResizeChatSubWindows()120 void MoveResizeChatSubWindows()
121 {
122    if (gstChatInfo.list_ctl != NULL) {
123       TidgetMoveResize(gstChatInfo.list_ctl->pti, gstChatInfo.list_win_info.x,
124             gstChatInfo.list_win_info.y, gstChatInfo.list_win_info.w,
125             gstChatInfo.list_win_info.h);
126    }
127    if (gstChatInfo.btn_ctl[CHAT_BTN_SEND] != NULL) {
128       TidgetMoveResize((gstChatInfo.btn_ctl[CHAT_BTN_SEND])->pti,
129             gstChatInfo.btn_win_info[CHAT_BTN_SEND].x,
130             gstChatInfo.btn_win_info[CHAT_BTN_SEND].y,
131             gstChatInfo.btn_win_info[CHAT_BTN_SEND].w,
132             gstChatInfo.btn_win_info[CHAT_BTN_SEND].h);
133    }
134    if (gstChatInfo.edit_ctl != NULL) {
135       TidgetMoveResize(gstChatInfo.edit_ctl->pti, gstChatInfo.edit_win_info.x,
136             gstChatInfo.edit_win_info.y, gstChatInfo.edit_win_info.w,
137             gstChatInfo.edit_win_info.h);
138    }
139 }
140 
MoveResizeChatWindow(x,y,w,h)141 void MoveResizeChatWindow(x, y, w, h)
142    int x, y, w, h;
143 {
144    XMoveResizeWindow(mainDisplay, chatWindow, x, y, w, h);
145    MoveResizeChatSubWindows();
146 }
147 
148 static
GetChatFontStyle(pnIsBold,pnIsItalic)149 int GetChatFontStyle(pnIsBold, pnIsItalic)
150    int *pnIsBold, *pnIsItalic;
151 {
152    int bold_state=TdgtBtnGetState(gstChatInfo.btn_ctl[CHAT_BTN_BOLD]);
153    int italic_state=TdgtBtnGetState(gstChatInfo.btn_ctl[CHAT_BTN_ITALIC]);
154    int is_bold=(bold_state != TGBS_NORMAL);
155    int is_italic=(italic_state != TGBS_NORMAL);
156    int font_style=INVALID;
157 
158    if (is_bold) {
159       if (is_italic) {
160          font_style = STYLE_BI;
161       } else {
162          font_style = STYLE_BR;
163       }
164    } else {
165       if (is_italic) {
166          font_style = STYLE_NI;
167       } else {
168          font_style = STYLE_NR;
169       }
170    }
171    if (pnIsBold != NULL) *pnIsBold = is_bold;
172    if (pnIsItalic != NULL) *pnIsItalic = is_italic;
173 
174    return font_style;
175 }
176 
177 static
InitChatNickName()178 int InitChatNickName()
179 {
180    char *c_ptr=NULL;
181 
182    if (cmdLineChatNickName != NULL) {
183       gpszChatNickName = UtilStrDup(cmdLineChatNickName);
184    } else {
185       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "ChatNickName")) != NULL) {
186          gpszChatNickName = UtilStrDup(c_ptr);
187       }
188    }
189    if (gpszChatNickName == NULL) {
190       c_ptr = getenv("USER");
191       if (c_ptr != NULL) {
192          gpszChatNickName = UtilStrDup(c_ptr);
193       } else {
194          gpszChatNickName = UtilStrDup(
195                TgLoadCachedString(CSTID_PARANED_UNKNOWN));
196       }
197    }
198    if (gpszChatNickName == NULL) FailAllocMessage();
199 
200    return TRUE;
201 }
202 
203 static
GetChatNickName(buf,buf_sz)204 void GetChatNickName(buf, buf_sz)
205    char *buf;
206    int buf_sz;
207 {
208    UtilStrCpyN(buf, buf_sz, gpszChatNickName);
209 }
210 
211 static
AddChatLineToListCtl(nick_name,color_index,font_style,buf)212 int AddChatLineToListCtl(nick_name, color_index, font_style, buf)
213    char *nick_name, *buf;
214    int color_index, font_style;
215 {
216    ListItemInfo *pListItemInfo=(ListItemInfo*)malloc(sizeof(ListItemInfo));
217 
218    if (pListItemInfo == NULL) FailAllocMessage();
219    memset(pListItemInfo, 0, sizeof(ListItemInfo));
220 
221    UtilStrCpyN(pListItemInfo->nick_name, sizeof(pListItemInfo->nick_name),
222          nick_name);
223    pListItemInfo->color_index = color_index;
224    pListItemInfo->font_style = font_style;
225    pListItemInfo->buf = UtilStrDup(buf);
226    if (pListItemInfo->buf == NULL) FailAllocMessage();
227 
228    return TdgtListInsertListItemInfo(gstChatInfo.list_ctl, pListItemInfo);
229 }
230 
231 static
ChatSendClicked()232 void ChatSendClicked()
233 {
234    char *buf=TdgtSmplEditGetText(gstChatInfo.edit_ctl);
235 
236    if (buf != NULL && *buf != '\0') {
237       int saved_auto_scroll=TdgtListGetAutoScrollOnInsert(gstChatInfo.list_ctl);
238       int rc=0;
239       struct SubCmdRec subcmd;
240       char *encoded_text=Base64Encode(buf);
241 
242       memset(&subcmd, 0, sizeof(struct SubCmdRec));
243 
244       TdgtSmplEditGetTextFormatInfo(gstChatInfo.edit_ctl,
245             &subcmd.detail.chat.tfi);
246 
247       subcmd.detail.chat.type = CHAT_STATE_NORMAL;
248       GetChatNickName(subcmd.detail.chat.nick_name,
249             sizeof(subcmd.detail.chat.nick_name));
250       UtilStrCpyN(subcmd.detail.chat.encoding,
251             sizeof(subcmd.detail.chat.encoding), "base64");
252       TdgtListSetAutoScrollOnInsert(gstChatInfo.list_ctl, TRUE);
253       rc = AddChatLineToListCtl(subcmd.detail.chat.nick_name,
254             subcmd.detail.chat.tfi.color_index,
255             subcmd.detail.chat.tfi.font_style, buf);
256       TdgtListSetAutoScrollOnInsert(gstChatInfo.list_ctl, saved_auto_scroll);
257       if (rc) {
258          subcmd.detail.chat.buf = UtilStrDup(encoded_text);
259          if (subcmd.detail.chat.buf == NULL) FailAllocMessage();
260          RecordWBChatALine(&subcmd);
261          UtilFree(subcmd.detail.chat.buf);
262       }
263       TdgtSmplEditSetText(gstChatInfo.edit_ctl, "");
264       UtilFree(encoded_text);
265    }
266 }
267 
ChatEventHandler(input,handling_pti)268 void ChatEventHandler(input, handling_pti)
269    XEvent *input;
270    TidgetInfo *handling_pti;
271 {
272    int keypress_event=(input->type==KeyPress), event_handled=FALSE;
273 
274    if (PRTGIF || noChatWindow || chatWindow == None) return;
275 
276    /*
277     * If the event is a KeyPress event, either a special key is pressed
278     *         or a regular key is pressed.  Special keys should be handled
279     *         by the list control and regular keys should be handled by
280     *         the edit control.
281     */
282    if (input->xany.window == chatWindow) {
283       TdgtNtfy tdgt_notify;
284 
285       memset(&tdgt_notify, 0, sizeof(TdgtNtfy));
286       if (input->type == Expose) {
287          XEvent ev;
288 
289          RedrawChatWindow();
290          while (XCheckWindowEvent(mainDisplay, chatWindow, ExposureMask, &ev)) ;
291       } else if (input->type == EnterNotify) {
292          SetMouseStatus("", "", "");
293          if (input->xcrossing.mode == NotifyNormal &&
294                (input->xcrossing.detail == NotifyAncestor ||
295                input->xcrossing.detail == NotifyNonlinear ||
296                input->xcrossing.detail == NotifyNonlinearVirtual)) {
297             TdgtSmplEditSetFocus(gstChatInfo.edit_ctl, TRUE);
298             if (gnInputMethod != TGIM_NONE) {
299                tgIMFocusIn(mainDisplay, gstChatInfo.edit_ctl->pti->tci.win);
300             }
301          }
302       } else if (input->type == LeaveNotify) {
303          if (input->xcrossing.mode == NotifyNormal &&
304                (input->xcrossing.detail == NotifyAncestor ||
305                input->xcrossing.detail == NotifyNonlinear ||
306                input->xcrossing.detail == NotifyNonlinearVirtual)) {
307             TdgtSmplEditSetFocus(gstChatInfo.edit_ctl, FALSE);
308             if (gnInputMethod != TGIM_NONE) {
309                tgIMFocusOut(mainDisplay, gstChatInfo.edit_ctl->pti->tci.win);
310             }
311          }
312       } else if (IsTdgtWindowNotifyEvent(chatWindow, input, &tdgt_notify)) {
313          switch (tdgt_notify.nf_type) {
314          case TDGTNF_EDIT_ENTERED:
315             ChatSendClicked();
316             break;
317          case TDGTNF_BTN_CLICKED:
318             switch (tdgt_notify.ctl_id) {
319             case ID_CHAT_BTN_SEND: ChatSendClicked(); break;
320 
321             case ID_CHAT_BTN_BOLD:
322             case ID_CHAT_BTN_ITALIC:
323                {
324                   int is_bold=FALSE, is_italic=FALSE;
325 
326                   /* bold or italic button changed state */
327                   int font_style=GetChatFontStyle(&is_bold, &is_italic);
328 
329                   TdgtSmplEditSetFontStyle(gstChatInfo.edit_ctl, font_style);
330                   tgWriteProfileString("User", "Bold",
331                         (is_bold ? "1" : "0"), gstChatInfo.ini_fname);
332                   tgWriteProfileString("User", "Italic",
333                         (is_italic ? "1" : "0"), gstChatInfo.ini_fname);
334                   tgWriteProfileString(NULL, NULL, NULL, gstChatInfo.ini_fname);
335                }
336                break;
337             case ID_CHAT_BTN_AUTO:
338                {
339                   /* auto scroll changed state */
340                   int auto_state=TdgtBtnGetState(
341                         gstChatInfo.btn_ctl[CHAT_BTN_AUTO]);
342                   int auto_scroll=(auto_state != TGBS_NORMAL);
343 
344                   TdgtListSetAutoScrollOnInsert(gstChatInfo.list_ctl,
345                         auto_scroll);
346                }
347                break;
348             }
349             break;
350          case TDGTNF_MULTI_BTN_CLICKED:
351             if (tdgt_notify.ctl_id == ID_CHAT_BTN_COLOR) {
352                int color_index=INVALID;
353 
354                switch (tdgt_notify.nf_arg) { /* Button[1-3] */
355                case Button1:
356                   color_index = (int)(long)TdgtBtnGetText(
357                         gstChatInfo.btn_ctl[CHAT_BTN_COLOR]);
358                   if (++color_index >= maxColors) color_index = 0;
359                   break;
360                case Button2:
361                   color_index = tdgt_notify.nf_arg2;
362                   break;
363                case Button3:
364                   color_index = (int)(long)TdgtBtnGetText(
365                         gstChatInfo.btn_ctl[CHAT_BTN_COLOR]);
366                   if (--color_index < 0) color_index = maxColors-1;
367                   break;
368                }
369                TdgtBtnSetText(gstChatInfo.btn_ctl[CHAT_BTN_COLOR],
370                      (char*)(long)color_index, NULL);
371                TdgtSmplEditSetColorIndex(gstChatInfo.edit_ctl, color_index);
372                tgWriteProfileString("User", "Color",
373                      colorMenuItems[color_index], gstChatInfo.ini_fname);
374                tgWriteProfileString(NULL, NULL, NULL, gstChatInfo.ini_fname);
375             }
376             break;
377          }
378          event_handled = TRUE;
379       }
380    } else if (gstChatInfo.list_ctl != NULL &&
381          TidgetEventHandler(gstChatInfo.list_ctl->pti, input, handling_pti)) {
382       /* this event has been handled by the list */
383       event_handled = TRUE;
384    } else if (gstChatInfo.edit_ctl != NULL &&
385          TidgetEventHandler(gstChatInfo.edit_ctl->pti, input, handling_pti)) {
386       event_handled = TRUE;
387    } else {
388       int i=0;
389 
390       for (i=0; i < MAX_CHAT_BTNS; i++) {
391          if (gstChatInfo.btn_ctl[i] != NULL &&
392                TidgetEventHandler((gstChatInfo.btn_ctl[i])->pti, input,
393                handling_pti)) {
394             event_handled = TRUE;
395          }
396       }
397    }
398    if (keypress_event && !event_handled &&
399          TidgetEventHandler(gstChatInfo.edit_ctl->pti, input, handling_pti)) {
400    }
401 }
402 
IsChatWindowEvent(input,ppti_handler_tidget_return)403 int IsChatWindowEvent(input, ppti_handler_tidget_return)
404    XEvent *input;
405    TidgetInfo **ppti_handler_tidget_return;
406 {
407    int i=0;
408 
409    *ppti_handler_tidget_return = NULL;
410 
411    if (chatWindow == None) return FALSE;
412 
413    if (input->xany.window == chatWindow) return TRUE;
414    if (gstChatInfo.list_ctl != NULL && IsTidgetEvent(gstChatInfo.list_ctl->pti,
415          input, ppti_handler_tidget_return)) {
416       return TRUE;
417    }
418    for (i=0; i < MAX_CHAT_BTNS; i++) {
419       if (gstChatInfo.btn_ctl[i] != NULL &&
420             IsTidgetEvent((gstChatInfo.btn_ctl[i])->pti, input,
421             ppti_handler_tidget_return)) {
422          return TRUE;
423       }
424    }
425    if (gstChatInfo.edit_ctl != NULL && IsTidgetEvent(gstChatInfo.edit_ctl->pti,
426          input, ppti_handler_tidget_return)) {
427       return TRUE;
428    }
429    return FALSE;
430 }
431 
432 #define BTN_Y_MARGIN 2
433 
GetInitialChatWindowHeight()434 int GetInitialChatWindowHeight()
435 {
436    int x=0, y=0;
437 
438    gstChatInfo.num_lines=6;
439    if (msgFontSet == NULL && msgFontPtr == NULL) {
440       gstChatInfo.font_height = defaultFontHeight;
441       gstChatInfo.font_width = defaultFontWidth;
442    } else {
443       gstChatInfo.font_height = msgFontHeight;
444       gstChatInfo.font_width = msgFontWidth;
445    }
446    gstChatInfo.btn_width = a1_width+(windowPadding<<1);
447 
448    /* gap */
449    y = gstChatInfo.gap = 4;
450 
451    /* list control */
452    gstChatInfo.list_win_info.x = gstChatInfo.gap;
453    gstChatInfo.list_win_info.y = y;
454    gstChatInfo.list_win_info.w = (-1);
455    gstChatInfo.list_win_info.h =
456          (gstChatInfo.num_lines*ROW_HEIGHT)+2+(windowPadding<<1);
457    y += gstChatInfo.list_win_info.h;
458 
459    /* gap */
460    y += gstChatInfo.gap;
461 
462    /* other controls */
463    x = gstChatInfo.list_win_info.x;
464    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].x = x;
465    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].y = y;
466    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].w = gstChatInfo.btn_width;
467    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].h = gstChatInfo.btn_width;
468    x += gstChatInfo.btn_width + (gstChatInfo.btn_width>>1);
469    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].x = x;
470    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].y = y;
471    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].w = gstChatInfo.btn_width;
472    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].h = gstChatInfo.btn_width;
473    x += gstChatInfo.btn_width + 2;
474    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].x = x;
475    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].y = y;
476    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].w = gstChatInfo.btn_width;
477    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].h = gstChatInfo.btn_width;
478    x += gstChatInfo.btn_width + 2;
479    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].x = x;
480    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].y = y;
481    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].w = gstChatInfo.btn_width;
482    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].h = gstChatInfo.btn_width;
483    x += gstChatInfo.btn_width + (gstChatInfo.btn_width>>1);
484    gstChatInfo.edit_win_info.x = x;
485    gstChatInfo.edit_win_info.y = y;
486    gstChatInfo.edit_win_info.w = (-1);
487    gstChatInfo.edit_win_info.h = gstChatInfo.btn_width;
488    x += gstChatInfo.btn_width + (gstChatInfo.btn_width>>1);
489    gstChatInfo.btn_win_info[CHAT_BTN_SEND].x = (-1);
490    gstChatInfo.btn_win_info[CHAT_BTN_SEND].y = y;
491    gstChatInfo.btn_win_info[CHAT_BTN_SEND].w =
492          ButtonWidth("Send", 4, NULL);
493    gstChatInfo.btn_win_info[CHAT_BTN_SEND].h =
494          (gstChatInfo.font_height+(BTN_Y_MARGIN<<1)+(windowPadding<<1));
495    y += gstChatInfo.btn_width;
496 
497    /* gap */
498    y += gstChatInfo.gap;
499 
500    return y;
501 }
502 
SetChatWindowGeom()503 void SetChatWindowGeom()
504 {
505    int x=0, y=0;
506 
507    gstChatInfo.base_win_info.x = (-1);
508    gstChatInfo.base_win_info.y = (-1);
509    gstChatInfo.base_win_info.w = chatWindowW;
510    gstChatInfo.base_win_info.h = chatWindowH;
511 
512    /* gap */
513    y = gstChatInfo.gap;
514 
515    /* list control */
516    gstChatInfo.list_win_info.x = gstChatInfo.gap;
517    gstChatInfo.list_win_info.y = y;
518    gstChatInfo.list_win_info.w =
519          gstChatInfo.base_win_info.w - (gstChatInfo.gap<<1);
520    gstChatInfo.list_win_info.h =
521          (gstChatInfo.num_lines*ROW_HEIGHT)+2+(windowPadding<<1);
522 
523    y += gstChatInfo.list_win_info.h;
524 
525    /* gap */
526    y += gstChatInfo.gap;
527 
528    /* other controls */
529    x = gstChatInfo.list_win_info.x;
530    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].x = x;
531    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].y = y;
532    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].w = gstChatInfo.btn_width;
533    gstChatInfo.btn_win_info[CHAT_BTN_AUTO].h = gstChatInfo.btn_width;
534    x += gstChatInfo.btn_width + (gstChatInfo.btn_width>>1);
535    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].x = x;
536    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].y = y;
537    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].w = gstChatInfo.btn_width;
538    gstChatInfo.btn_win_info[CHAT_BTN_COLOR].h = gstChatInfo.btn_width;
539    x += gstChatInfo.btn_width + 2;
540    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].x = x;
541    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].y = y;
542    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].w = gstChatInfo.btn_width;
543    gstChatInfo.btn_win_info[CHAT_BTN_BOLD].h = gstChatInfo.btn_width;
544    x += gstChatInfo.btn_width + 2;
545    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].x = x;
546    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].y = y;
547    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].w = gstChatInfo.btn_width;
548    gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].h = gstChatInfo.btn_width;
549    x += gstChatInfo.btn_width + (gstChatInfo.btn_width>>1);
550    gstChatInfo.edit_win_info.x = x;
551    gstChatInfo.edit_win_info.y = y;
552    gstChatInfo.edit_win_info.w = (-1);
553    gstChatInfo.edit_win_info.h = gstChatInfo.btn_width;
554    x += gstChatInfo.btn_width + (gstChatInfo.btn_width>>1);
555    gstChatInfo.btn_win_info[CHAT_BTN_SEND].x = (-1);
556    gstChatInfo.btn_win_info[CHAT_BTN_SEND].y = y;
557    gstChatInfo.btn_win_info[CHAT_BTN_SEND].w =
558          ButtonWidth("Send", 4, NULL);
559    gstChatInfo.btn_win_info[CHAT_BTN_SEND].h = gstChatInfo.btn_width;
560    y += gstChatInfo.btn_width;
561 
562    gstChatInfo.btn_win_info[CHAT_BTN_SEND].x =
563          gstChatInfo.base_win_info.w - gstChatInfo.gap -
564          (windowPadding<<1) - gstChatInfo.btn_win_info[CHAT_BTN_SEND].w;
565    gstChatInfo.edit_win_info.w = gstChatInfo.btn_win_info[CHAT_BTN_SEND].x -
566          (gstChatInfo.btn_width>>1) - gstChatInfo.edit_win_info.x;
567 
568    /* gap */
569    y += gstChatInfo.gap;
570 }
571 
MapChatSubWindows()572 void MapChatSubWindows()
573 {
574    int i=0;
575 
576    if (gstChatInfo.list_ctl != NULL) MapTidget(gstChatInfo.list_ctl->pti);
577    for (i=0; i < MAX_CHAT_BTNS; i++) {
578       if (gstChatInfo.btn_ctl[i] != NULL) {
579          MapTidget((gstChatInfo.btn_ctl[i])->pti);
580       }
581    }
582    if (gstChatInfo.edit_ctl != NULL) MapTidget(gstChatInfo.edit_ctl->pti);
583 }
584 
CreateChatSubWindows()585 int CreateChatSubWindows()
586 {
587    MouseOverStatusInfo mosi;
588    char *buf=NULL;
589    int new_alloc=FALSE, ival=0, font_style=STYLE_NR;
590    int is_bold=FALSE, is_italic=FALSE, color_index=colorIndex;
591 
592    if ((buf=tgGetProfileString("User", "Color", gstChatInfo.ini_fname)) !=
593          NULL) {
594       color_index = QuickFindColorIndex(NULL, buf, &new_alloc, TRUE);
595       tgFreeProfileString(buf);
596    }
597    if ((buf=tgGetProfileString("User", "Bold", gstChatInfo.ini_fname)) !=
598          NULL) {
599       if (sscanf(buf, "%d", &ival) == 1) {
600          is_bold = ival;
601       } else {
602          tgWriteProfileString("User", "Bold", "0", gstChatInfo.ini_fname);
603          tgWriteProfileString(NULL, NULL, NULL, gstChatInfo.ini_fname);
604       }
605       tgFreeProfileString(buf);
606    }
607    if ((buf=tgGetProfileString("User", "Italic", gstChatInfo.ini_fname)) !=
608          NULL) {
609       if (sscanf(buf, "%d", &ival) == 1) {
610          is_italic = ival;
611       } else {
612          tgWriteProfileString("User", "Italic", "0", gstChatInfo.ini_fname);
613          tgWriteProfileString(NULL, NULL, NULL, gstChatInfo.ini_fname);
614       }
615       tgFreeProfileString(buf);
616    }
617    if (is_bold) {
618       if (is_italic) {
619          font_style = STYLE_BI;
620       } else {
621          font_style = STYLE_BR;
622       }
623    } else {
624       if (is_italic) {
625          font_style = STYLE_NI;
626       } else {
627          font_style = STYLE_NR;
628       }
629    }
630    memset(&mosi, 0, sizeof(MouseOverStatusInfo));
631    mosi.one_line_status = TRUE;
632 
633    a1Pixmap = XCreateBitmapFromData(mainDisplay, mainWindow,
634          (char*)a1_bits, a1_width, a1_height);
635    bold1Pixmap = XCreateBitmapFromData(mainDisplay, mainWindow,
636          (char*)bold1_bits, bold1_width, bold1_height);
637    italic1Pixmap = XCreateBitmapFromData(mainDisplay, mainWindow,
638          (char*)italic1_bits, italic1_width, italic1_height);
639 
640    gstChatInfo.list_ctl = CreateTdgtList(chatWindow, NULL, ID_CHAT_LIST,
641          gstChatInfo.list_win_info.x, gstChatInfo.list_win_info.y,
642          gstChatInfo.list_win_info.w, TDGTLIST_DEF_H_PAD, TDGTLIST_DEF_V_PAD,
643          gstChatInfo.num_lines, FALSE, TRUE, TRUE);
644    if (gstChatInfo.list_ctl == NULL) return FALSE;
645 
646    UtilStrCpyN(mosi.one_line_str, sizeof(mosi.one_line_str),
647          TgLoadString(STID_TOGGLE_AUTO_SCR_IN_CHAT));
648    gstChatInfo.btn_ctl[CHAT_BTN_AUTO] = CreateTdgtBtn(chatWindow, NULL,
649          ID_CHAT_BTN_AUTO, gstChatInfo.btn_win_info[CHAT_BTN_AUTO].x,
650          gstChatInfo.btn_win_info[CHAT_BTN_AUTO].y,
651          gstChatInfo.btn_win_info[CHAT_BTN_AUTO].w,
652          gstChatInfo.btn_win_info[CHAT_BTN_AUTO].h,
653          0, 0, TGMUTYPE_BITMAP, TDGTBTN_STICKY, TGBS_LOWRED, STYLE_NR,
654          (char*)(&a1Pixmap), &mosi);
655 
656    UtilStrCpyN(mosi.one_line_str, sizeof(mosi.one_line_str),
657          TgLoadString(STID_TOGGLE_BOLD_IN_CHAT));
658    gstChatInfo.btn_ctl[CHAT_BTN_BOLD] = CreateTdgtBtn(chatWindow, NULL,
659          ID_CHAT_BTN_BOLD, gstChatInfo.btn_win_info[CHAT_BTN_BOLD].x,
660          gstChatInfo.btn_win_info[CHAT_BTN_BOLD].y,
661          gstChatInfo.btn_win_info[CHAT_BTN_BOLD].w,
662          gstChatInfo.btn_win_info[CHAT_BTN_BOLD].h,
663          0, 0, TGMUTYPE_BITMAP, TDGTBTN_STICKY,
664          (is_bold ? TGBS_LOWRED : TGBS_NORMAL), STYLE_BR,
665          (char*)(&bold1Pixmap), &mosi);
666 
667    UtilStrCpyN(mosi.one_line_str, sizeof(mosi.one_line_str),
668          TgLoadString(STID_TOGGLE_ITALIC_IN_CHAT));
669    gstChatInfo.btn_ctl[CHAT_BTN_ITALIC] = CreateTdgtBtn(chatWindow, NULL,
670          ID_CHAT_BTN_ITALIC, gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].x,
671          gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].y,
672          gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].w,
673          gstChatInfo.btn_win_info[CHAT_BTN_ITALIC].h,
674          0, 0, TGMUTYPE_BITMAP, TDGTBTN_STICKY,
675          (is_italic ? TGBS_LOWRED : TGBS_NORMAL), STYLE_NI,
676          (char*)(&italic1Pixmap), &mosi);
677 
678    UtilStrCpyN(mosi.one_line_str, sizeof(mosi.one_line_str),
679          TgLoadString(STID_SEND_CHAT_TEXT));
680    gstChatInfo.btn_ctl[CHAT_BTN_SEND] = CreateTdgtBtn(chatWindow, NULL,
681          ID_CHAT_BTN_SEND, gstChatInfo.btn_win_info[CHAT_BTN_SEND].x,
682          gstChatInfo.btn_win_info[CHAT_BTN_SEND].y,
683          gstChatInfo.btn_win_info[CHAT_BTN_SEND].w,
684          gstChatInfo.btn_win_info[CHAT_BTN_SEND].h,
685          0, 0, TGMUTYPE_TEXT, TDGTBTN_CLICK, TGBS_NORMAL, STYLE_NR, "Send",
686          &mosi);
687 
688    mosi.one_line_status = FALSE;
689    UtilStrCpyN(mosi.btn_str[0], sizeof(mosi.btn_str[0]), colorMouseStatus[0].l);
690    UtilStrCpyN(mosi.btn_str[1], sizeof(mosi.btn_str[1]), colorMouseStatus[0].m);
691    UtilStrCpyN(mosi.btn_str[2], sizeof(mosi.btn_str[2]), colorMouseStatus[0].r);
692    gstChatInfo.btn_ctl[CHAT_BTN_COLOR] = CreateTdgtBtn(chatWindow, NULL,
693          ID_CHAT_BTN_COLOR, gstChatInfo.btn_win_info[CHAT_BTN_COLOR].x,
694          gstChatInfo.btn_win_info[CHAT_BTN_COLOR].y,
695          gstChatInfo.btn_win_info[CHAT_BTN_COLOR].w,
696          gstChatInfo.btn_win_info[CHAT_BTN_COLOR].h,
697          0, 0, TGMUTYPE_COLOR, TDGTBTN_CLICK, TGBS_NORMAL, INVALID,
698          (char*)(long)color_index, &mosi);
699 
700    gstChatInfo.edit_ctl = CreateTdgtSmplEdit(chatWindow, NULL, ID_CHAT_EDIT,
701          gstChatInfo.edit_win_info.x, gstChatInfo.edit_win_info.y,
702          gstChatInfo.edit_win_info.w, TDGTSEDT_DEF_H_PAD, TDGTSEDT_DEF_V_PAD,
703          "", font_style, color_index);
704    if (gstChatInfo.edit_ctl == NULL) return FALSE;
705 
706    return TRUE;
707 }
708 
709 /* --------------------- ChatInsertChatLine --------------------- */
710 
ChatAppendChatLine(ptfi,nick_name,encoding,buf)711 void ChatAppendChatLine(ptfi, nick_name, encoding, buf)
712    TextFormatInfo *ptfi;
713    char *nick_name, *encoding, *buf;
714 {
715    char *clear_text=NULL;
716    ListItemInfo *pListItemInfo=(ListItemInfo*)malloc(sizeof(ListItemInfo));
717 
718    if (pListItemInfo == NULL) FailAllocMessage();
719    memset(pListItemInfo, 0, sizeof(ListItemInfo));
720 
721    if (*encoding == '\0') {
722       clear_text = buf;
723    } else if (strcmp(encoding, "base64") == 0) {
724       clear_text = Base64Decode(buf);
725    } else {
726       /* reject */
727    }
728    UtilStrCpyN(pListItemInfo->nick_name, sizeof(pListItemInfo->nick_name),
729          nick_name);
730    pListItemInfo->color_index = ptfi->color_index;
731    pListItemInfo->font_style = ptfi->font_style;
732    pListItemInfo->buf = UtilStrDup(clear_text);
733    if (pListItemInfo->buf == NULL) FailAllocMessage();
734 
735    TdgtListInsertListItemInfo(gstChatInfo.list_ctl, pListItemInfo);
736 
737    UtilFree(clear_text);
738 }
739 
740 /* --------------------- ChatAddUser --------------------- */
741 
ChatAddUser(buf)742 void ChatAddUser(buf)
743    char *buf;
744 {
745 }
746 
747 /* --------------------- Init & Clean Up --------------------- */
748 
InitChat()749 int InitChat()
750 {
751    memset(&gstChatInfo, 0, sizeof(ChatInfo));
752 
753    sprintf(gstChatInfo.ini_fname, "%s%cchat.ini", tgifDir, DIR_SEP);
754    return InitChatNickName();
755 }
756 
CleanUpChat()757 void CleanUpChat()
758 {
759    int i=0;
760 
761    UtilFree(gpszChatNickName);
762    gpszChatNickName = NULL;
763 
764    if (a1Pixmap != None) XFreePixmap(mainDisplay, a1Pixmap);
765    if (bold1Pixmap != None) XFreePixmap(mainDisplay, bold1Pixmap);
766    if (italic1Pixmap != None) XFreePixmap(mainDisplay, italic1Pixmap);
767    a1Pixmap = bold1Pixmap = italic1Pixmap = None;
768 
769    if (gstChatInfo.list_ctl != NULL) {
770       TidgetInfo *pti=((gstChatInfo.list_ctl)->pti);
771 
772       DestroyTidget(&pti);
773    }
774    for (i=0; i < MAX_CHAT_BTNS; i++) {
775       if (gstChatInfo.btn_ctl[i] != NULL) {
776          TidgetInfo *pti=((gstChatInfo.btn_ctl[i])->pti);
777 
778          DestroyTidget(&pti);
779       }
780    }
781    if (gstChatInfo.edit_ctl != NULL) {
782       TidgetInfo *pti=((gstChatInfo.edit_ctl)->pti);
783 
784       DestroyTidget(&pti);
785    }
786 }
787 
788