void HandleNeed(const CChan& Channel, const CString& sPerms) { MCString::iterator it = m_msChanModes.find(Channel.GetName()); if (it == m_msChanModes.end()) return; CString sModes = it->second; bool bMaster = (sModes.find("m") != CString::npos) || (sModes.find("n") != CString::npos); if (sPerms.find("o") != CString::npos) { bool bOp = (sModes.find("o") != CString::npos); bool bAutoOp = (sModes.find("a") != CString::npos); if (bMaster || bOp) { if (!bAutoOp) { PutModule("RequestPerms: Requesting op on " + Channel.GetName()); PutQ("OP " + Channel.GetName()); } return; } } if (sPerms.find("v") != CString::npos) { bool bVoice = (sModes.find("v") != CString::npos); bool bAutoVoice = (sModes.find("g") != CString::npos); if (bMaster || bVoice) { if (!bAutoVoice) { PutModule("RequestPerms: Requesting voice on " + Channel.GetName()); PutQ("VOICE " + Channel.GetName()); } return; } } }
void MCError::add(uint2 id, uint2 line, uint2 pos, const MCString &token) { if (MCerrorlock != 0 || thrown) return; if (line != 0 && errorline == 0) { errorline = line; errorpos = pos; } if (depth > 1024) return; char *newerror = new char[U2L * 3 + token.getlength()]; if (token == MCnullmcstring) sprintf(newerror, "%d,%d,%d", id, line, pos); else { const char *eptr = token.getstring(); int4 length = 0; while (length < (int4)token.getlength()) { if (*eptr++ == '\n') break; length++; } sprintf(newerror, "%d,%d,%d,%*.*s", id, line, pos, length, length, token.getstring()); } MCU_addline(buffer, newerror, strlen(buffer) == 0); depth += 1; delete newerror; }
void MCExecPoint::insert(const MCString &istring, uint4 s, uint4 e) { if (format == VF_NUMBER) tos(); uint4 oldlength = svalue.getlength(); uint4 ilength = istring.getlength(); uint4 newlength = oldlength - (e - s) + ilength; const char *sptr = svalue.getstring(); const char *isptr = istring.getstring(); char *oldbuffer = NULL; if (newlength > size || sptr >= buffer && sptr < buffer + newlength || isptr >= buffer && isptr < buffer + newlength) { oldbuffer = buffer; size = newlength + EP_PAD & EP_MASK; buffer = new char[size]; memcpy(buffer, sptr, s); memcpy(&buffer[s], isptr, ilength); memcpy(&buffer[s + ilength], &sptr[e], oldlength - e); } else { memmove(buffer, sptr, s); memmove(&buffer[s], isptr, ilength); memmove(&buffer[s + ilength], &sptr[e], oldlength - e); } delete oldbuffer; svalue.set(buffer, newlength); format = VF_STRING; }
Exec_stat MCVideoClip::setprop(uint4 parid, Properties p, MCExecPoint &ep, Boolean effective) { MCString data = ep.getsvalue(); Boolean dirty = False; switch (p) { case P_DONT_REFRESH: if (!MCU_matchflags(data, flags, F_DONT_REFRESH, dirty)) { MCeerror->add (EE_OBJECT_NAB, 0, 0, data); return ES_ERROR; } return ES_NORMAL; case P_FRAME_RATE: if (data.getlength() == 0) flags &= ~F_FRAME_RATE; else { if (!MCU_stoui2(data, framerate)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } flags |= F_FRAME_RATE; } return ES_NORMAL; case P_SCALE: if (!MCU_stor8(data, scale)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } flags |= F_SCALE_FACTOR; return ES_NORMAL; case P_TEXT: delete frames; size = data.getlength(); frames = new uint1[size]; memcpy(frames, data.getstring(), size); return ES_NORMAL; default: break; } return MCObject::setprop(parid, p, ep, effective); }
void MCS_posttourl(MCObject *p_target, const MCString& p_data, const char *p_url) { bool t_success = true; char *t_processed = nil; MCObjectHandle *t_obj = nil; MCSPostUrlState t_state; t_success = MCSystemProcessUrl(p_url, kMCSystemUrlOperationStrip, t_processed); if (t_success) t_success = nil != (t_obj = p_target->gethandle()); if (t_success) { t_state . url = t_processed; t_state . status = kMCSystemUrlStatusNone; t_state . object = t_obj; t_state . data . assign_empty(); t_state . post_sent = 0; t_state . post_length = p_data . getlength(); t_success = MCSystemPostUrl(t_processed, p_data.getstring(), p_data.getlength(), MCS_posturl_callback, &t_state); } if (t_success) { MCurlresult -> clear(); while(t_state . status != kMCSystemUrlStatusFinished && t_state . status != kMCSystemUrlStatusError) MCscreen -> wait(60.0, True, True); if (t_state . status == kMCSystemUrlStatusFinished) { MCurlresult -> getvalue() . exchange(t_state . data); MCresult -> clear(); } else { MCurlresult -> clear(); MCresult -> getvalue() . exchange(t_state . data); } } MCCStringFree(t_processed); if (t_obj != nil) t_obj -> Release(); }
bool MCSystemRemoveEvent(const char* p_calendar_event_id, bool p_reoccurring, char*& r_calendar_event_id_deleted) { // TODO - IMPLEMENT SUPPORT FOR API LEVEL 14 MCLog("MCSystemRemoveCalendarEvent: %s", p_calendar_event_id); MCAndroidEngineRemoteCall("removeCalendarEvent", "ss", &r_calendar_event_id_deleted, p_calendar_event_id); r_calendar_event_id_deleted = s_calendar_event_selected.clone(); return true; }
void MCError::copysvalue(const MCString &s, Boolean t) { delete buffer; buffer = s.clone(); thrown = t; if (thrown) svalue.set(buffer, strlen(buffer)); }
bool MCSystemFindEvent(MCDateTime p_start_date, MCDateTime p_end_date, char *& r_result) { // TODO - IMPLEMENT SUPPORT FOR API LEVEL 14 char *t_result; r_result = s_calendar_events_selected.clone(); MCLog("MCSystemFindCalendarEvent result: %s", r_result); return true; }
static bool MCParseRGBA(const MCString &p_data, bool p_require_alpha, uint1 &r_red, uint1 &r_green, uint1 &r_blue, uint1 &r_alpha) { bool t_success = true; Boolean t_parsed; uint2 r, g, b, a; const char *t_data = p_data.getstring(); uint32_t l = p_data.getlength(); if (t_success) { r = MCU_max(0, MCU_min(255, MCU_strtol(t_data, l, ',', t_parsed))); t_success = t_parsed; } if (t_success) { g = MCU_max(0, MCU_min(255, MCU_strtol(t_data, l, ',', t_parsed))); t_success = t_parsed; } if (t_success) { b = MCU_max(0, MCU_min(255, MCU_strtol(t_data, l, ',', t_parsed))); t_success = t_parsed; } if (t_success) { a = MCU_max(0, MCU_min(255, MCU_strtol(t_data, l, ',', t_parsed))); if (!t_parsed) { if (p_require_alpha) t_success = false; else a = 255; } } if (t_success) { r_red = r; r_green = g; r_blue = b; r_alpha = a; } return t_success; }
String *getLine(int lno) { int pos = colorer_get_line_pos(edit, lno); //CLR_TRACE("MC", "getLine:%03d - pos=%d", lno, pos); if (pos == -1){ CLR_ERROR("MC", "getLine: %d returns null", lno); return null; } cline->setPosition(pos); return cline; }
bool SendIRCMsgToSkype(const CString& a_nick, const CString& a_channel, const CString& a_message) { if(m_chanNameMap.find(a_channel.AsLower()) != m_chanNameMap.end() && !a_message.empty()) { CString l_message = stripIRCColorCodes(a_message); if(!IsStrValidUTF8(l_message)) { l_message = AnsiToUtf8(l_message); } if(!a_nick.empty()) { l_message = "<" + a_nick + "> " + l_message; } return SendSkypeCommand("CHATMESSAGE " + m_chanNameMap[a_channel.AsLower()] + " " + l_message); } return false; }
bool MCSystemShowEvent(const char* p_calendar_event_id, char*& r_result) { // TODO - IMPLEMENT SUPPORT FOR API LEVEL 14 MCLog("MCSystemShowCalendarEvent", NULL); MCAndroidEngineRemoteCall("showCalendarEvent", "vs", nil, p_calendar_event_id); s_calendar_event_status = kMCAndroidCalendarEventWaiting; while (s_calendar_event_status == kMCAndroidCalendarEventWaiting) MCscreen->wait(60.0, False, True); r_result = s_calendar_event_selected.clone(); MCLog("MCSystemShowCalendarEvent - finished", NULL); return true; }
IO_stat IO_write_string(const MCString &p_string, IO_handle p_stream, uint8_t p_size, bool p_write_null) { IO_stat stat = IO_NORMAL; uint32_t t_strlen = p_string.getlength(); uint4 length = 0; uint32_t t_inc = p_write_null ? 1 : 0; switch (p_size) { case 1: { uint1 len = t_strlen == 0 ? 0 : MCU_min(t_strlen + t_inc, MAXUINT1); if ((stat = IO_write_uint1(len, p_stream)) != IO_NORMAL) return stat; length = len; break; } case 2: { uint2 len = t_strlen == 0 ? 0 : MCU_min(t_strlen + t_inc, MAXUINT2); if ((stat = IO_write_uint2(len, p_stream)) != IO_NORMAL) return stat; length = len; break; } case 4: length = t_strlen == 0 ? 0 : t_strlen + t_inc; if ((stat = IO_write_uint4(length, p_stream)) != IO_NORMAL) return stat; break; } if (length) { stat = MCStackSecurityWrite(p_string.getstring(), length - t_inc, p_stream); if (stat == IO_NORMAL && p_write_null) stat = IO_write_uint1(0, p_stream); } return stat; }
bool MCSystemAddEvent(MCCalendar p_new_calendar_event_data, char*& r_result) { // TODO - IMPLEMENT SUPPORT FOR API LEVEL 14 MCLog("MCSystemAddCalendarEvent", NULL); MCAndroidEngineRemoteCall("addCalendarEvent", "issssbbbbiisiis", &r_result, p_new_calendar_event_data.mceventid.getstring(), p_new_calendar_event_data.mctitle.getstring(), p_new_calendar_event_data.mcnote.getstring(), p_new_calendar_event_data.mclocation.getstring(), p_new_calendar_event_data.mcalldayset, p_new_calendar_event_data.mcallday, p_new_calendar_event_data.mcstartdateset, p_new_calendar_event_data.mcenddateset, p_new_calendar_event_data.mcalert1, p_new_calendar_event_data.mcalert2, p_new_calendar_event_data.mcfrequency.getstring(), p_new_calendar_event_data.mcfrequencycount, p_new_calendar_event_data.mcfrequencyinterval, p_new_calendar_event_data.mccalendar.getstring()); r_result = s_calendar_event_selected.clone(); return true; }
void MCS_putintourl(MCObject *p_target, const MCString& p_data, const char *p_url) { bool t_success = true; char *t_processed = nil; MCObjectHandle *t_obj = nil; MCSPutUrlState t_state; t_success = MCSystemProcessUrl(p_url, kMCSystemUrlOperationStrip, t_processed); if (t_success) t_success = nil != (t_obj = p_target->gethandle()); if (t_success) { t_state.url = t_processed; t_state.status = kMCSystemUrlStatusNone; t_state.object = t_obj; t_state.put_sent = 0; t_state.put_length = p_data.getlength(); t_success = MCSystemPutUrl(t_processed, p_data . getstring(), p_data . getlength(), MCS_puturl_callback, &t_state); } if (t_success); { MCurlresult->clear(); while (t_state.status != kMCSystemUrlStatusUploaded && t_state.status != kMCSystemUrlStatusError) MCscreen->wait(60.0, True, True); if (t_state.status == kMCSystemUrlStatusUploaded) MCresult->clear(); else MCresult->sets(MCString(t_state.error)); } MCCStringFree(t_processed); if (t_obj != nil) t_obj->Release(); }
MCFontnode::MCFontnode(const MCString &fname, uint2 &size, uint2 style, Boolean printer) { reqname = fname.clone(); reqsize = size; reqstyle = style; reqprinter = printer; font = new MCFontStruct; if (MCnoui) { memset(font, 0, sizeof(MCFontStruct)); return; } LOGFONTA logfont; memset(&logfont, 0, sizeof(LOGFONTA)); uint4 maxlength = MCU_min(LF_FACESIZE - 1U, fname.getlength()); strncpy(logfont.lfFaceName, fname.getstring(), maxlength); logfont.lfFaceName[maxlength] = '\0'; // MW-2012-05-03: [[ Bug 10180 ]] Make sure the default charset for the font // is chosen - otherwise things like WingDings don't work! logfont.lfCharSet = DEFAULT_CHARSET; //parse font and encoding char *sptr = logfont.lfFaceName; if (sptr = strchr(logfont.lfFaceName, ',')) { *sptr = '\0'; sptr++; } HDC hdc; // MW-2013-11-07: [[ Bug 11393 ]] 'printer' in the fontstruct now means use ideal // metrics for rendering and measuring. MCScreenDC *pms = (MCScreenDC *)MCscreen; hdc = pms->getsrchdc(); logfont.lfHeight = MulDiv(MulDiv(size, 7, 8), SCREEN_WIDTH_FOR_FONT_USE, 72); logfont.lfWeight = weighttable[MCF_getweightint(style)]; if (style & FA_ITALIC) logfont.lfItalic = TRUE; if (style & FA_OBLIQUE) logfont.lfOrientation = 3600 - 150; /* 15 degree forward slant */ HFONT newfont = CreateFontIndirectA(&logfont); SelectObject(hdc, newfont); char testname[LF_FACESIZE]; memset(testname, 0, LF_FACESIZE); GetTextFaceA(hdc, LF_FACESIZE, testname); // MW-2012-02-13: If we failed to find an exact match then remap the font name and // try again. if (newfont == NULL || (MCU_strncasecmp(testname, logfont.lfFaceName, strlen(testname) + 1))) { if (newfont != NULL) DeleteObject(newfont); mapfacename(logfont.lfFaceName, logfont.lfFaceName, printer == True); // Force the resulting font to be TrueType and with ANSI charset (otherwise // we get strange UI symbol font on XP). logfont.lfCharSet = ANSI_CHARSET; logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS; newfont = CreateFontIndirectA(&logfont); SelectObject(hdc, newfont); } // At this point we will have either found an exact match for the textFont, mapped // using the defaults table and found a match, or been given a default truetype font. TEXTMETRICA tm; GetTextMetricsA(hdc, &tm); font->fid = (MCSysFontHandle)newfont; font->size = size; // MW-2013-12-19: [[ Bug 11606 ]] Use Mac-style metric adjustment in printer (ideal // layout mode). if (!printer) { font->ascent = MulDiv(tm.tmAscent, 15, 16); font->descent = tm.tmDescent; } else { font -> ascent = size - 1; font -> descent = size * 2 / 14 + 1; } font->printer = printer; }
LRESULT CALLBACK MCWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static Boolean isactive = True; KeySym keysym; MCStack *target; _Drawable _dw; Drawable dw = &_dw; dw->type = DC_WINDOW; dw->handle.window = (MCSysWindowHandle)hwnd; MCScreenDC *pms = (MCScreenDC *)MCscreen; MCStack *omousestack = MCmousestackptr; uint2 button; Boolean down; char buffer[XLOOKUPSTRING_SIZE]; MCPoint t_mouseloc; t_mouseloc = MCPointMake(LOWORD(lParam), HIWORD(lParam)); // IM-2014-01-28: [[ HiDPI ]] Convert screen to logical coords t_mouseloc = ((MCScreenDC*)MCscreen)->screentologicalpoint(t_mouseloc); // MW-2005-02-20: Seed the SSL random number generator #ifdef MCSSL SeedSSL(msg, wParam, lParam); #endif if (curinfo == NULL) curinfo = &dummycurinfo; switch (msg) { #ifdef FEATURE_RELAUNCH_SUPPORT case WM_COPYDATA: { LRESULT t_result; COPYDATASTRUCT *t_data; t_data = (COPYDATASTRUCT *)lParam; t_result = 0; if (t_data -> dwData == CWM_RELAUNCH) { MCresult -> clear(); MCParameter *t_first_parameter = NULL; MCParameter *t_current_parameter = NULL; extern char *strndup(const char *, unsigned int); char *t_command_line = strndup((char *)t_data -> lpData, t_data -> cbData); char *sptr = t_command_line; while(*sptr) { if (*sptr == '\\') *sptr = '/'; sptr++; } sptr = t_command_line; while(*sptr) { char *t_argument; int t_argument_length; while (isspace(*sptr)) sptr++; t_argument_length = 0; if (*sptr == '"') { t_argument = ++sptr; while (*sptr && *sptr != '"') { sptr++; t_argument_length += 1; } } else { t_argument = sptr; while(*sptr && !isspace(*sptr)) { sptr++; t_argument_length += 1; } } if (t_argument_length != 0) { MCParameter *t_parameter; MCString t_param; t_param . set(t_argument, t_argument_length); t_parameter = new MCParameter(t_param); if (t_first_parameter == NULL) t_first_parameter = t_parameter; else t_current_parameter -> setnext(t_parameter); t_current_parameter = t_parameter; } if (*sptr) sptr++; } if (MCdispatcher -> gethome() -> message(MCM_relaunch, t_first_parameter, False, True) != ES_NORMAL) t_result = 0; else { MCExecPoint t_ep; MCresult -> fetch(t_ep); if (t_ep . getsvalue() == "background") t_result = (LRESULT)HWND_BOTTOM; else t_result = MCdefaultstackptr -> getwindow() == NULL ? (LRESULT)HWND_BOTTOM : (LRESULT)(MCdefaultstackptr -> getwindow() -> handle . window); } while(t_first_parameter != NULL) { MCParameter *t_next; t_next = t_first_parameter -> getnext(); delete t_first_parameter; t_first_parameter = t_next; } free(t_command_line); MCresult -> clear(); } return t_result; } #endif case CWM_TASKBAR_NOTIFICATION: ((MCScreenDC *)MCscreen) -> processtaskbarnotify(hwnd, wParam, lParam); break; case WM_DISPLAYCHANGE: case WM_SETTINGCHANGE: { if (hwnd != ((MCScreenDC *)MCscreen) -> getinvisiblewindow()) break; ((MCScreenDC *)MCscreen) -> processdesktopchanged(true); } break; case WM_PALETTECHANGED: dw->handle.window = (MCSysWindowHandle)wParam; if (MCdispatcher->findstackd(dw) == NULL) { dw->handle.window = (MCSysWindowHandle)hwnd; MCStack *sptr = MCdispatcher->findstackd(dw); if (sptr != NULL) sptr->dirtyall(); } break; case WM_PAINT: { MCStack *t_stack; t_stack = MCdispatcher -> findstackd(dw); if (t_stack != nil) t_stack -> onpaint(); } break; case WM_SETFOCUS: //FocusIn if (curinfo->dispatch) { if (MCtracewindow == DNULL || hwnd != (HWND)MCtracewindow->handle.window) { dw->handle.window = (MCSysWindowHandle)GetFocus(); MCdispatcher->wkfocus(dw); } curinfo->handled = True; } else { MCEventnode *tptr = new MCEventnode(hwnd, msg, wParam, lParam, 0, MCmodifierstate, MCeventtime); pms->appendevent(tptr); } break; case WM_KILLFOCUS: //FocusOut: if (curinfo->dispatch) { if (MCtracewindow == DNULL || hwnd != (HWND)MCtracewindow->handle.window) MCdispatcher->wkunfocus(dw); curinfo->handled = True; } else { MCEventnode *tptr = new MCEventnode(hwnd, msg, wParam, lParam, 0, MCmodifierstate, MCeventtime); pms->appendevent(tptr); } break; case WM_SYSKEYDOWN: case WM_SYSCHAR: case WM_CHAR: case WM_KEYDOWN: { if (wParam == VK_CONTROL) break; char t_input_char; t_input_char = (char)wParam; if (IsWindowUnicode(hwnd)) { if (wParam >= 128) { bool t_is_unicode; WCHAR t_wide[1]; // MW-2012-07-25: [[ Bug 9200 ]] Make sure we roundtrip the input character // through 1252 *not* the active code page (which could be anything). t_wide[0] = (WCHAR)wParam; t_is_unicode = (WideCharToMultiByte(1252, 0, t_wide, 1, &t_input_char, 1, NULL, NULL) == 0); if (!t_is_unicode) { WCHAR t_reverse_wide[1]; t_is_unicode = MultiByteToWideChar(1252, 0, &t_input_char, 1, t_reverse_wide, 1) == 0; if (!t_is_unicode) t_is_unicode = t_reverse_wide[0] != t_wide[0]; } if (t_is_unicode && (msg == WM_CHAR || msg == WM_SYSCHAR)) { if (MCactivefield) { MCString t_unicode_string; t_unicode_string . set((char *)t_wide, 2); // MW-2012-02-03: [[ Unicode Block ]] Use the new finsert method to insert // text in unicode mode. MCactivefield -> finsertnew(FT_IMEINSERT, t_unicode_string, LCH_UNICODE, true); } break; } } } else if (wParam >= 128 && (((MCScreenDC *)MCscreen) -> system_codepage) != (((MCScreenDC *)MCscreen) -> input_codepage)) { WCHAR t_unicode_char; MultiByteToWideChar((((MCScreenDC *)MCscreen) -> input_codepage), 0, &t_input_char, 1, &t_unicode_char, 1); bool t_is_unicode; t_is_unicode = (WideCharToMultiByte((((MCScreenDC *)MCscreen) -> system_codepage), 0, &t_unicode_char, 1, &t_input_char, 1, NULL, NULL) == 0); if (!t_is_unicode) { WCHAR t_reverse_unicode_char; t_is_unicode = MultiByteToWideChar((((MCScreenDC *)MCscreen) -> system_codepage), 0, &t_input_char, 1, &t_reverse_unicode_char, 1) == 0; if (!t_is_unicode) t_is_unicode = t_reverse_unicode_char != t_unicode_char; } if (t_is_unicode) { if (MCactivefield) { MCString t_unicode_string; t_unicode_string . set((char *)&t_unicode_char, 2); // MW-2012-02-03: [[ Unicode Block ]] Use the new finsert method to insert // text in unicode mode. MCactivefield -> finsertnew(FT_IMEINSERT, t_unicode_string, LCH_UNICODE, true); } break; } } if (msg == WM_CHAR || msg == WM_SYSCHAR) wParam = t_input_char; buffer[0] = buffer[1] = 0; if (msg == WM_CHAR || msg == WM_SYSCHAR) buffer[0] = lastchar = wParam; // MW-2010-11-17: [[ Bug 3892 ]] Ctrl+Alt can be the same as AltGr. // If we are a CHAR message *and* have a non-control character *and* have Ctrl+Alt set, we discard the modifiers if ((msg == WM_CHAR || msg == WM_SYSCHAR) && wParam >= 32 && (MCmodifierstate & (MS_CONTROL | MS_ALT)) == (MS_CONTROL | MS_ALT)) MCmodifierstate = 0; if (curinfo->keysym == 0) // event came from some other dispatch keysym = pms->getkeysym(wParam, lParam); else keysym = curinfo->keysym; lastkeysym = keysym; if (MCmodifierstate & MS_CONTROL) if (wParam == VK_CANCEL || keysym == '.') { if (MCallowinterrupts && !MCdefaultstackptr->cantabort()) curinfo->abort = True; else MCinterrupt = True; } else if (msg == WM_KEYDOWN) buffer[0] = lastchar = wParam; if (curinfo->dispatch) { if (MCtracewindow == DNULL || hwnd != (HWND)MCtracewindow->handle.window) { uint2 count = LOWORD(lParam); while (count--) { if (!MCdispatcher->wkdown(dw, buffer, keysym) && (msg == WM_SYSKEYDOWN || msg == WM_SYSCHAR)) return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); if (count || lParam & 0x40000000) MCdispatcher->wkup(dw, buffer, keysym); } curinfo->handled = curinfo->reset = True; } } else { MCEventnode *tptr = new MCEventnode(hwnd, msg, wParam, lParam, keysym, MCmodifierstate, MCeventtime); pms->appendevent(tptr); } } break; case WM_KEYUP: case WM_SYSKEYUP: { if (curinfo->keysym == 0) // event came from some other dispatch keysym = pms->getkeysym(wParam, lParam); else keysym = curinfo->keysym; if (keysym == lastkeysym) buffer[0] = lastchar; else buffer[0] = 0; buffer[1] = 0; if (curinfo->dispatch) { if (MCtracewindow == DNULL || hwnd != (HWND)MCtracewindow->handle.window) { MCeventtime = GetMessageTime(); //krevent->time; MCdispatcher->wkup(dw, buffer, keysym); curinfo->handled = curinfo->reset = True; } } else { MCEventnode *tptr = new MCEventnode(hwnd, msg, wParam, lParam, 0, MCmodifierstate, MCeventtime); pms->appendevent(tptr); } } break; case WM_IME_STARTCOMPOSITION: if (!MCinlineinput) return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); break; case WM_IME_ENDCOMPOSITION: if (!MCinlineinput) return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); break; case WM_IME_CHAR: { if (!MCactivefield) break; uint2 unicodekey = MAXUINT2; uint4 destlen; if (IsWindowUnicode(hwnd)) { unicodekey = wParam; destlen = 2; } else { char multibytechar[3]; multibytechar[0] = HIBYTE((WORD)wParam) ; multibytechar[1] = LOBYTE((WORD)wParam) ; multibytechar[2] = '\0'; MCU_multibytetounicode(multibytechar, 2, (char *)&unicodekey, 2, destlen, MCS_langidtocharset(LOWORD(GetKeyboardLayout(0)))); } MCString unicodestr; unicodestr.set((char *)&unicodekey, destlen); // MW-2012-02-03: [[ Unicode Block ]] Use the new finsert method to insert // text in unicode mode. MCactivefield->finsertnew(FT_IMEINSERT, unicodestr, 0, true); } break; case WM_IME_COMPOSITION: { if (!MCinlineinput) return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); if (!MCactivefield) break; DWORD dwindex = 0; if (lParam & GCS_RESULTSTR) { MCactivefield->stopcomposition(True,False); dwindex = GCS_RESULTSTR; } else if (lParam & GCS_COMPSTR) { MCactivefield->startcomposition(); dwindex = GCS_COMPSTR; } HIMC hIMC = ImmGetContext(hwnd); if (!hIMC || !dwindex) break; int2 cursorpos = LOWORD(ImmGetCompositionStringA(hIMC, GCS_CURSORPOS, NULL, 0)); MCactivefield->setcompositioncursoroffset(cursorpos << 1); uint2 compstrsize = 0; char *compstring = NULL; compstrsize = (uint2)ImmGetCompositionStringW(hIMC, dwindex, NULL, 0); compstring = new char[compstrsize+sizeof(WCHAR)]; ImmGetCompositionStringW(hIMC, dwindex, compstring, compstrsize); MCString unicodestr(compstring, compstrsize); // MW-2012-02-03: [[ Unicode Block ]] Use the new finsert method to insert // text in unicode mode. MCactivefield->finsertnew(FT_IMEINSERT, unicodestr, 0, true); delete compstring; ImmReleaseContext(hwnd, hIMC); } break; case WM_IME_NOTIFY: //sent when IME opens windows switch (wParam) { case IMN_OPENCANDIDATE: { HIMC hIMC = ImmGetContext(hwnd); DWORD imeprop = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY); if (imeprop & IME_PROP_AT_CARET) { if (MCactivefield) { uint1 i; for (i = 0; i < 4; i++) { MCRectangle r; CANDIDATEFORM cdf; cdf.dwIndex = i; cdf.dwStyle = CFS_CANDIDATEPOS; MCactivefield->getcompositionrect(r, -1); cdf.ptCurrentPos.x = r.x; cdf.ptCurrentPos.y = r.y + r.height + 32; cdf.rcArea.right = 1; cdf.rcArea.left = r.x; cdf.rcArea.top = r.y + r.height + 32; cdf.rcArea.bottom = 1; ImmSetCandidateWindow(hIMC, &cdf); } } } } break; case IMN_SETOPENSTATUS: { COMPOSITIONFORM cpf; HIMC hIMC = ImmGetContext(hwnd); cpf.dwStyle = CFS_DEFAULT; cpf.ptCurrentPos.x = 0; cpf.ptCurrentPos.y = 0; ImmSetCompositionWindow(hIMC, &cpf); ImmReleaseContext(hwnd, hIMC); } break; } return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); break; case WM_SETCURSOR: if (curinfo->live && !pms->isgrabbed() && LOWORD(lParam) != HTCLIENT) return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); MCmousestackptr = MCdispatcher->findstackd(dw); if (MCmousestackptr != NULL) { MCmousestackptr->resetcursor(True); if (pms->getmousetimer() == 0) pms->setmousetimer(timeSetEvent(LEAVE_CHECK_INTERVAL, 100, mouseproc, 0, TIME_ONESHOT)); } if (omousestack != MCmousestackptr) { if (omousestack != NULL && omousestack != MCtracestackptr) omousestack->munfocus(); if (MCmousestackptr != NULL && MCmousestackptr != MCtracestackptr) MCmousestackptr->enter(); } break; case WM_CAPTURECHANGED: if (curinfo->live) { if (pms->isgrabbed()) { MCStack *sptr = MCdispatcher->findstackd(dw); if (sptr != NULL) { if (lastdown != 0) sptr->mup(lastdown); buffer[0] = 0x1B; // escape buffer[1] = '\0'; Boolean oldlock = MClockmessages; MClockmessages = True; sptr->kdown(buffer, XK_Escape); sptr->kup(buffer, XK_Escape); MClockmessages = oldlock; sptr->munfocus(); pms->setgrabbed(False); curinfo->handled = True; } capturehwnd = NULL; } } break; case WM_MOUSEMOVE: //MotionNotify: case WM_NCMOUSEMOVE: // IM-2013-09-23: [[ FullscreenMode ]] Update mouseloc with MCscreen getters & setters MCStack *t_old_mousestack; MCPoint t_old_mouseloc; MCscreen->getmouseloc(t_old_mousestack, t_old_mouseloc); if (t_old_mouseloc.x != t_mouseloc.x || t_old_mouseloc.y != t_mouseloc.y) { MCscreen->setmouseloc(t_old_mousestack, t_mouseloc); if (curinfo->dispatch) { if (msg != WM_NCMOUSEMOVE) MCscreen->setmouseloc(MCdispatcher->findstackd(dw), t_mouseloc); if (MCtracewindow == DNULL || hwnd != (HWND)MCtracewindow->handle.window) { if (t_old_mousestack != NULL && MCmousestackptr != t_old_mousestack) t_old_mousestack->munfocus(); if (msg == WM_MOUSEMOVE) { MCPoint t_clickloc; MCStack *t_stackptr; MCscreen->getclickloc(t_stackptr, t_clickloc); MCdispatcher->wmfocus(dw, t_mouseloc.x, t_mouseloc.y); if (capturehwnd != NULL && MCbuttonstate != 0 && !dragclick && (MCU_abs(t_mouseloc.x - t_clickloc.x) >= MCdragdelta || MCU_abs(t_mouseloc.y - t_clickloc.y) >= MCdragdelta)) { dragclick = True; MCdispatcher -> wmdrag(dw); } } else if (MCmousestackptr != NULL) MCmousestackptr->munfocus(); curinfo->handled = True; } } else { MCEventnode *tptr = new MCEventnode(hwnd, msg, wParam, lParam, 0, MCmodifierstate, MCeventtime); pms->appendevent(tptr); } } if (msg == WM_NCMOUSEMOVE) return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); break; case WM_APP: if (MCmousestackptr != NULL && MCdispatcher->getmenu() == NULL) { POINT p; if (!GetCursorPos(&p) || !MCU_point_in_rect(MCmousestackptr->getrect(), (int2)p.x, (int2)p.y)) { if (MCmousestackptr != MCtracestackptr) MCmousestackptr->munfocus(); } else pms->setmousetimer(timeSetEvent(LEAVE_CHECK_INTERVAL, 100, mouseproc, 0, TIME_ONESHOT)); } curinfo->handled = True; break; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP || msg == WM_LBUTTONDBLCLK) button = 1; else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP || msg == WM_MBUTTONDBLCLK) button = 2; else button = 3; if (msg == WM_LBUTTONUP || msg == WM_MBUTTONUP || msg == WM_RBUTTONUP) { if (curinfo->live && !pms->isgrabbed()) { ReleaseCapture(); capturehwnd = NULL; } MCbuttonstate &= ~(1L << (button - 1)); down = False; lastdown = 0; } else { if (curinfo->live && !pms->isgrabbed()) { SetCapture(hwnd); capturehwnd = hwnd; lastdown = button; } MCbuttonstate |= 1L << (button - 1); down = True; if (msg == WM_LBUTTONDBLCLK || msg == WM_MBUTTONDBLCLK || msg == WM_RBUTTONDBLCLK) doubledown = True; } if (curinfo->dispatch) { if (MCtracewindow == DNULL || hwnd != (HWND)MCtracewindow->handle.window) if (down) if (doubledown) MCdispatcher->wdoubledown(dw, button); else { if (doubleclick && MCeventtime - clicktime < MCdoubletime && MCU_abs(MCclicklocx - t_mouseloc.x) < MCdoubledelta && MCU_abs(MCclicklocy - t_mouseloc.y) < MCdoubledelta) tripleclick = True; else tripleclick = False; doubleclick = False; // IM-2013-09-23: [[ FullscreenMode ]] Update clickloc with MCscreen getters & setters MCscreen->setclickloc(MCmousestackptr, t_mouseloc); dragclick = False; MCdispatcher->wmfocus(dw, t_mouseloc.x, t_mouseloc.y); MCdispatcher->wmdown(dw, button); } else { if (doubledown) { doubledown = False; doubleclick = True; clicktime = MCeventtime; MCdispatcher->wdoubleup(dw, button); } else MCdispatcher->wmup(dw, button); } curinfo->handled = curinfo->reset = True; } else { MCEventnode *tptr = new MCEventnode(hwnd, msg, wParam, lParam, 0, MCmodifierstate, MCeventtime); pms->appendevent(tptr); } break; case WM_SIZE: { MCStack *target = MCdispatcher->findstackd(dw); if (target != NULL) { if (wParam == SIZE_MINIMIZED) target->iconify(); else if (target->isiconic()) { MCstacks->restack(target); target->view_configure(true); target->uniconify(); SetWindowPos((HWND)target -> getwindow() -> handle . window, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); } else target->view_configure(true); curinfo->handled = True; } } break; case WM_MOVE: MCdispatcher->configure(dw); curinfo->handled = True; break; case WM_CLOSE: MCdispatcher->wclose(dw); curinfo->handled = True; break; case WM_GETMINMAXINFO: target = MCdispatcher->findstackd(dw); if (target != NULL) target->constrain(lParam); break; case WM_ERASEBKGND: break; case WM_TIMER: curinfo->handled = True; if (MCmousestackptr != NULL && MCdispatcher->getmenu() == NULL) { int2 x, y; pms->querymouse(x, y); MCRectangle rect; if (pms->getwindowgeometry(MCmousestackptr->getw(), rect) && capturehwnd == NULL && !pms->getgrabbed() && !MCU_point_in_rect(rect, x, y)) { MCmousestackptr->munfocus(); MCmousestackptr = NULL; } } break; case WM_CANCELMODE: if (pms->isgrabbed()) { buffer[0] = 0x1B; buffer[1] = '\0'; Boolean oldlock = MClockmessages; MClockmessages = True; MCdispatcher->wkdown(dw, buffer, XK_Escape); MCdispatcher->wkup(dw, buffer, XK_Escape); MClockmessages = oldlock; curinfo->handled = True; pms->setgrabbed(False); MCmousex = MCmousey = -1; // prevent button msg from reopening menu MCdispatcher->wmfocus(dw, MCmousex, MCmousey); } break; case MM_MCINOTIFY: if (wParam == MCI_NOTIFY_SUCCESSFUL) { MCPlayer *tptr = MCplayers; while (tptr != NULL) { if (lParam == (LPARAM)tptr->getDeviceID()) { if (tptr->isdisposable()) tptr->playstop(); else tptr->message_with_args(MCM_play_stopped, tptr->getname()); break; } tptr = tptr->getnextplayer(); } curinfo->handled = True; } break; case WM_USER: { uint2 i; for (i = 0 ; i < MCnsockets ; i++) { if (MCsockets[i]->fd == 0) MCsockets[i]->readsome(); if (wParam == MCsockets[i]->fd && !MCsockets[i]->shared) break; } if (i < MCnsockets) { if (WSAGETSELECTERROR(lParam)) { MCsockets[i]->error = new char[16 + I4L]; sprintf(MCsockets[i]->error, "Error %d on socket", WSAGETSELECTERROR(lParam)); MCsockets[i]->doclose(); } else { /* I.M * TODO - look in to this further: * we sometimes get FD_READ, but there's no data ready to read * so trying to read when using SSL results in us getting stuck * in SSTATE_RETRYREAD, which won't be cleared until data is * available to read. As a quick fix, we can check the socket with select() */ int t_events = 0; TIMEVAL t_time = {0,0}; fd_set rmaskfd, wmaskfd, emaskfd; FD_ZERO(&rmaskfd); FD_ZERO(&wmaskfd); FD_ZERO(&emaskfd); FD_SET(wParam, &rmaskfd); FD_SET(wParam, &emaskfd); select(0, &rmaskfd, &wmaskfd, &emaskfd, &t_time); if (FD_ISSET(wParam, &emaskfd)) t_events = t_events; if (FD_ISSET(wParam, &rmaskfd)) t_events |= FD_READ; if (FD_ISSET(wParam, &wmaskfd)) t_events |= FD_WRITE; switch (WSAGETSELECTEVENT(lParam)) { case FD_OOB: // bogus, from MCS_read_socket case FD_READ: if (t_events & FD_READ) MCsockets[i]->readsome(); break; case FD_WRITE: MCsockets[i]->writesome(); MCsockets[i]->setselect(); break; case FD_CONNECT: MCsockets[i]->writesome(); MCsockets[i]->readsome(); MCsockets[i]->setselect(); break; case FD_ACCEPT: MCsockets[i]->acceptone(); break; case FD_CLOSE: MCsockets[i]->readsome(); #ifdef MCSSL if (MCsockets[i]->fd != 0 && !MCsockets[i]->secure) #else if (MCsockets[i]->fd != 0) #endif MCsockets[i]->doclose(); break; } } } curinfo->handled = True; break; } case WM_WINDOWPOSCHANGING: { ((MCScreenDC *)MCscreen) -> restackwindows(hwnd, msg, wParam, lParam); // return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); } break; case WM_POWERBROADCAST: MCS_reset_time(); return TRUE; case WM_THEMECHANGED: case WM_SYSCOLORCHANGE: if (hwnd == pms->getinvisiblewindow() && MCcurtheme && MCcurtheme->getthemeid() == LF_NATIVEWIN) { MCcurtheme->unload(); MCcurtheme->load(); // MW-2011-08-17: [[ Redraw ]] The theme has changed so redraw everything. MCRedrawDirtyScreen(); } break; case WM_ACTIVATEAPP: if (wParam != isactive) { MCstacks->hidepalettes(!wParam); ((MCScreenDC *)MCscreen) -> hidebackdrop(!wParam); if (MCdefaultstackptr != NULL) MCdefaultstackptr->getcard()->message(wParam ? MCM_resume : MCM_suspend); isactive = wParam; if (!wParam) { if (pms->taskbarhidden) { //we are suspended, show menu bar for other process pms->showtaskbar(); pms->taskbarhidden = True; } } else { if (pms->taskbarhidden) { pms->taskbarhidden = False; pms->hidetaskbar(); } } } break; case WM_INPUTLANGCHANGE: { LCID t_locale_id; t_locale_id = MAKELCID(lParam, SORT_DEFAULT); char t_info[8]; GetLocaleInfoA(t_locale_id, LOCALE_IDEFAULTANSICODEPAGE, t_info, 8); ((MCScreenDC *)MCscreen) -> input_codepage = atoi(t_info); ((MCScreenDC *)MCscreen) -> system_codepage = GetACP(); } break; case WM_NCACTIVATE: if (MCactivatepalettes && wParam == FALSE && MCstacks->getactive()) { MCStack *sptr = MCdispatcher->findstackd(dw); if (sptr != NULL && sptr->getmode() == WM_PALETTE) wParam = TRUE; } return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); case WM_MOUSEWHEEL: case WM_MOUSEHWHEEL: if (MCmousestackptr != NULL) { MCObject *mfocused = MCmousestackptr->getcard()->getmfocused(); if (mfocused == NULL) mfocused = MCmousestackptr -> getcard(); if (mfocused != NULL) { int4 val = (short)HIWORD(wParam); if (msg == WM_MOUSEWHEEL) { if (val < 0) mfocused->kdown("", XK_WheelUp); else mfocused->kdown("", XK_WheelDown); } else if (msg == WM_MOUSEHWHEEL) { if (val < 0) mfocused->kdown("", XK_WheelLeft); else mfocused->kdown("", XK_WheelRight); } } } break; default: return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam); } return 0; }
IO_stat MCDispatch::dosavestack(MCStack *sptr, const MCString &fname) { if (MCModeCheckSaveStack(sptr, fname) != IO_NORMAL) return IO_ERROR; char *linkname; if (fname.getlength() != 0) linkname = fname.clone(); else if ((linkname = strclone(sptr->getfilename())) == NULL) { MCresult->sets("stack does not have a filename"); return IO_ERROR; } if (linkname == NULL) { MCresult->sets("can't open stack file, bad path"); return IO_ERROR; } if (MCS_noperm(linkname)) { MCresult->sets("can't open stack file, no permission"); delete linkname; return IO_ERROR; } char *oldfiletype = MCfiletype; MCfiletype = MCstackfiletype; char *backup = new char[strlen(linkname) + 2]; strcpy(backup, linkname); strcat(backup, "~"); MCS_unlink(backup); if (MCS_exists(linkname, True) && !MCS_backup(linkname, backup)) { MCresult->sets("can't open stack backup file"); MCfiletype = oldfiletype; delete linkname; delete backup; return IO_ERROR; } IO_handle stream; if ((stream = MCS_open(linkname, IO_WRITE_MODE, True, False, 0)) == NULL) { MCresult->sets("can't open stack file"); cleanup(stream, linkname, backup); MCfiletype = oldfiletype; return IO_ERROR; } MCfiletype = oldfiletype; MCString errstring = "Error writing stack (disk full?)"; // MW-2012-03-04: [[ StackFile5500 ]] Work out what header to emit, and the size. const char *t_header; uint32_t t_header_size; if (MCstackfileversion >= 5500) t_header = newheader5500, t_header_size = 8; else if (MCstackfileversion >= 2700) t_header = newheader, t_header_size = 8; else t_header = header, t_header_size = HEADERSIZE; if (IO_write(t_header, sizeof(char), t_header_size, stream) != IO_NORMAL || IO_write_uint1(CHARSET, stream) != IO_NORMAL) { MCresult->sets(errstring); cleanup(stream, linkname, backup); return IO_ERROR; } if (IO_write_uint1(OT_NOTHOME, stream) != IO_NORMAL || IO_write_string(NULL, stream) != IO_NORMAL) { // was stackfiles MCresult->sets(errstring); cleanup(stream, linkname, backup); return IO_ERROR; } // MW-2012-02-22; [[ NoScrollSave ]] Adjust the rect by the current group offset. MCgroupedobjectoffset . x = 0; MCgroupedobjectoffset . y = 0; MCresult -> clear(); if (sptr->save(stream, 0, false) != IO_NORMAL || IO_write_uint1(OT_END, stream) != IO_NORMAL) { if (MCresult -> isclear()) MCresult->sets(errstring); cleanup(stream, linkname, backup); return IO_ERROR; } MCS_close(stream); uint2 oldmask = MCS_umask(0); uint2 newmask = ~oldmask & 00777; if (oldmask & 00400) newmask &= ~00100; if (oldmask & 00040) newmask &= ~00010; if (oldmask & 00004) newmask &= ~00001; MCS_umask(oldmask); MCS_chmod(linkname, newmask); if (sptr->getfilename() != NULL && !strequal(linkname, sptr->getfilename())) MCS_copyresourcefork(sptr->getfilename(), linkname); else if (sptr -> getfilename() != NULL) MCS_copyresourcefork(backup, linkname); sptr->setfilename(linkname); if (backup != NULL) { MCS_unlink(backup); delete backup; } return IO_NORMAL; }
void MCExecPoint::concat(const MCString &two, Exec_concat ec, Boolean first) { if (format == VF_NUMBER) tos(); uint4 oldlength = svalue.getlength(); uint4 newlength = oldlength + two.getlength(); if (!first && ec != EC_NONE) newlength++; if (newlength > size) { // MW-2012-01-25: [[ Bug 9956 ]] Small optimization to improve large // concatenations. Using 'realloc' means that no copying of data is // needed in the best cases. size = newlength + EP_PAD & EP_MASK; if (svalue.getstring() != buffer) { char *newbuffer = new char[size]; memcpy(newbuffer, svalue.getstring(), oldlength); delete buffer; buffer = newbuffer; } else { char *newbuffer = (char *)realloc(buffer, size); if (newbuffer == nil) return; buffer = newbuffer; } svalue.setstring(buffer); } else if (svalue.getstring() != buffer) { memmove(buffer, svalue.getstring(), oldlength); svalue.setstring(buffer); } if (!first) switch (ec) { case EC_NONE: break; case EC_SPACE: buffer[oldlength++] = ' '; break; case EC_COMMA: buffer[oldlength++] = ','; break; case EC_NULL: buffer[oldlength++] = '\0'; break; case EC_RETURN: buffer[oldlength++] = '\n'; break; // MW-2009-06-17: Can now concatenate with tab into an EP. case EC_TAB: buffer[oldlength++] = '\t'; break; } if (two.getlength() == 1) buffer[oldlength] = two.getstring()[0]; else memcpy(&buffer[oldlength], two.getstring(), two.getlength()); svalue.setlength(newlength); format = VF_STRING; }
bool CClient::PutClient(const CMessage& Message) { if (!m_bAwayNotify && Message.GetType() == CMessage::Type::Away) { return false; } else if (!m_bAccountNotify && Message.GetType() == CMessage::Type::Account) { return false; } CMessage Msg(Message); const CIRCSock* pIRCSock = GetIRCSock(); if (pIRCSock) { if (Msg.GetType() == CMessage::Type::Numeric) { unsigned int uCode = Msg.As<CNumericMessage>().GetCode(); if (uCode == 352) { // RPL_WHOREPLY if (!m_bNamesx && pIRCSock->HasNamesx()) { // The server has NAMESX, but the client doesn't, so we need // to remove extra prefixes CString sNick = Msg.GetParam(6); if (sNick.size() > 1 && pIRCSock->IsPermChar(sNick[1])) { CString sNewNick = sNick; size_t pos = sNick.find_first_not_of(pIRCSock->GetPerms()); if (pos >= 2 && pos != CString::npos) { sNewNick = sNick[0] + sNick.substr(pos); } Msg.SetParam(6, sNewNick); } } } else if (uCode == 353) { // RPL_NAMES if ((!m_bNamesx && pIRCSock->HasNamesx()) || (!m_bUHNames && pIRCSock->HasUHNames())) { // The server has either UHNAMES or NAMESX, but the client // is missing either or both CString sNicks = Msg.GetParam(3); VCString vsNicks; sNicks.Split(" ", vsNicks, false); for (CString& sNick : vsNicks) { if (sNick.empty()) break; if (!m_bNamesx && pIRCSock->HasNamesx() && pIRCSock->IsPermChar(sNick[0])) { // The server has NAMESX, but the client doesn't, so // we just use the first perm char size_t pos = sNick.find_first_not_of(pIRCSock->GetPerms()); if (pos >= 2 && pos != CString::npos) { sNick = sNick[0] + sNick.substr(pos); } } if (!m_bUHNames && pIRCSock->HasUHNames()) { // The server has UHNAMES, but the client doesn't, // so we strip away ident and host sNick = sNick.Token(0, false, "!"); } } Msg.SetParam( 3, CString(" ").Join(vsNicks.begin(), vsNicks.end())); } } } else if (Msg.GetType() == CMessage::Type::Join) { if (!m_bExtendedJoin && pIRCSock->HasExtendedJoin()) { Msg.SetParams({Msg.As<CJoinMessage>().GetTarget()}); } } } CString sLine = Msg.ToString(CMessage::ExcludeTags); // TODO: introduce a module hook that gives control over the tags that are // sent MCString mssTags; if (HasServerTime()) { CString sServerTime = Msg.GetTag("time"); if (!sServerTime.empty()) { mssTags["time"] = sServerTime; } else { mssTags["time"] = CUtils::FormatServerTime(Msg.GetTime()); } } if (HasBatch()) { CString sBatch = Msg.GetTag("batch"); if (!sBatch.empty()) { mssTags["batch"] = sBatch; } } if (!mssTags.empty()) { CUtils::SetMessageTags(sLine, mssTags); } PutClient(sLine); return true; }
MCOldFontnode::MCOldFontnode(const MCString &fname, uint2 &size, uint2 style) { char fontname[XLFD_LENGTH]; uint4 length = fname.getlength(); reqname = new char[length + 1]; MCU_lower(reqname, fname); reqname[length] = '\0'; reqsize = size; reqstyle = style; uint2 t_original_size; t_original_size = size; XFontStruct *fs = NULL; memset(&font, 0, sizeof(MCFontStruct)); font.charset = 0; if (MCnoui) return; Boolean t_is_unicode = False; // MW-2005-02-08: We aren't going to use XMBTEXT for now, instead we will // search for an appropriate ISO10646 font if in 'encoding mode'. if (strchr(reqname, ',') != NULL) { sprintf(fontname, "-*-%.*s-%s-%s-%s--%d-*-*-*-*-*-iso10646-*", strchr(reqname, ',') - reqname, reqname, MCF_getweightstring(style), MCF_getslantshortstring(style), MCF_getexpandstring(style), size); t_is_unicode = True; } else sprintf(fontname, "-*-%s-%s-%s-%s--%d-*-*-*-*-*-iso8859-%d", reqname, MCF_getweightstring(style), MCF_getslantshortstring(style), MCF_getexpandstring(style), size, MCcharset); if ((fs = XLoadQueryFont(MCdpy, fontname)) == NULL) fs = lookup(reqname, size, style); else font.unicode = t_is_unicode; if (fs == NULL) if ((fs = XLoadQueryFont(MCdpy, reqname)) != NULL) { if (pixelsize == 0) pixelsize = XInternAtom(MCdpy, "PIXEL_SIZE", True); uint2 i = fs->n_properties; while (i--) if (fs->properties[i].name == pixelsize) { size = reqsize = fs->properties[i].card32; break; } size = reqsize = fs->ascent + fs->descent - 2; } if (fs == NULL) fs = lookup(DEFAULT_TEXT_FONT, size, style); if (fs == NULL) fs = XLoadQueryFont(MCdpy, "fixed"); font.reqname = strdup(reqname) ; font.reqsize = reqsize ; font.reqstyle = reqstyle ; font.fstruct = fs; font.max_byte1 = fs -> max_byte1; font.ascent = fs -> ascent; font.descent = fs -> descent; font.unicode = t_is_unicode; if (t_is_unicode) font.charset = LCH_UNICODE; }
bool CTemplate::Print(const CString& sFileName, ostream& oOut) { if (sFileName.empty()) { DEBUG("Empty filename in CTemplate::Print()"); return false; } CFile File(sFileName); if (!File.Open()) { DEBUG("Unable to open file [" + sFileName + "] in CTemplate::Print()"); return false; } CString sLine; CString sSetBlockVar; bool bValidLastIf = false; bool bInSetBlock = false; unsigned long uFilePos = 0; unsigned long uCurPos = 0; unsigned int uLineNum = 0; unsigned int uNestedIfs = 0; unsigned int uSkip = 0; bool bLoopCont = false; bool bLoopBreak = false; bool bExit = false; while (File.ReadLine(sLine)) { CString sOutput; bool bFoundATag = false; bool bTmplLoopHasData = false; uLineNum++; CString::size_type iPos = 0; uCurPos = uFilePos; unsigned int uLineSize = sLine.size(); bool bBroke = false; while (1) { iPos = sLine.find("<?"); if (iPos == CString::npos) { break; } uCurPos += iPos; bFoundATag = true; if (!uSkip) { sOutput += sLine.substr(0, iPos); } sLine = sLine.substr(iPos +2); CString::size_type iPos2 = sLine.find("?>"); // Make sure our tmpl tag is ended properly if (iPos2 == CString::npos) { DEBUG("Template tag not ended properly in file [" + sFileName + "] [<?" + sLine + "]"); return false; } uCurPos += iPos2 +4; CString sMid = CString(sLine.substr(0, iPos2)).Trim_n(); // Make sure we don't have a nested tag if (sMid.find("<?") == CString::npos) { sLine = sLine.substr(iPos2 +2); CString sAction = sMid.Token(0); CString sArgs = sMid.Token(1, true); bool bNotFound = false; // If we're breaking or continuing from within a loop, skip all tags that aren't ENDLOOP if ((bLoopCont || bLoopBreak) && !sAction.Equals("ENDLOOP")) { continue; } if (!uSkip) { if (sAction.Equals("INC")) { if (!Print(ExpandFile(sArgs, true), oOut)) { DEBUG("Unable to print INC'd file [" + sArgs + "]"); return false; } } else if (sAction.Equals("SETOPTION")) { m_spOptions->Parse(sArgs); } else if (sAction.Equals("ADDROW")) { CString sLoopName = sArgs.Token(0); MCString msRow; if (sArgs.Token(1, true, " ").OptionSplit(msRow)) { CTemplate& NewRow = AddRow(sLoopName); for (MCString::iterator it = msRow.begin(); it != msRow.end(); ++it) { NewRow[it->first] = it->second; } } } else if (sAction.Equals("SET")) { CString sName = sArgs.Token(0); CString sValue = sArgs.Token(1, true); (*this)[sName] = sValue; } else if (sAction.Equals("JOIN")) { VCString vsArgs; //sArgs.Split(" ", vsArgs, false, "\"", "\""); sArgs.QuoteSplit(vsArgs); if (vsArgs.size() > 1) { CString sDelim = vsArgs[0]; bool bFoundOne = false; CString::EEscape eEscape = CString::EASCII; for (unsigned int a = 1; a < vsArgs.size(); a++) { const CString& sArg = vsArgs[a]; if (sArg.Equals("ESC=", false, 4)) { eEscape = CString::ToEscape(sArg.LeftChomp_n(4)); } else { CString sValue = GetValue(sArg); if (!sValue.empty()) { if (bFoundOne) { sOutput += sDelim; } sOutput += sValue.Escape_n(eEscape); bFoundOne = true; } } } } } else if (sAction.Equals("SETBLOCK")) { sSetBlockVar = sArgs; bInSetBlock = true; } else if (sAction.Equals("EXPAND")) { sOutput += ExpandFile(sArgs, true); } else if (sAction.Equals("VAR")) { sOutput += GetValue(sArgs); } else if (sAction.Equals("LT")) { sOutput += "<?"; } else if (sAction.Equals("GT")) { sOutput += "?>"; } else if (sAction.Equals("CONTINUE")) { CTemplateLoopContext* pContext = GetCurLoopContext(); if (pContext) { uSkip++; bLoopCont = true; break; } else { DEBUG("[" + sFileName + ":" + CString(uCurPos - iPos2 -4) + "] <? CONTINUE ?> must be used inside of a loop!"); } } else if (sAction.Equals("BREAK")) { // break from loop CTemplateLoopContext* pContext = GetCurLoopContext(); if (pContext) { uSkip++; bLoopBreak = true; break; } else { DEBUG("[" + sFileName + ":" + CString(uCurPos - iPos2 -4) + "] <? BREAK ?> must be used inside of a loop!"); } } else if (sAction.Equals("EXIT")) { bExit = true; } else if (sAction.Equals("DEBUG")) { DEBUG("CTemplate DEBUG [" + sFileName + "@" + CString(uCurPos - iPos2 -4) + "b] -> [" + sArgs + "]"); } else if (sAction.Equals("LOOP")) { CTemplateLoopContext* pContext = GetCurLoopContext(); if (!pContext || pContext->GetFilePosition() != uCurPos) { // we are at a brand new loop (be it new or a first pass at an inner loop) CString sLoopName = sArgs.Token(0); bool bReverse = (sArgs.Token(1).Equals("REVERSE")); bool bSort = (sArgs.Token(1).Left(4).Equals("SORT")); vector<CTemplate*>* pvLoop = GetLoop(sLoopName); if (bSort && pvLoop != NULL && pvLoop->size() > 1) { CString sKey; if(sArgs.Token(1).TrimPrefix_n("SORT").Left(4).Equals("ASC=")) { sKey = sArgs.Token(1).TrimPrefix_n("SORTASC="); } else if(sArgs.Token(1).TrimPrefix_n("SORT").Left(5).Equals("DESC=")) { sKey = sArgs.Token(1).TrimPrefix_n("SORTDESC="); bReverse = true; } if (!sKey.empty()) { std::sort(pvLoop->begin(), pvLoop->end(), CLoopSorter(sKey)); } } if (pvLoop) { // If we found data for this loop, add it to our context vector //unsigned long uBeforeLoopTag = uCurPos - iPos2 - 4; unsigned long uAfterLoopTag = uCurPos; for (CString::size_type t = 0; t < sLine.size(); t++) { char c = sLine[t]; if (c == '\r' || c == '\n') { uAfterLoopTag++; } else { break; } } m_vLoopContexts.push_back(new CTemplateLoopContext(uAfterLoopTag, sLoopName, bReverse, pvLoop)); } else { // If we don't have data, just skip this loop and everything inside uSkip++; } } } else if (sAction.Equals("IF")) { if (ValidIf(sArgs)) { uNestedIfs++; bValidLastIf = true; } else { uSkip++; bValidLastIf = false; } } else if (sAction.Equals("REM")) { uSkip++; } else { bNotFound = true; } } else if (sAction.Equals("REM")) { uSkip++; } else if (sAction.Equals("IF")) { uSkip++; } else if (sAction.Equals("LOOP")) { uSkip++; } if (sAction.Equals("ENDIF")) { if (uSkip) { uSkip--; } else { uNestedIfs--; } } else if (sAction.Equals("ENDREM")) { if (uSkip) { uSkip--; } } else if (sAction.Equals("ENDSETBLOCK")) { bInSetBlock = false; sSetBlockVar = ""; } else if (sAction.Equals("ENDLOOP")) { if (bLoopCont && uSkip == 1) { uSkip--; bLoopCont = false; } if (bLoopBreak && uSkip == 1) { uSkip--; } if (uSkip) { uSkip--; } else { // We are at the end of the loop so we need to inc the index CTemplateLoopContext* pContext = GetCurLoopContext(); if (pContext) { pContext->IncRowIndex(); // If we didn't go out of bounds we need to seek back to the top of our loop if (!bLoopBreak && pContext->GetCurRow()) { uCurPos = pContext->GetFilePosition(); uFilePos = uCurPos; uLineSize = 0; File.Seek(uCurPos); bBroke = true; if (!sOutput.Trim_n().empty()) { pContext->SetHasData(); } break; } else { if (sOutput.Trim_n().empty()) { sOutput.clear(); } bTmplLoopHasData = pContext->HasData(); DelCurLoopContext(); bLoopBreak = false; } } } } else if (sAction.Equals("ELSE")) { if (!bValidLastIf && uSkip == 1) { CString sArg = sArgs.Token(0); if (sArg.empty() || (sArg.Equals("IF") && ValidIf(sArgs.Token(1, true)))) { uSkip = 0; bValidLastIf = true; } } else if (!uSkip) { uSkip = 1; } } else if (bNotFound) { // Unknown tag that isn't being skipped... vector<CSmartPtr<CTemplateTagHandler> >& vspTagHandlers = GetTagHandlers(); if (!vspTagHandlers.empty()) { // @todo this should go up to the top to grab handlers CTemplate* pTmpl = GetCurTemplate(); CString sCustomOutput; for (unsigned int j = 0; j < vspTagHandlers.size(); j++) { CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j]; if (spTagHandler->HandleTag(*pTmpl, sAction, sArgs, sCustomOutput)) { sOutput += sCustomOutput; bNotFound = false; break; } } if (bNotFound) { DEBUG("Unknown/Unhandled tag [" + sAction + "]"); } } } continue; } DEBUG("Malformed tag on line " + CString(uLineNum) + " of [" << File.GetLongName() + "]"); DEBUG("--------------- [" + sLine + "]"); } if (!bBroke) { uFilePos += uLineSize; if (!uSkip) { sOutput += sLine; } } if (!bFoundATag || bTmplLoopHasData || sOutput.find_first_not_of(" \t\r\n") != CString::npos) { if (bInSetBlock) { CString sName = sSetBlockVar.Token(0); //CString sValue = sSetBlockVar.Token(1, true); (*this)[sName] += sOutput; } else { oOut << sOutput; } } if (bExit) { break; } } oOut.flush(); return true; }
Exec_stat MCF_parsetextatts(Properties which, const MCString &data, uint4 &flags, char *&fname, uint2 &height, uint2 &size, uint2 &style) { int2 i1; switch (which) { case P_TEXT_ALIGN: flags &= ~F_ALIGNMENT; if (data == MCleftstring || data.getlength() == 0) flags |= F_ALIGN_LEFT; else if (data == MCcenterstring) flags |= F_ALIGN_CENTER; else if (data == MCrightstring) flags |= F_ALIGN_RIGHT; else if (data == MCjustifystring) flags |= F_ALIGN_JUSTIFY; else { MCeerror->add(EE_OBJECT_BADALIGN, 0, 0, data); return ES_ERROR; } break; case P_TEXT_FONT: { fname = data.clone(); // MW-2012-02-17: [[ IntrinsicUnicode ]] Strip any lang tag from the // fontname. char *t_tag; t_tag = strchr(fname, ','); if (t_tag != nil) t_tag[0] = '\0'; } break; case P_TEXT_HEIGHT: if (!MCU_stoi2(data, i1)) { MCeerror->add (EE_OBJECT_TEXTHEIGHTNAN, 0, 0, data); return ES_ERROR; } height = i1; break; case P_TEXT_SIZE: if (data.getlength() == 0) i1 = 0; else if (!MCU_stoi2(data, i1)) { MCeerror->add (EE_OBJECT_TEXTSIZENAN, 0, 0, data); return ES_ERROR; } size = i1; break; case P_TEXT_STYLE: { // MW-2012-02-17: [[ SplitTextAttrs ]] If the string is empty, then // return 0 for the style - indicating to unset the property. uint4 l = data.getlength(); const char *sptr = data.getstring(); if (l == 0) style = 0; else { style = FA_DEFAULT_STYLE; while (l) { const char *startptr = sptr; if (!MCU_strchr(sptr, l, ',')) { sptr += l; l = 0; } MCString tdata(startptr, sptr - startptr); MCU_skip_char(sptr, l); MCU_skip_spaces(sptr, l); if (MCF_setweightstring(style, tdata)) continue; if (MCF_setexpandstring(style, tdata)) continue; if (MCF_setslantlongstring(style, tdata)) continue; if (tdata == MCplainstring) { style = FA_DEFAULT_STYLE; continue; } if (tdata == MCmixedstring) { style = FA_DEFAULT_STYLE; continue; } if (tdata == MCboxstring) { style &= ~FA_3D_BOX; style |= FA_BOX; continue; } if (tdata == MCthreedboxstring) { style &= ~FA_BOX; style |= FA_3D_BOX; continue; } if (tdata == MCunderlinestring) { style |= FA_UNDERLINE; continue; } if (tdata == MCstrikeoutstring) { style |= FA_STRIKEOUT; continue; } if (tdata == MCgroupstring || tdata == MClinkstring) { style |= FA_LINK; continue; } MCeerror->add(EE_OBJECT_BADSTYLE, 0, 0, data); return ES_ERROR; } } } break; default: break; } return ES_NORMAL; }
EModRet HandleMessage(const CNick& Nick, CString sMessage) { if (!Nick.NickEquals("Q") || !Nick.GetHost().Equals("CServe.quakenet.org")) return CONTINUE; sMessage.Trim(); #if Q_DEBUG_COMMUNICATION PutModule("[ZNC <-- Q] " + sMessage); #endif // WHOAMI if (sMessage.find("WHOAMI is only available to authed users") != CString::npos) { m_bAuthed = false; Auth(); m_bCatchResponse = m_bRequestedWhoami; } else if (sMessage.find("Information for user") != CString::npos) { m_bAuthed = true; m_msChanModes.clear(); m_bCatchResponse = m_bRequestedWhoami; m_bRequestedWhoami = true; } else if (m_bRequestedWhoami && sMessage.WildCmp("#*")) { CString sChannel = sMessage.Token(0); CString sFlags = sMessage.Token(1, true).Trim_n().TrimLeft_n("+"); m_msChanModes[sChannel] = sFlags; } else if (m_bRequestedWhoami && m_bCatchResponse && (sMessage.Equals("End of list.") || sMessage.Equals( "account, or HELLO to create an account."))) { m_bRequestedWhoami = m_bCatchResponse = false; return HALT; } // AUTH else if (sMessage.Equals("Username or password incorrect.")) { m_bAuthed = false; PutModule("Auth failed: " + sMessage); return HALT; } else if (sMessage.WildCmp("You are now logged in as *.")) { m_bAuthed = true; PutModule("Auth successful: " + sMessage); WhoAmI(); return HALT; } else if (m_bRequestedChallenge && sMessage.Token(0).Equals("CHALLENGE")) { m_bRequestedChallenge = false; if (sMessage.find("not available once you have authed") != CString::npos) { m_bAuthed = true; } else { if (sMessage.find("HMAC-SHA-256") != CString::npos) { ChallengeAuth(sMessage.Token(1)); } else { PutModule( "Auth failed: Q does not support HMAC-SHA-256 for " "CHALLENGEAUTH, falling back to standard AUTH."); SetUseChallenge(false); Auth(); } } return HALT; } // prevent buffering of Q's responses return !m_bCatchResponse && GetUser()->IsUserAttached() ? CONTINUE : HALT; }
void SendSkypeMsgToIRC(const CReceivedSkypeMsg *a_msg) { CString l_msgBuffer; if(a_msg->timestamp < time(0) - 120 && !a_msg->edited) { char l_timeBuf[100]; strftime(l_timeBuf, 100, "[%a %H:%M:%S] ", localtime(&a_msg->timestamp)); l_msgBuffer = l_timeBuf; } if(!a_msg->edited) { if(a_msg->type == "EMOTED") { l_msgBuffer += a_msg->fromDispname + " "; } else { l_msgBuffer += "<" + a_msg->fromDispname + "> "; } l_msgBuffer += a_msg->body; } else { char l_timeBuf[100]; strftime(l_timeBuf, 100, "%H:%M:%S", localtime(&a_msg->timestamp)); if(a_msg->body == "[deleted]") { l_msgBuffer += "(" + a_msg->fromDispname + " deleted their message from " + CString(l_timeBuf) + ")"; } else { l_msgBuffer += a_msg->fromDispname + " edited their message from " + CString(l_timeBuf) + ": " + a_msg->body; } } l_msgBuffer.Replace("\r", ""); l_msgBuffer.Replace("\n", " "); for(MCString::iterator it = m_chanNameMap.begin(); it != m_chanNameMap.end(); it++) { if(it->second.Equals(a_msg->chatName)) { std::wstring l_buffer = Utf8ToWide(l_msgBuffer); std::wstring l_line; CString l_utfLine; do { l_line = l_buffer.substr(0, 400); l_buffer.erase(0, 400); if(!l_buffer.empty()) { l_line += L"..."; l_buffer = L"..." + l_buffer; } l_utfLine = WideToUtf8(l_line); PutIRC("PRIVMSG " + it->first + " :" + l_utfLine); PutUser(":" + m_pUser->GetIRCNick().GetNick() + "!x@y PRIVMSG " + it->first + " :" + l_utfLine); } while(!l_buffer.empty()); return; } } PutModule("WARNING: Group chat " + a_msg->chatName + " not mapped to any channel. A message has been lost."); }
CString CTemplate::GetValue(const CString& sArgs, bool bFromIf) { CTemplateLoopContext* pContext = GetCurLoopContext(); CString sName = sArgs.Token(0); CString sRest = sArgs.Token(1, true); CString sRet; while (sRest.Replace(" =", "=", "\"", "\"")) {} while (sRest.Replace("= ", "=", "\"", "\"")) {} VCString vArgs; MCString msArgs; //sRest.Split(" ", vArgs, false, "\"", "\""); sRest.QuoteSplit(vArgs); for (unsigned int a = 0; a < vArgs.size(); a++) { const CString& sArg = vArgs[a]; msArgs[sArg.Token(0, false, "=").AsUpper()] = sArg.Token(1, true, "="); } /* We have no CConfig in ZNC land * Hmm... Actually, we do have it now. if (msArgs.find("CONFIG") != msArgs.end()) { sRet = CConfig::GetValue(sName); } else*/ if (msArgs.find("ROWS") != msArgs.end()) { vector<CTemplate*>* pLoop = GetLoop(sName); sRet = CString((pLoop) ? pLoop->size() : 0); } else if (msArgs.find("TOP") == msArgs.end() && pContext) { sRet = pContext->GetValue(sArgs, bFromIf); if (!sRet.empty()) { return sRet; } } else { if (sName.Left(1) == "*") { sName.LeftChomp(1); MCString::iterator it = find(sName); sName = (it != end()) ? it->second : ""; } MCString::iterator it = find(sName); sRet = (it != end()) ? it->second : ""; } vector<CSmartPtr<CTemplateTagHandler> >& vspTagHandlers = GetTagHandlers(); if (!vspTagHandlers.empty()) { // @todo this should go up to the top to grab handlers CTemplate* pTmpl = GetCurTemplate(); if (sRet.empty()) { for (unsigned int j = 0; j < vspTagHandlers.size(); j++) { CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j]; CString sCustomOutput; if (!bFromIf && spTagHandler->HandleVar(*pTmpl, sArgs.Token(0), sArgs.Token(1, true), sCustomOutput)) { sRet = sCustomOutput; break; } else if (bFromIf && spTagHandler->HandleIf(*pTmpl, sArgs.Token(0), sArgs.Token(1, true), sCustomOutput)) { sRet = sCustomOutput; break; } } } for (unsigned int j = 0; j < vspTagHandlers.size(); j++) { CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j]; if (spTagHandler->HandleValue(*pTmpl, sRet, msArgs)) { break; } } } if (!bFromIf) { if (sRet.empty()) { sRet = ResolveLiteral(msArgs["DEFAULT"]); } MCString::iterator it = msArgs.find("ESC"); if (it != msArgs.end()) { VCString vsEscs; it->second.Split(",", vsEscs, false); for (unsigned int a = 0; a < vsEscs.size(); a++) { sRet.Escape(CString::ToEscape(vsEscs[a])); } } else { sRet.Escape(m_spOptions->GetEscapeFrom(), m_spOptions->GetEscapeTo()); } } return sRet; }
TEST(IRC32, GetMessageTags) { EXPECT_EQ(MCString(), CUtils::GetMessageTags("")); EXPECT_EQ(MCString(), CUtils::GetMessageTags(":nick!ident@host PRIVMSG #chan :hello world")); MCString exp; exp["a"] = "b"; EXPECT_EQ(exp, CUtils::GetMessageTags("@a=b")); EXPECT_EQ(exp, CUtils::GetMessageTags("@a=b :nick!ident@host PRIVMSG #chan :hello world")); EXPECT_EQ(exp, CUtils::GetMessageTags("@a=b :rest")); exp.clear(); exp["ab"] = "cdef"; exp["znc.in/gh-ij"] = "klmn,op"; EXPECT_EQ(exp, CUtils::GetMessageTags("@ab=cdef;znc.in/gh-ij=klmn,op :rest")); exp.clear(); exp["a"] = "==b=="; EXPECT_EQ(exp, CUtils::GetMessageTags("@a===b== :rest")); exp.clear(); exp["a"] = ""; exp["b"] = "c"; exp["d"] = ""; EXPECT_EQ(exp, CUtils::GetMessageTags("@a;b=c;d :rest")); exp.clear(); exp["semi-colon"] += ';'; exp["space"] += ' '; exp["NUL"] += '\0'; exp["backslash"] += '\\'; exp["CR"] += '\r'; exp["LF"] += '\n'; EXPECT_EQ(exp, CUtils::GetMessageTags(R"(@semi-colon=\:;space=\s;NUL=\0;backslash=\\;CR=\r;LF=\n :rest)")); exp.clear(); exp["a"] = "; \\\r\n"; EXPECT_EQ(exp, CUtils::GetMessageTags(R"(@a=\:\s\\\r\n :rest)")); exp.clear(); } TEST(IRC32, SetMessageTags) { CString sLine; sLine = ":rest"; CUtils::SetMessageTags(sLine, MCString()); EXPECT_EQ(":rest", sLine); MCString tags; tags["a"] = "b"; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ("@a=b :rest", sLine); tags["c"] = "d"; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ("@a=b;c=d :rest", sLine); tags["e"] = ""; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ("@a=b;c=d;e :rest", sLine); tags.clear(); tags["semi-colon"] += ';'; tags["space"] += ' '; tags["NUL"] += '\0'; tags["backslash"] += '\\'; tags["CR"] += '\r'; tags["LF"] += '\n'; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ(R"(@CR=\r;LF=\n;NUL=\0;backslash=\\;semi-colon=\:;space=\s :rest)", sLine); tags.clear(); tags["a"] = "; \\\r\n"; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ(R"(@a=\:\s\\\r\n :rest)", sLine); }
void MCSort::additem(MCExecPoint &ep, MCSortnode *&items, uint4 &nitems, Sort_type form, MCString &s, MCExpression *by) { if (by != NULL) { MCerrorlock++; ep.setsvalue(s); MCeach->store(ep, False); if (by->eval(ep) == ES_NORMAL) s = ep.getsvalue(); else s = MCnullmcstring; MCerrorlock--; } switch (form) { case ST_DATETIME: ep.setsvalue(s); if (MCD_convert(ep, CF_UNDEFINED, CF_UNDEFINED, CF_SECONDS, CF_UNDEFINED)) { if (!MCU_stor8(ep.getsvalue(), items[nitems].nvalue)) items[nitems].nvalue = -MAXREAL8; } else items[nitems].nvalue = -MAXREAL8; break; case ST_NUMERIC: { const char *sptr = s.getstring(); uint4 length = s.getlength(); // MW-2013-03-21: [[ Bug ]] Make sure we skip any whitespace before the // number starts - making it consistent with string->number conversions // elsewhere. MCU_skip_spaces(sptr, length); // REVIEW - at the moment the numeric prefix of the string is used to // derive the sort key e.g. 1000abc would get processed as 1000. while (length && (isdigit((uint1)*sptr) || *sptr == '.' || *sptr == '-' || *sptr == '+')) { sptr++; length--; } s.setlength(s.getlength() - length); if (!MCU_stor8(s, items[nitems].nvalue)) items[nitems].nvalue = -MAXREAL8; } break; default: if (ep.getcasesensitive() && by == NULL) items[nitems].svalue = (char *)s.getstring(); else if (ep.getcasesensitive()) items[nitems].svalue = s.clone(); else { #if defined(_MAC_DESKTOP) || defined(_IOS_MOBILE) if (form == ST_INTERNATIONAL) { extern char *MCSystemLowercaseInternational(const MCString& s); items[nitems].svalue = MCSystemLowercaseInternational(s); } else #endif { items[nitems].svalue = new char[s.getlength() + 1]; MCU_lower(items[nitems].svalue, s); items[nitems].svalue[s.getlength()] = '\0'; } } break; } nitems++; }
bool CClient::PutClient(const CMessage& Message) { if (!m_bAwayNotify && Message.GetType() == CMessage::Type::Away) { return false; } else if (!m_bAccountNotify && Message.GetType() == CMessage::Type::Account) { return false; } CMessage Msg(Message); const CIRCSock* pIRCSock = GetIRCSock(); if (pIRCSock) { if (Msg.GetType() == CMessage::Type::Numeric) { unsigned int uCode = Msg.As<CNumericMessage>().GetCode(); if (uCode == 352) { // RPL_WHOREPLY if (!m_bNamesx && pIRCSock->HasNamesx()) { // The server has NAMESX, but the client doesn't, so we need // to remove extra prefixes CString sNick = Msg.GetParam(6); if (sNick.size() > 1 && pIRCSock->IsPermChar(sNick[1])) { CString sNewNick = sNick; size_t pos = sNick.find_first_not_of(pIRCSock->GetPerms()); if (pos >= 2 && pos != CString::npos) { sNewNick = sNick[0] + sNick.substr(pos); } Msg.SetParam(6, sNewNick); } } } else if (uCode == 353) { // RPL_NAMES if ((!m_bNamesx && pIRCSock->HasNamesx()) || (!m_bUHNames && pIRCSock->HasUHNames())) { // The server has either UHNAMES or NAMESX, but the client // is missing either or both CString sNicks = Msg.GetParam(3); VCString vsNicks; sNicks.Split(" ", vsNicks, false); for (CString& sNick : vsNicks) { if (sNick.empty()) break; if (!m_bNamesx && pIRCSock->HasNamesx() && pIRCSock->IsPermChar(sNick[0])) { // The server has NAMESX, but the client doesn't, so // we just use the first perm char size_t pos = sNick.find_first_not_of(pIRCSock->GetPerms()); if (pos >= 2 && pos != CString::npos) { sNick = sNick[0] + sNick.substr(pos); } } if (!m_bUHNames && pIRCSock->HasUHNames()) { // The server has UHNAMES, but the client doesn't, // so we strip away ident and host sNick = sNick.Token(0, false, "!"); } } Msg.SetParam( 3, CString(" ").Join(vsNicks.begin(), vsNicks.end())); } } } else if (Msg.GetType() == CMessage::Type::Join) { if (!m_bExtendedJoin && pIRCSock->HasExtendedJoin()) { Msg.SetParams({Msg.As<CJoinMessage>().GetTarget()}); } } } MCString mssTags; for (const auto& it : Msg.GetTags()) { if (IsTagEnabled(it.first)) { mssTags[it.first] = it.second; } } if (HasServerTime()) { // If the server didn't set the time tag, manually set it mssTags.emplace("time", CUtils::FormatServerTime(Msg.GetTime())); } Msg.SetTags(mssTags); Msg.SetClient(this); Msg.SetNetwork(m_pNetwork); bool bReturn = false; NETWORKMODULECALL(OnSendToClientMessage(Msg), m_pUser, m_pNetwork, this, &bReturn); if (bReturn) return false; return PutClientRaw(Msg.ToString()); }
Exec_stat MCEPS::setprop_legacy(uint4 parid, Properties p, MCExecPoint &ep, Boolean effective) { Boolean dirty = True; real8 n; int2 i; int2 i1, i2, i3, i4; MCString data = ep.getsvalue(); switch (p) { #ifdef /* MCEPS::setprop */ LEGACY_EXEC case P_TRAVERSAL_ON: case P_SHOW_BORDER: if (MCControl::setprop(parid, p, ep, effective) != ES_NORMAL) return ES_ERROR; resetscale(); break; case P_ANGLE: if (!MCU_stoi2(data, i)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } angle = i; break; case P_POSTSCRIPT: delete postscript; postscript = data.clone(); size = data.getlength() + 1; setextents(); resetscale(); break; case P_PROLOG: delete prolog; prolog = data.clone(); break; case P_RETAIN_IMAGE: if (!MCU_matchflags(data, flags, F_RETAIN_IMAGE, dirty)) { MCeerror->add (EE_OBJECT_NAB, 0, 0, data); return ES_ERROR; } dirty = False; break; case P_RETAIN_POSTSCRIPT: if (!MCU_matchflags(data, flags, F_RETAIN_POSTSCRIPT, dirty)) { MCeerror->add (EE_OBJECT_NAB, 0, 0, data); return ES_ERROR; } dirty = False; break; case P_SCALE_INDEPENDENTLY: if (!MCU_matchflags(data, flags, F_SCALE_INDEPENDENTLY, dirty)) { MCeerror->add (EE_OBJECT_NAB, 0, 0, data); return ES_ERROR; } if (dirty) resetscale(); break; case P_BOUNDING_RECT: if (!MCU_stoi2x4(data, i1, i2, i3, i4)) { MCeerror->add (EE_OBJECT_NAR, 0, 0, data); return ES_ERROR; } if (tx != i1 || ty != i2 || tx + ex != i3 || ty + ey != i4) { tx = i1; ty = i2; ex = MCU_max(i3 - i1, 1); ey = MCU_max(i4 - i2, 1); resetscale(); } else dirty = False; break; case P_SCALE: if (!MCU_stor8(data, n)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } xscale = yscale = n; break; case P_X_SCALE: if (!MCU_stor8(data, n)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } xscale = n; ex = (uint2)(rect.width * xf / xscale + 0.5); flags |= F_SCALE_INDEPENDENTLY; break; case P_Y_SCALE: if (!MCU_stor8(data, n)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } yscale = n; ey = (uint2)(rect.height * yf / yscale + 0.5); flags |= F_SCALE_INDEPENDENTLY; break; case P_X_OFFSET: if (!MCU_stoi2(data, i)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } tx = i; break; case P_Y_OFFSET: if (!MCU_stoi2(data, i)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } ty = i; break; case P_X_EXTENT: if (!MCU_stoi2(data, i)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } ex = i; resetscale(); break; case P_Y_EXTENT: if (!MCU_stoi2(data, i)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } ey = i; resetscale(); break; case P_CURRENT_PAGE: //set eps current page to display if (!MCU_stoi2(data, i)) { MCeerror->add (EE_OBJECT_NAN, 0, 0, data); return ES_ERROR; } if ((uint2)i > pagecount) curpage = pagecount; else curpage = i; break; #endif /* MCEPS::setprop */ default: return MCControl::setprop_legacy(parid, p, ep, effective); } if (dirty && opened) { // MW-2011-08-18: [[ Layers ]] Invalidate the whole object. layer_redrawall(); } return ES_NORMAL; }