void * List_Delete(PTList pPueue, int index) { int i = List_Index(pPueue, index); PTListItem temp; void * Result = NULL; if (pPueue != NULL) { if (i < 0) { return NULL; } else { temp = List_Get(pPueue, index); if (temp != NULL) { pPueue->length--; Result = temp->item; if (pPueue->first == temp && pPueue->last == temp) { pPueue->first = NULL; pPueue->last = NULL; } else if (pPueue->first == temp) { pPueue->first = temp->next; pPueue->first->prv = NULL; } else if (pPueue->last == temp) { pPueue->last = temp->prv; pPueue->last->next = NULL; } else { temp->prv->next = temp->next; temp->next->prv = temp->prv; } List_Item_Destroy(temp); return Result; } } } return NULL; }
CList List_Copy(CList &l, size_t from, size_t count) { from = clamp(from, 0ul, l.size); count = clamp(count, 0ul, l.size - from); CList copy = List_Create(count); for(size_t i = 0; i < count; ++i) { List_Append(copy, List_Get(l, from + i)); } return copy; }
HMENUITEM GetDefaultMenuItem(HPOPUP popup) { for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); if (item->item_style & CPM_ITEM_DEFAULT) return item; } return NULL; }
PTListItem List_Insert(PTList pPueue, void * item, int index) { int i = (index >= 0 && index <= pPueue->length) ? index : -1; PTListItem temp, Result; if (pPueue != NULL) { if (i < 0) { return NULL; } else if (i == 0) { temp = pPueue->first; Result = List_Item_Create(); Result->item = item; Result->next = pPueue->first; pPueue->first = Result; if (pPueue->length == 0) { pPueue->last = pPueue->first; } else { Result->next->prv = Result; } } else if (i == pPueue->length) { Result = List_Item_Create(); Result->item = item; Result->prv = pPueue->last; pPueue->last->next = Result; pPueue->last = Result; } else { temp = List_Get(pPueue, index); Result = List_Item_Create(); Result->item = item; Result->next = temp; Result->prv = temp->prv; Result->prv->next = Result; Result->next->prv = Result; } pPueue->length++; return Result; } return NULL; }
LRESULT CALLBACK Internal_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HPOPUP popup = (HPOPUP)GetWindowLong(hWnd, GWLP_USERDATA); switch (message) { case WM_PAINT: { HDC hdc; PAINTSTRUCT paintstruct; hdc = BeginPaint(hWnd, &paintstruct); DRAWCONTEXT context; context.paintstruct = paintstruct; context.fill_color = CLASSIC_DEFAULT_BASECOLOR; context.draw_color = 0x000000; // NOTE(toni): We can just straight up use the "right" and "bottom" // variables because the x and y position are always gonna be zero anyways. CDrawUtils::FillRectangle3D( &context, 0, 0, popup->menu_size.cx, popup->menu_size.cy, RECT_RAISED ); // Item positions int xPos = 3, yPos = 3; for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); switch (item->item_style & CPM_ITEM_TYPEMASK) { case CPM_ITEM_ICONTEXT: { // TODO(toni): Implement! } case CPM_ITEM_TEXT: { LPCPM_ITEM_EXTRADATA_TEXT text_data = (LPCPM_ITEM_EXTRADATA_TEXT)item->item_extradata; if (!text_data->item_text) break; int text_x = xPos + 16, text_y = yPos + 3; // Selecting the correct font to draw SelectObject( hdc, (item->item_style & CPM_ITEM_DEFAULT) ? popup->menu_item_font_default : popup->menu_item_font ); if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_SELECTED) { context.fill_color = 0x800000; context.draw_color = 0xFFFFFF; CDrawUtils::FillSolidRectangle( &context, xPos, yPos, popup->menu_size.cx - 6, item->item_size.cy ); } else if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_DISABLED) { context.fill_color = CLASSIC_DEFAULT_BASECOLOR; context.draw_color = 0xFFFFFF; CDrawUtils::DrawString( &context, text_data->item_text, text_x + 1, text_y + 1 ); context.draw_color = 0x848284; } else { context.fill_color = CLASSIC_DEFAULT_BASECOLOR; context.draw_color = 0x000000; } SetBkMode(hdc, TRANSPARENT); CDrawUtils::DrawString( &context, text_data->item_text, text_x, text_y ); SetBkMode(hdc, OPAQUE); } break; case CPM_ITEM_SEPARATOR: { context.fill_color = 0x848284; CDrawUtils::FillSolidRectangle(&context, xPos + 1, yPos + 3, popup->menu_size.cx - 8, 1); context.fill_color = 0xFFFFFF; CDrawUtils::FillSolidRectangle(&context, xPos + 1, yPos + 4, popup->menu_size.cx - 8, 1); } break; default: break; // We should never even get here } yPos += item->item_size.cy; } EndPaint(hWnd, &paintstruct); } break; case WM_MOUSEMOVE: { int mx = (int)((short)LOWORD(lParam)), my = (int)((short)HIWORD(lParam)); // Initial item positions int xPos = 3, yPos = 3; bool flags_changed = false; RECT rect_deselected = { 0, 0, 0, 0 }, rect_selected = { 0, 0, 0, 0 }; for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); // Skipping Separators and disabled items... if (((item->item_style & CPM_ITEM_TYPEMASK) == CPM_ITEM_SEPARATOR) || ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_DISABLED)) { yPos += item->item_size.cy; continue; } if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_SELECTED) { // Remember: Border is 3 pixels, and width always means "double the value dude!" if (!IsPointInArea(mx, my, xPos, yPos, popup->menu_size.cx - 6, item->item_size.cy)) { // If previous items are still selected, // even though the mouse isn't over it anymore, // just deselect them item->item_style &= ~CPM_ITEM_STATE_SELECTED; // Marking the area that has to be redrawn // // NOTE(toni): There only should ever be exactly // 1 menu item selected at the same time. // So we only have to care about this one area. rect_deselected.left = xPos; rect_deselected.top = yPos; rect_deselected.right = MAKECOORDINATE(xPos, popup->menu_size.cx - 6); rect_deselected.bottom = MAKECOORDINATE(yPos, item->item_size.cy); flags_changed = true; } } else { if (IsPointInArea(mx, my, xPos, yPos, popup->menu_size.cx - 6, item->item_size.cy)) { // Select the current item item->item_style |= CPM_ITEM_STATE_SELECTED; // Marking the area that has to be redrawn rect_selected.left = xPos; rect_selected.top = yPos; rect_selected.right = MAKECOORDINATE(xPos, popup->menu_size.cx - 6); rect_selected.bottom = MAKECOORDINATE(yPos, item->item_size.cy); flags_changed = true; } } yPos += item->item_size.cy; } if (flags_changed) { if ((rect_deselected.left > 0) && (rect_deselected.top > 0) && (rect_deselected.right > 0) && (rect_deselected.bottom > 0)) RedrawWindow(hWnd, &rect_deselected, NULL, RDW_INVALIDATE); if ((rect_selected.left > 0) && (rect_selected.top > 0) && (rect_selected.right > 0) && (rect_selected.bottom > 0)) RedrawWindow(hWnd, &rect_selected, NULL, RDW_INVALIDATE); } } break; case WM_LBUTTONUP: case WM_RBUTTONUP: { for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_SELECTED) { // Notify the menu procedure (if there is one) // that the user clicked on a menu item! if (popup->menu_proc) { CPM_ITEMINFO info = { item, i }; popup->menu_proc(popup, CPM_ITEMSELECTED, &info); } DestroyWindow(hWnd); break; } } } break; case WM_ACTIVATE: { // If our little popup menu gets thrown into the background // just destroy it... if (!wParam) DestroyWindow(hWnd); } break; case WM_DESTROY: { // Before we deallocate, we have to notify the Menu Procedure. // Because maybe the user wants to access the Menu items // before they're gone. // (if there even is one) if (popup->menu_proc) popup->menu_proc(popup, CPM_DESTROY, NULL); // Destroying all the Menu items // we don't need them anymore after this popup menu has been closed. for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); DestroyMenuItem(item); } PostQuitMessage(0); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
DWORD WINAPI PopupWorker(LPVOID param) { HPOPUP popup = (HPOPUP)param; if (!List_GetCount(popup->menu_items)) { // If there have no menu items been inserted yet // just fail the call and close everything immediately DBG_ErrorExit("Popup Menu creation - No menu items!"); return 1; } popup->menu_wndclass.style = (CS_HREDRAW | CS_VREDRAW); popup->menu_wndclass.lpfnWndProc = Internal_WndProc; popup->menu_wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); popup->menu_wndclass.lpszClassName = GenerateNewClassName(TEXT("Classic_Popup")); if (!RegisterClass(&popup->menu_wndclass)) { DBG_ErrorExit("Popup Menu creation (In Worker thread)"); return 1; } POINT mpos; if (!GetCursorPos(&mpos)) { DBG_ErrorExit("Popup Menu creation - Unable to retrieve cursor positon!"); return 1; } int popup_w = 0, popup_h = 0; for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); // Compute the absolute size of our popup menu if (popup_w < item->item_size.cx) popup_w = item->item_size.cx; popup_h += item->item_size.cy; } // Adding some extra pixels // Think about the border too! popup_w += 19; // Suffix Icon Size (16 x 16) + Border Width (3) popup_h += 7; // Menu Item Extra pixels from bottom + 3 pixels for border popup->menu_wnd = CreateWindowEx( WS_EX_TOOLWINDOW, popup->menu_wndclass.lpszClassName, NULL, WS_POPUP, mpos.x, mpos.y, popup_w, popup_h, NULL, NULL, popup->menu_wndclass.hInstance, NULL ); popup->menu_size.cx = popup_w; popup->menu_size.cy = popup_h; if (!popup->menu_wnd) { DBG_ErrorExit("Popup Menu HWND creation (In Worker thread)"); return 1; } // Gotta give the WndProc access to our popup struct SetWindowLong(popup->menu_wnd, GWLP_USERDATA, (long)popup); if (popup->menu_proc) popup->menu_proc(popup, CPM_CREATE, NULL); ShowWindow(popup->menu_wnd, SW_SHOW); UpdateWindow(popup->menu_wnd); if (popup->menu_proc) popup->menu_proc(popup, CPM_SHOW, NULL); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } DeleteObject(popup->menu_item_font); DeleteObject(popup->menu_item_font_default); // Unregister our Window class since we won't ever use it anymore UnregisterClass( popup->menu_wndclass.lpszClassName, popup->menu_wndclass.hInstance ); CloseHandle(popup->worker_thread_handle); free(popup); // Freeing the Popup handle return 0; }
void *parse (void * context) { void (*_edge_fn) (char *from, char *to) = context; char *url, *page; node_t *entry; while (!areQueuesEmpty ()) { //critical section: dequeue page from shared unbounded queue acting as consumer //printf("in parser\n"); pthread_mutex_lock(&lock2); while (List_Empty(queue_pages)) pthread_cond_wait (&fill_unbounded, &lock2); entry = List_Get (queue_pages); pthread_mutex_unlock(&lock2); url = entry->key; page = entry->val; //printf("parsing %s\n",url); //core logic for parsing a page char *save_ptr1, *token; char *delim = " \n\t"; regex_t regex; char *expr = "^link:.*"; int reti = regcomp (®ex, expr, 0); if (reti) { //printf (stderr, "Could not compile regex\n"); exit (1); } char *str1 = page; int has_atleast_a_link = 0; for (;; str1 = NULL) { token = strtok_r (str1, delim, &save_ptr1); if (token != NULL) { if (!(regexec (®ex, token, 0, NULL, 0)) && strlen(token)>5) { //printf ("%s matched: %s len=%d\n", url,token, (int) strlen (token)); char *addr = strndup (token + 5, (int) strlen (token) - 5); //critical section: insert into shared bounded queue acting as producer pthread_mutex_lock (&lock1); while (count == QUEUE_SIZE) pthread_cond_wait (&empty, &lock1); //check if url is not already visited pthread_mutex_unlock (&lock1); _edge_fn(url,addr); pthread_mutex_lock (&lock1); if(lookup_string(urls, addr)==NULL){ has_atleast_a_link = 1; add_string(urls, addr); put(addr); pthread_mutex_lock(&glock); sum_queue_lengths++; pthread_mutex_unlock(&glock); //_edge_fn(url,addr); pthread_cond_signal (&fill); } pthread_mutex_unlock (&lock1); } } else break; } pthread_mutex_lock(&glock); sum_queue_lengths--; pthread_mutex_unlock(&glock); /* if (has_atleast_a_link == 0) { pthread_mutex_lock (&glock); sum_queue_lengths--; pthread_mutex_unlock (&glock); } */ } thr_exit (); //printf("parser thread exiting\n"); return NULL; }